diff options
Diffstat (limited to 'qlparser')
146 files changed, 31559 insertions, 0 deletions
diff --git a/qlparser/Makefile.am b/qlparser/Makefile.am new file mode 100644 index 0000000..7638cea --- /dev/null +++ b/qlparser/Makefile.am @@ -0,0 +1,93 @@ +# -*-Makefile-*- (for Emacs) +# +# 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 <http://www.gnu.org/licenses/>. +# +# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +# rasdaman GmbH. +# +# For more information please see <http://www.rasdaman.org> +# or contact Peter Baumann via <baumann@rasdaman.com>. +# +# MAKEFILE FOR: +# module qlparser +# +# +# COMMENTS: +# +# +################################################################## + +noinst_LIBRARIES=libqlparser.a + +# -I gnererates an interactive scanner which doesn't try to look ahead past a newline +# -i generates a scanner which doesn't care about upper and lower case; doesn't work +AM_LFLAGS=-i -I + +YACC = bison +# -d generates token definitions in .h file +AM_YFLAGS=-d -y +AM_CXXFLAGS=@BASEDBCXXFLAGS@ +AM_CFLAGS=$(CXXFLAGS) +libqlparser_a_SOURCES=oql.yy lex.ll alloca.c\ + symtab.cc symtab.hh \ + qtoncstream.cc qtoncstream.hh qtoncstream.icc \ + qtmddaccess.cc qtmddaccess.hh qtmddaccess.icc \ + qtiterator.cc qtiterator.hh qtiterator.icc \ + qtoperationiterator.cc qtoperationiterator.hh qtoperationiterator.icc \ + qtselectioniterator.cc qtselectioniterator.hh qtselectioniterator.icc \ + qtjoiniterator.cc qtjoiniterator.hh qtjoiniterator.icc \ + qtoperation.cc qtoperation.hh qtoperation.icc \ + qtbinaryoperation.cc qtbinaryoperation.hh qtbinaryoperation.icc \ + qtbinaryinduce.cc qtbinaryinduce.hh qtbinaryinduce.icc \ + qtbinaryinduce2.cc qtbinaryinduce2.hh qtbinaryinduce2.icc \ + qtunaryoperation.cc qtunaryoperation.hh qtunaryoperation.icc \ + qtunaryinduce.cc qtunaryinduce.hh qtunaryinduce.icc \ + qtvariable.cc qtvariable.hh qtvariable.icc \ + qtconst.cc qtconst.hh qtconst.icc \ + qtdata.cc qtdata.hh qtdata.icc \ + qtscalardata.cc qtscalardata.hh qtscalardata.icc \ + qtatomicdata.cc qtatomicdata.hh qtatomicdata.icc \ + qtcomplexdata.cc qtcomplexdata.hh qtcomplexdata.icc \ + qtmdd.cc qtmdd.hh qtmdd.icc \ + qtstringdata.cc qtstringdata.hh qtstringdata.icc \ + qtcondense.cc qtcondense.hh qtcondense.icc \ + parseinfo.cc parseinfo.hh parseinfo.icc \ + qtdomainoperation.cc qtdomainoperation.hh qtdomainoperation.icc \ + qtconversion.cc qtconversion.hh qtconversion.icc\ + qtupdate.cc qtupdate.hh qtupdate.icc \ + qtinsert.cc qtinsert.hh qtinsert.icc \ + qtdelete.cc qtdelete.hh \ + qtcommand.cc qtcommand.hh qtcommand.icc \ + qtoid.cc qtoid.hh qtoid.icc\ + qtintervalop.cc qtintervalop.hh qtintervalop.icc \ + qtmintervalop.cc qtmintervalop.hh qtmintervalop.icc \ + qtintervaldata.cc qtintervaldata.hh qtintervaldata.icc \ + qtpointop.cc qtpointop.hh qtpointop.icc \ + qtmintervaldata.cc qtmintervaldata.hh qtmintervaldata.icc \ + qtpointdata.cc qtpointdata.hh qtpointdata.icc \ + qtnaryoperation.cc qtnaryoperation.hh qtnaryoperation.icc \ + qtunaryfunc.cc qtunaryfunc.hh qtunaryfunc.icc \ + qtbinaryfunc.cc qtbinaryfunc.hh qtbinaryfunc.icc \ + qtmarrayop.cc qtmarrayop.hh qtmarrayop.icc \ + qtmarrayop2.cc qtmarrayop2.hh qtmarrayop2.icc \ + qtcondenseop.cc qtcondenseop.hh qtcondenseop.icc \ + qtnode.cc qtnode.hh qtnode.icc \ + querytree.cc querytree.hh querytree.icc \ + qtexecute.hh qtdelete.icc +EXTRA_libqlparser_a_SOURCES = autogen_qtui.hh autogen_qtui.icc autogen_qtui.cc + +BUILT_SOURCES=lex.cc oql.cc oql.h +CLEANFILES=lex.cc oql.cc oql.h diff --git a/qlparser/alloca.c b/qlparser/alloca.c new file mode 100644 index 0000000..d9a7ba2 --- /dev/null +++ b/qlparser/alloca.c @@ -0,0 +1,531 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#include "mymalloc/mymalloc.h" +/* alloca.c -- allocate automatically reclaimed memory + (Mostly) portable public-domain implementation -- D A Gwyn + + This implementation of the PWB library alloca function, + which is used to allocate space off the run-time stack so + that it is automatically reclaimed upon procedure exit, + was inspired by discussions with J. Q. Johnson of Cornell. + J.Otto Tennant <jot@cray.com> contributed the Cray support. + + There are some preprocessor constants that can + be defined when compiling for your specific system, for + improved efficiency; however, the defaults should be okay. + + The general concept of this implementation is to keep + track of all alloca-allocated blocks, and reclaim any + that are found to be deeper in the stack than the current + invocation. This heuristic does not reclaim storage as + soon as it becomes invalid, but it will do so eventually. + + As a special case, alloca(0) reclaims storage without + allocating any. It is a good idea to use alloca(0) in + your main control loop, etc. to force garbage collection. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#endif +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#endif + +#ifdef emacs +#include "blockinput.h" +#endif + +/* If compiling with GCC 2, this file's not needed. */ +#if !defined (__GNUC__) || __GNUC__ < 2 +#ifndef SOLARIS + +/* If someone has defined alloca as a macro, + there must be some other way alloca is supposed to work. */ +#ifndef alloca + +#ifdef emacs +#ifdef static +/* actually, only want this if static is defined as "" + -- this is for usg, in which emacs must undefine static + in order to make unexec workable + */ +#ifndef STACK_DIRECTION +you +lose +-- must know STACK_DIRECTION at compile-time +#endif /* STACK_DIRECTION undefined */ +#endif /* static */ +#endif /* emacs */ + +/* If your stack is a linked list of frames, you have to + provide an "address metric" ADDRESS_FUNCTION macro. */ + +#if defined (CRAY) && defined (CRAY_STACKSEG_END) +long i00afunc (); +#define ADDRESS_FUNCTION(arg) (char *) i00afunc (&(arg)) +#else +#define ADDRESS_FUNCTION(arg) &(arg) +#endif + +#if __STDC__ +typedef void *pointer; +#else +typedef char *pointer; +#endif + +#ifndef NULL +#define NULL 0 +#endif + +/* Different portions of Emacs need to call different versions of + malloc. The Emacs executable needs alloca to call xmalloc, because + ordinary malloc isn't protected from input signals. On the other + hand, the utilities in lib-src need alloca to call malloc; some of + them are very simple, and don't have an xmalloc routine. + + Non-Emacs programs expect this to call use xmalloc. + + Callers below should use malloc. */ + +/* +#ifndef emacs +#define malloc xmalloc +#endif +*/ +extern pointer mymalloc (); + +/* Define STACK_DIRECTION if you know the direction of stack + growth for your system; otherwise it will be automatically + deduced at run-time. + + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ + +#ifndef STACK_DIRECTION +#define STACK_DIRECTION 0 /* Direction unknown. */ +#endif + +#if STACK_DIRECTION != 0 + +#define STACK_DIR STACK_DIRECTION /* Known at compile-time. */ + +#else /* STACK_DIRECTION == 0; need run-time code. */ + +static int stack_dir; /* 1 or -1 once known. */ +#define STACK_DIR stack_dir + +static void +find_stack_direction () +{ + static char *addr = NULL; /* Address of first `dummy', once known. */ + auto char dummy; /* To get stack address. */ + + if (addr == NULL) + { /* Initial entry. */ + addr = ADDRESS_FUNCTION (dummy); + + find_stack_direction (); /* Recurse once. */ + } + else + { + /* Second entry. */ + if (ADDRESS_FUNCTION (dummy) > addr) + stack_dir = 1; /* Stack grew upward. */ + else + stack_dir = -1; /* Stack grew downward. */ + } +} + +#endif /* STACK_DIRECTION == 0 */ + +/* An "alloca header" is used to: + (a) chain together all alloca'ed blocks; + (b) keep track of stack depth. + + It is very important that sizeof(header) agree with malloc + alignment chunk size. The following default should work okay. */ + +#ifndef ALIGN_SIZE +#define ALIGN_SIZE sizeof(double) +#endif + +typedef union hdr +{ + char align[ALIGN_SIZE]; /* To force sizeof(header). */ + struct + { + union hdr *next; /* For chaining headers. */ + char *deep; /* For stack depth measure. */ + } h; +} header; + +static header *last_alloca_header = NULL; /* -> last alloca header. */ + +/* Return a pointer to at least SIZE bytes of storage, + which will be automatically reclaimed upon exit from + the procedure that called alloca. Originally, this space + was supposed to be taken from the current stack frame of the + caller, but that method cannot be made to work for some + implementations of C, for example under Gould's UTX/32. */ + +pointer +alloca (size) + unsigned size; +{ + auto char probe; /* Probes stack depth: */ + register char *depth = ADDRESS_FUNCTION (probe); + +#if STACK_DIRECTION == 0 + if (STACK_DIR == 0) /* Unknown growth direction. */ + find_stack_direction (); +#endif + + /* Reclaim garbage, defined as all alloca'd storage that + was allocated from deeper in the stack than currently. */ + + { + register header *hp; /* Traverses linked list. */ + +#ifdef emacs + BLOCK_INPUT; +#endif + + for (hp = last_alloca_header; hp != NULL;) + if ((STACK_DIR > 0 && hp->h.deep > depth) + || (STACK_DIR < 0 && hp->h.deep < depth)) + { + register header *np = hp->h.next; + + free ((pointer) hp); /* Collect garbage. */ + + hp = np; /* -> next header. */ + } + else + break; /* Rest are not deeper. */ + + last_alloca_header = hp; /* -> last valid storage. */ + +#ifdef emacs + UNBLOCK_INPUT; +#endif + } + + if (size == 0) + return NULL; /* No allocation required. */ + + /* Allocate combined header + user data storage. */ + + { + register pointer new = mymalloc (sizeof (header) + size); + /* Address of header. */ + + if (new == 0) + abort(); + + ((header *) new)->h.next = last_alloca_header; + ((header *) new)->h.deep = depth; + + last_alloca_header = (header *) new; + + /* User storage begins just after header. */ + + return (pointer) ((char *) new + sizeof (header)); + } +} + +#if defined (CRAY) && defined (CRAY_STACKSEG_END) + +#ifdef DEBUG_I00AFUNC +#include <stdio.h> +#endif + +#ifndef CRAY_STACK +#define CRAY_STACK +#ifndef CRAY2 +/* Stack structures for CRAY-1, CRAY X-MP, and CRAY Y-MP */ +struct stack_control_header + { + long shgrow:32; /* Number of times stack has grown. */ + long shaseg:32; /* Size of increments to stack. */ + long shhwm:32; /* High water mark of stack. */ + long shsize:32; /* Current size of stack (all segments). */ + }; + +/* The stack segment linkage control information occurs at + the high-address end of a stack segment. (The stack + grows from low addresses to high addresses.) The initial + part of the stack segment linkage control information is + 0200 (octal) words. This provides for register storage + for the routine which overflows the stack. */ + +struct stack_segment_linkage + { + long ss[0200]; /* 0200 overflow words. */ + long sssize:32; /* Number of words in this segment. */ + long ssbase:32; /* Offset to stack base. */ + long:32; + long sspseg:32; /* Offset to linkage control of previous + segment of stack. */ + long:32; + long sstcpt:32; /* Pointer to task common address block. */ + long sscsnm; /* Private control structure number for + microtasking. */ + long ssusr1; /* Reserved for user. */ + long ssusr2; /* Reserved for user. */ + long sstpid; /* Process ID for pid based multi-tasking. */ + long ssgvup; /* Pointer to multitasking thread giveup. */ + long sscray[7]; /* Reserved for Cray Research. */ + long ssa0; + long ssa1; + long ssa2; + long ssa3; + long ssa4; + long ssa5; + long ssa6; + long ssa7; + long sss0; + long sss1; + long sss2; + long sss3; + long sss4; + long sss5; + long sss6; + long sss7; + }; + +#else /* CRAY2 */ +/* The following structure defines the vector of words + returned by the STKSTAT library routine. */ +struct stk_stat + { + long now; /* Current total stack size. */ + long maxc; /* Amount of contiguous space which would + be required to satisfy the maximum + stack demand to date. */ + long high_water; /* Stack high-water mark. */ + long overflows; /* Number of stack overflow ($STKOFEN) calls. */ + long hits; /* Number of internal buffer hits. */ + long extends; /* Number of block extensions. */ + long stko_mallocs; /* Block allocations by $STKOFEN. */ + long underflows; /* Number of stack underflow calls ($STKRETN). */ + long stko_free; /* Number of deallocations by $STKRETN. */ + long stkm_free; /* Number of deallocations by $STKMRET. */ + long segments; /* Current number of stack segments. */ + long maxs; /* Maximum number of stack segments so far. */ + long pad_size; /* Stack pad size. */ + long current_address; /* Current stack segment address. */ + long current_size; /* Current stack segment size. This + number is actually corrupted by STKSTAT to + include the fifteen word trailer area. */ + long initial_address; /* Address of initial segment. */ + long initial_size; /* Size of initial segment. */ + }; + +/* The following structure describes the data structure which trails + any stack segment. I think that the description in 'asdef' is + out of date. I only describe the parts that I am sure about. */ + +struct stk_trailer + { + long this_address; /* Address of this block. */ + long this_size; /* Size of this block (does not include + this trailer). */ + long unknown2; + long unknown3; + long link; /* Address of trailer block of previous + segment. */ + long unknown5; + long unknown6; + long unknown7; + long unknown8; + long unknown9; + long unknown10; + long unknown11; + long unknown12; + long unknown13; + long unknown14; + }; + +#endif /* CRAY2 */ +#endif /* not CRAY_STACK */ + +#ifdef CRAY2 +/* Determine a "stack measure" for an arbitrary ADDRESS. + I doubt that "lint" will like this much. */ + +static long +i00afunc (long *address) +{ + struct stk_stat status; + struct stk_trailer *trailer; + long *block, size; + long result = 0; + + /* We want to iterate through all of the segments. The first + step is to get the stack status structure. We could do this + more quickly and more directly, perhaps, by referencing the + $LM00 common block, but I know that this works. */ + + STKSTAT (&status); + + /* Set up the iteration. */ + + trailer = (struct stk_trailer *) (status.current_address + + status.current_size + - 15); + + /* There must be at least one stack segment. Therefore it is + a fatal error if "trailer" is null. */ + + if (trailer == 0) + abort (); + + /* Discard segments that do not contain our argument address. */ + + while (trailer != 0) + { + block = (long *) trailer->this_address; + size = trailer->this_size; + if (block == 0 || size == 0) + abort (); + trailer = (struct stk_trailer *) trailer->link; + if ((block <= address) && (address < (block + size))) + break; + } + + /* Set the result to the offset in this segment and add the sizes + of all predecessor segments. */ + + result = address - block; + + if (trailer == 0) + { + return result; + } + + do + { + if (trailer->this_size <= 0) + abort (); + result += trailer->this_size; + trailer = (struct stk_trailer *) trailer->link; + } + while (trailer != 0); + + /* We are done. Note that if you present a bogus address (one + not in any segment), you will get a different number back, formed + from subtracting the address of the first block. This is probably + not what you want. */ + + return (result); +} + +#else /* not CRAY2 */ +/* Stack address function for a CRAY-1, CRAY X-MP, or CRAY Y-MP. + Determine the number of the cell within the stack, + given the address of the cell. The purpose of this + routine is to linearize, in some sense, stack addresses + for alloca. */ + +static long +i00afunc (long address) +{ + long stkl = 0; + + long size, pseg, this_segment, stack; + long result = 0; + + struct stack_segment_linkage *ssptr; + + /* Register B67 contains the address of the end of the + current stack segment. If you (as a subprogram) store + your registers on the stack and find that you are past + the contents of B67, you have overflowed the segment. + + B67 also points to the stack segment linkage control + area, which is what we are really interested in. */ + + stkl = CRAY_STACKSEG_END (); + ssptr = (struct stack_segment_linkage *) stkl; + + /* If one subtracts 'size' from the end of the segment, + one has the address of the first word of the segment. + + If this is not the first segment, 'pseg' will be + nonzero. */ + + pseg = ssptr->sspseg; + size = ssptr->sssize; + + this_segment = stkl - size; + + /* It is possible that calling this routine itself caused + a stack overflow. Discard stack segments which do not + contain the target address. */ + + while (!(this_segment <= address && address <= stkl)) + { +#ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o %011o\n", this_segment, address, stkl); +#endif + if (pseg == 0) + break; + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + this_segment = stkl - size; + } + + result = address - this_segment; + + /* If you subtract pseg from the current end of the stack, + you get the address of the previous stack segment's end. + This seems a little convoluted to me, but I'll bet you save + a cycle somewhere. */ + + while (pseg != 0) + { +#ifdef DEBUG_I00AFUNC + fprintf (stderr, "%011o %011o\n", pseg, size); +#endif + stkl = stkl - pseg; + ssptr = (struct stack_segment_linkage *) stkl; + size = ssptr->sssize; + pseg = ssptr->sspseg; + result += size; + } + return (result); +} + +#endif /* not CRAY2 */ +#endif /* CRAY */ + +#endif /* no alloca */ +#endif /* no solaris */ +#endif /* not GCC version 2 */ diff --git a/qlparser/autogen_qtui.cc b/qlparser/autogen_qtui.cc new file mode 100644 index 0000000..408fed3 --- /dev/null +++ b/qlparser/autogen_qtui.cc @@ -0,0 +1,1151 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: Automaticaly generated + * + ************************************************************/ + + +const QtNode::QtNodeType QtAbs::nodeType = QtNode::QT_ABS; + +QtAbs::QtAbs(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtAbs::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_ABS ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtAbs::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtAbsObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} + +void QtAbs::printAlgebraicExpression(ostream& s) { + s << "abs("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtAbs::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtAbs", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_ABS, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtAbs::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_ABS, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtAbs::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtAbs::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtAbs::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtSqrt::nodeType = QtNode::QT_SQRT; + +QtSqrt::QtSqrt(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtSqrt::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_SQRT ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtSqrt::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtSqrtObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtSqrt::printAlgebraicExpression(ostream& s) { + s << "sqrt("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtSqrt::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtSqrt", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_SQRT, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtSqrt::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_SQRT, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtSqrt::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtSqrt::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtSqrt::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtExp::nodeType = QtNode::QT_EXP; + +QtExp::QtExp(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtExp::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_EXP ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtExp::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtExpObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtExp::printAlgebraicExpression(ostream& s) { + s << "exp("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtExp::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtExp", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_EXP, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtExp::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_EXP, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtExp::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtExp::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtExp::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtLog::nodeType = QtNode::QT_LOG; + +QtLog::QtLog(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtLog::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_LOG ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtLog::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtLogObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtLog::printAlgebraicExpression(ostream& s) { + s << "log("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtLog::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtLog", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_LOG, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtLog::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_LOG, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtLog::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtLog::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtLog::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtLn::nodeType = QtNode::QT_LN; + +QtLn::QtLn(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtLn::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_LN ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtLn::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtLnObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtLn::printAlgebraicExpression(ostream& s) { + s << "ln("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtLn::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtLn", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_LN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtLn::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_LN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtLn::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtLn::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtLn::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtSin::nodeType = QtNode::QT_SIN; + +QtSin::QtSin(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtSin::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_SIN ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtSin::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtSinObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtSin::printAlgebraicExpression(ostream& s) { + s << "sin("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtSin::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtSin", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_SIN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtSin::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_SIN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtSin::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtSin::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtSin::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtCos::nodeType = QtNode::QT_COS; + +QtCos::QtCos(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtCos::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_COS ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtCos::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtCosObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtCos::printAlgebraicExpression(ostream& s) { + s << "cos("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtCos::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtCos", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_COS, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtCos::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_COS, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtCos::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtCos::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtCos::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtTan::nodeType = QtNode::QT_TAN; + +QtTan::QtTan(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtTan::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_TAN ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtTan::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtTanObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtTan::printAlgebraicExpression(ostream& s) { + s << "tan("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtTan::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtTan", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_TAN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtTan::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_TAN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtTan::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtTan::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtTan::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtSinh::nodeType = QtNode::QT_SINH; + +QtSinh::QtSinh(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtSinh::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_SINH ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtSinh::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtSinhObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtSinh::printAlgebraicExpression(ostream& s) { + s << "sinh("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtSinh::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtSinh", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_SINH, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtSinh::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_SINH, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtSinh::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtSinh::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtSinh::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtCosh::nodeType = QtNode::QT_COSH; + +QtCosh::QtCosh(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtCosh::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_COSH ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtCosh::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtCoshObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtCosh::printAlgebraicExpression(ostream& s) { + s << "cosh("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtCosh::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtCosh", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_COSH, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtCosh::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_COSH, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtCosh::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtCosh::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtCosh::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtTanh::nodeType = QtNode::QT_TANH; + +QtTanh::QtTanh(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtTanh::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_TANH ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtTanh::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtTanhObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtTanh::printAlgebraicExpression(ostream& s) { + s << "tanh("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtTanh::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtTanh", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_TANH, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtTanh::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_TANH, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtTanh::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtTanh::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtTanh::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +const QtNode::QtNodeType QtArcsin::nodeType = QtNode::QT_ARCSIN; + +QtArcsin::QtArcsin(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtArcsin::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_ARCSIN ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtArcsin::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtArcsinObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtArcsin::printAlgebraicExpression(ostream& s) { + s << "arcsin("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtArcsin::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtArcsin", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_ARCSIN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtArcsin::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_ARCSIN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtArcsin::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtArcsin::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtArcsin::checkType() - operand branch invalid." << endl; + return dataStreamType; +} + +const QtNode::QtNodeType QtArccos::nodeType = QtNode::QT_ARCCOS; + +QtArccos::QtArccos(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtArccos::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_ARCCOS ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtArccos::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtArccosObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} +void QtArccos::printAlgebraicExpression(ostream& s) { + s << "arccos("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtArccos::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtArccos", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_ARCCOS, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtArccos::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_ARCCOS, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtArccos::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtArccos::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtArccos::checkType() - operand branch invalid." << endl; + return dataStreamType; +} + +const QtNode::QtNodeType QtArctan::nodeType = QtNode::QT_ARCTAN; + +QtArctan::QtArctan(QtOperation* initInput): QtUnaryInduce(initInput) {} +QtData* QtArctan::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) { + try { + returnValue = computeOp( operand, Ops::OP_ARCTAN ); + } + catch(...) { + operand->deleteRef(); + throw; + } + } + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtArctan::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtArctanObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} + +void QtArctan::printAlgebraicExpression(ostream& s) { + s << "arctan("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtArctan::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtArctan", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + // check operand branches + if(input) + { + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "AutoGen", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_ARCTAN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtArctan::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_ARCTAN, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtArctan::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtArctan::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtArctan::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + diff --git a/qlparser/autogen_qtui.hh b/qlparser/autogen_qtui.hh new file mode 100644 index 0000000..f3ce42d --- /dev/null +++ b/qlparser/autogen_qtui.hh @@ -0,0 +1,296 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: Automaticaly generated + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtAbs : public QtUnaryInduce { +public: + QtAbs(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtSqrt : public QtUnaryInduce { +public: + QtSqrt(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtExp : public QtUnaryInduce { +public: + QtExp(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtLog : public QtUnaryInduce { +public: + QtLog(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtLn : public QtUnaryInduce { +public: + QtLn(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtSin : public QtUnaryInduce { +public: + QtSin(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtCos : public QtUnaryInduce { +public: + QtCos(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtTan : public QtUnaryInduce { +public: + QtTan(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtSinh : public QtUnaryInduce { +public: + QtSinh(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtCosh : public QtUnaryInduce { +public: + QtCosh(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtTanh : public QtUnaryInduce { +public: + QtTanh(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtArcsin : public QtUnaryInduce { +public: + QtArcsin(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtArccos : public QtUnaryInduce { +public: + QtArccos(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtArctan : public QtUnaryInduce { +public: + QtArctan(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES ); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + static const QtNodeType nodeType; +}; + diff --git a/qlparser/autogen_qtui.icc b/qlparser/autogen_qtui.icc new file mode 100644 index 0000000..0a339a8 --- /dev/null +++ b/qlparser/autogen_qtui.icc @@ -0,0 +1,44 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: Automaticaly generated + * + ************************************************************/ + + +inline const QtNode::QtNodeType QtAbs::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtSqrt::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtExp::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtLog::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtLn::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtSin::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtCos::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtTan::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtSinh::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtCosh::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtTanh::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtArcsin::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtArccos::getNodeType() const { return nodeType; } +inline const QtNode::QtNodeType QtArctan::getNodeType() const { return nodeType; } diff --git a/qlparser/lex.ll b/qlparser/lex.ll new file mode 100644 index 0000000..8a1b140 --- /dev/null +++ b/qlparser/lex.ll @@ -0,0 +1,354 @@ +%{ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * COMMENTS: + * - token BY seems unused + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, lexer: $Id: oql.l,v 1.64 2005/07/06 22:48:34 rasdev Exp $"; + +#include "qlparser/qtoperation.hh" +#include "qlparser/querytree.hh" +#include "qlparser/qtmddaccess.hh" +#include "qlparser/qtcomplexdata.hh" +#include "qlparser/qtiterator.hh" +#include "qlparser/qtunaryinduce.hh" + +std::list<ParseInfo> infoList; + +ParseInfo *currInfo=0; + +struct QtUpdateSpecElement +{ + QtOperation* iterator; + QtOperation* domain; +}; + +#include "oql.h" + +QueryTree* parseQueryTree = NULL; +char* beginParseString = NULL; +char* iterParseString = NULL; +void yyreset(); + +unsigned int lineNo = 1; +unsigned int columnNo = 1; +void llerror( char* s ); +int yyparse( ); + +int string_yyinput( char* buf, int max_size ) +{ + int lenParseString = strlen( iterParseString ); + int bufLength = max_size < lenParseString ? max_size : lenParseString; + if( bufLength > 0 ) + { + memcpy( buf, iterParseString, bufLength ); + iterParseString += bufLength; + } + return bufLength; +} + +#undef YY_INPUT +#define YY_INPUT( buff, buffLen, maxSize ) ( buffLen = string_yyinput( buff, maxSize ) ) + +#define SETTOKEN( TOKEN, TYPE, VALUE ) \ + yylval.TYPE.value = VALUE; \ + if(!infoList.empty()) { \ + currInfo = new ParseInfo(infoList.front()); \ + infoList.pop_front(); \ + } \ + else { \ + currInfo = new ParseInfo( yytext, lineNo, columnNo ); \ + } \ + yylval.TYPE.info = currInfo; \ + columnNo += yyleng; \ + parseQueryTree->addDynamicObject( yylval.TYPE.info ); \ + return TOKEN; + + +#define SETSTRTOKEN( TOKEN, TYPE, VALUE ) \ + char* temp = strdup(VALUE); \ + parseQueryTree->addCString( temp ); \ + yylval.TYPE.value = temp; \ + if(!infoList.empty()) { \ + currInfo = new ParseInfo(infoList.front()); \ + infoList.pop_front(); \ + } \ + else { \ + currInfo = new ParseInfo( yytext, lineNo, columnNo ); \ + } \ + yylval.TYPE.info = currInfo; \ + columnNo += yyleng; \ + parseQueryTree->addDynamicObject( yylval.TYPE.info ); \ + return TOKEN; + + +#define SETINTTOKEN( VALUE, NEGATIVE, BYTES ) \ + yylval.integerToken.negative = NEGATIVE; \ + yylval.integerToken.bytes = BYTES; \ + if( NEGATIVE ) \ + yylval.integerToken.svalue = VALUE; \ + else \ + yylval.integerToken.uvalue = (unsigned long)VALUE; \ + if(!infoList.empty()) { \ + currInfo = new ParseInfo(infoList.front()); \ + infoList.pop_front(); \ + } \ + else { \ + currInfo = new ParseInfo( yytext, lineNo, columnNo ); \ + } \ + yylval.integerToken.info = currInfo; \ + columnNo += yyleng; \ + parseQueryTree->addDynamicObject( yylval.integerToken.info ); \ + return IntegerLit; + + +#define SETFLTTOKEN( VALUE, BYTES ) \ + yylval.floatToken.value = VALUE; \ + yylval.floatToken.bytes = BYTES; \ + if(!infoList.empty()) { \ + currInfo = new ParseInfo(infoList.front()); \ + infoList.pop_front(); \ + } \ + else { \ + currInfo = new ParseInfo(yytext, lineNo, columnNo); \ + } \ + yylval.floatToken.info = currInfo; \ + columnNo += yyleng; \ + parseQueryTree->addDynamicObject( yylval.floatToken.info ); \ + return FloatLit; + +%} + +%option noyywrap + +%% + +"/*""/"*([^*/]|[^*]"/"|"*"[^/])*"*"*"*/" { + if( !strncmp( yytext, "/*+", 3 ) ) + { + if( strstr( yytext, "opt 0" ) ) + parseQueryTree->setOptimizationLevel(0); + if( strstr( yytext, "opt 1" ) ) + parseQueryTree->setOptimizationLevel(1); + if( strstr( yytext, "opt 2" ) ) + parseQueryTree->setOptimizationLevel(2); + if( strstr( yytext, "opt 3" ) ) + parseQueryTree->setOptimizationLevel(3); + if( strstr( yytext, "opt 4" ) ) + parseQueryTree->setOptimizationLevel(4); + } + columnNo += yyleng; + } +"//".* { columnNo += yyleng; } +"--".* { columnNo += yyleng; } + +"[opt 0]" { parseQueryTree->setOptimizationLevel(0); columnNo += yyleng; } +"[opt 1]" { parseQueryTree->setOptimizationLevel(1); columnNo += yyleng; } +"[opt 2]" { parseQueryTree->setOptimizationLevel(2); columnNo += yyleng; } +"[opt 3]" { parseQueryTree->setOptimizationLevel(3); columnNo += yyleng; } +"[opt 4]" { parseQueryTree->setOptimizationLevel(4); columnNo += yyleng; } + +"complex" { SETTOKEN( COMPLEX, commandToken, COMPLEX ) } +"re" { SETTOKEN( RE, commandToken, RE ) } +"im" { SETTOKEN( IM, commandToken, IM ) } + +"struct" { SETTOKEN( STRCT, commandToken, STRCT ) } +"fastscale" { SETTOKEN( FASTSCALE, commandToken, FASTSCALE ) } +"members" { SETTOKEN( MEMBERS, commandToken, MEMBERS ) } +"add" { SETTOKEN( ADD, commandToken, ADD ) } +"alter" { SETTOKEN( ALTER, commandToken, ALTER ) } +"list" { SETTOKEN( LIST, commandToken, LIST ) } +"select" { SETTOKEN( SELECT, commandToken, SELECT ) } +"from" { SETTOKEN( FROM, commandToken, FROM ) } +"where" { SETTOKEN( WHERE, commandToken, WHERE ) } +"as" { SETTOKEN( AS, commandToken, AS ) } +"restrict" { SETTOKEN( RESTRICT, commandToken, RESTRICT ) } +"to" { SETTOKEN( TO, commandToken, TO ) } +"extend" { SETTOKEN( EXTEND, commandToken, EXTEND ) } +"by" { SETTOKEN( BY, commandToken, BY ) } +"project" { SETTOKEN( PROJECT, commandToken, PROJECT ) } +"at" { SETTOKEN( AT, commandToken, AT ) } +"dimension" { SETTOKEN( DIMENSION, commandToken, DIMENSION ) } +"all_cell"|"all_cells" { SETTOKEN( ALL, commandToken, ALL ) } +"some_cell"|"some_cells" { SETTOKEN( SOME, commandToken, SOME ) } +"count_cell"|"count_cells" { SETTOKEN( COUNTCELLS, commandToken, COUNTCELLS ) } +"add_cell"|"add_cells" { SETTOKEN( ADDCELLS, commandToken, ADDCELLS ) } +"avg_cell"|"avg_cells" { SETTOKEN( AVGCELLS, commandToken, AVGCELLS ) } +"min_cell"|"min_cells" { SETTOKEN( MINCELLS, commandToken, MINCELLS ) } +"max_cell"|"max_cells" { SETTOKEN( MAXCELLS, commandToken, MAXCELLS ) } +"sdom" { SETTOKEN( SDOM, commandToken, SDOM ) } +"over" { SETTOKEN( OVER, commandToken, OVER ) } +"overlay" { SETTOKEN( OVERLAY, commandToken, OVERLAY ) } +"using" { SETTOKEN( USING, commandToken, USING ) } +"lo" { SETTOKEN( LO, commandToken, LO ) } +"hi" { SETTOKEN( HI, commandToken, HI ) } + +"insert" { SETTOKEN( INSERT, commandToken, INSERT ) } +"into" { SETTOKEN( INTO, commandToken, INTO ) } +"values" { SETTOKEN( VALUES, commandToken, VALUES ) } +"delete" { SETTOKEN( DELETE, commandToken, DELETE ) } +"drop" { SETTOKEN( DROP, commandToken, DROP ) } +"create" { SETTOKEN( CREATE, commandToken, CREATE ) } +"collection" { SETTOKEN( COLLECTION, commandToken, COLLECTION ) } + +"update" { SETTOKEN( UPDATE, commandToken, UPDATE ) } +"set" { SETTOKEN( SET, commandToken, SET ) } +"assign" { SETTOKEN( ASSIGN, commandToken, ASSIGN ) } +"in" { SETTOKEN( IN, commandToken, IN ) } +"marray" { SETTOKEN( MARRAY, commandToken, MARRAY ) } +"condense" { SETTOKEN( CONDENSE, commandToken, CONDENSE ) } + +"oid" { SETTOKEN( OID, commandToken, OID ) } +"shift" { SETTOKEN( SHIFT, commandToken, SHIFT ) } +"scale" { SETTOKEN( SCALE, commandToken, SCALE ) } + +"." { SETTOKEN( DOT, commandToken, DOT ) } +"," { SETTOKEN( COMMA, commandToken, COMMA ) } +"is" { SETTOKEN( IS, commandToken, IS ) } +"not" { SETTOKEN( NOT, commandToken, NOT ) } +"sqrt" { SETTOKEN( SQRT, commandToken, SQRT ) } + +"tiff" { SETTOKEN( TIFF, commandToken, TIFF ) } +"bmp" { SETTOKEN( BMP, commandToken, BMP ) } +"hdf" { SETTOKEN( HDF, commandToken, HDF ) } +"jpeg" { SETTOKEN( JPEG, commandToken, JPEG ) } +"csv" { SETTOKEN( CSV, commandToken, CSV ) } +"png" { SETTOKEN( PNG, commandToken, PNG ) } +"vff" { SETTOKEN( VFF, commandToken, VFF ) } +"tor" { SETTOKEN( TOR, commandToken, TOR ) } +"dem" { SETTOKEN( DEM, commandToken, DEM ) } + +"inv_tiff" { SETTOKEN( INV_TIFF, commandToken, INV_TIFF ) } +"inv_bmp" { SETTOKEN( INV_BMP, commandToken, INV_BMP ) } +"inv_hdf" { SETTOKEN( INV_HDF, commandToken, INV_HDF ) } +"inv_jpeg" { SETTOKEN( INV_JPEG, commandToken, INV_JPEG ) } +"inv_csv" { SETTOKEN( INV_CSV, commandToken, INV_CSV ) } +"inv_png" { SETTOKEN( INV_PNG, commandToken, INV_PNG ) } +"inv_vff" { SETTOKEN( INV_VFF, commandToken, INV_VFF ) } +"inv_tor" { SETTOKEN( INV_TOR, commandToken, INV_TOR ) } +"inv_dem" { SETTOKEN( INV_DEM, commandToken, INV_DEM ) } + +"abs" { SETTOKEN( ABS, commandToken, ABS ) } +"exp" { SETTOKEN( EXP, commandToken, EXP ) } +"log" { SETTOKEN( LOG, commandToken, LOG ) } +"ln" { SETTOKEN( LN, commandToken, LN ) } +"sin" { SETTOKEN( SIN, commandToken, SIN ) } +"cos" { SETTOKEN( COS, commandToken, COS ) } +"tan" { SETTOKEN( TAN, commandToken, TAN ) } +"sinh" { SETTOKEN( SINH, commandToken, SINH ) } +"cosh" { SETTOKEN( COSH, commandToken, COSH ) } +"tanh" { SETTOKEN( TANH, commandToken, TANH ) } +"arcsin" { SETTOKEN( ARCSIN, commandToken, ARCSIN ) } +"arccos" { SETTOKEN( ARCCOS, commandToken, ARCCOS ) } +"arctan" { SETTOKEN( ARCTAN, commandToken, ARCTAN ) } + +"unsigned" { SETTOKEN( TUNSIG, typeToken, TUNSIG) } +"bool" { SETTOKEN( TBOOL, typeToken, TBOOL) } +"char" { SETTOKEN( TCHAR, typeToken, TCHAR) } +"octet" { SETTOKEN( TOCTET, typeToken, TOCTET) } +"short" { SETTOKEN( TSHORT, typeToken, TSHORT) } +"ushort" { SETTOKEN( TUSHORT, typeToken, TUSHORT) } +"long" { SETTOKEN( TLONG, typeToken, TLONG) } +"ulong" { SETTOKEN( TULONG, typeToken, TULONG) } +"float" { SETTOKEN( TFLOAT, typeToken, TFLOAT) } +"double" { SETTOKEN( TDOUBLE, typeToken, TDOUBLE) } + +"bit" { SETTOKEN( BIT, commandToken, BIT ) } +"and" { SETTOKEN( AND, commandToken, AND ) } +"or" { SETTOKEN( OR, commandToken, OR ) } +"xor" { SETTOKEN( XOR, commandToken, XOR ) } +"+" { SETTOKEN( PLUS, commandToken, PLUS ) } +"-" { SETTOKEN( MINUS, commandToken, MINUS ) } +"*" { SETTOKEN( MULT, commandToken, MULT ) } +"/" { SETTOKEN( DIV, commandToken, DIV ) } +"=" { SETTOKEN( EQUAL, commandToken, EQUAL ) } +"<" { SETTOKEN( LESS, commandToken, LESS ) } +">" { SETTOKEN( GREATER, commandToken, GREATER ) } +"<=" { SETTOKEN( LESSEQUAL, commandToken, LESSEQUAL ) } +">=" { SETTOKEN( GREATEREQUAL, commandToken, GREATEREQUAL ) } +"<>" { SETTOKEN( NOTEQUAL, commandToken, NOTEQUAL ) } +"!=" { SETTOKEN( NOTEQUAL, commandToken, NOTEQUAL ) } +":" { SETTOKEN( COLON, commandToken, COLON ) } +";" { SETTOKEN( SEMICOLON, commandToken, SEMICOLON ) } +"[" { SETTOKEN( LEPAR, commandToken, LEPAR ) } +"]" { SETTOKEN( REPAR, commandToken, REPAR ) } +"(" { SETTOKEN( LRPAR, commandToken, LRPAR ) } +")" { SETTOKEN( RRPAR, commandToken, RRPAR ) } +"{" { SETTOKEN( LCPAR, commandToken, LCPAR ) } +"}" { SETTOKEN( RCPAR, commandToken, RCPAR ) } +#MDD[0-9]+# { SETTOKEN( MDDPARAM, commandToken, atoi(&(yytext[1])) ) } +$[0-9]+ { llerror("unresolved query parameter"); columnNo++; } + +"true"|"false"|"TRUE"|"FALSE" { SETTOKEN( BooleanLit, booleanToken, yytext[0] == 't' || yytext[0] == 'T') } +[a-zA-Z_][a-zA-Z0-9_]* { SETSTRTOKEN( Identifier, identifierToken, yytext ) } +"'"[^']"'" { SETTOKEN( CharacterLit, characterToken, yytext[1] ) } +\"([^"]|\\["\n])*\" { + yytext[strlen(yytext)-1] = '\0'; + SETSTRTOKEN( StringLit, stringToken, &(yytext[1]) ) + } + +0x[0-f]+[cC] { SETINTTOKEN( strtoul( yytext, (char**)NULL, 16 ), 0, 1 ) } +0x[0-f]+"us"|"US" { SETINTTOKEN( strtoul( yytext, (char**)NULL, 16 ), 0, 2 ) } +0x[0-f]+"ul"|"UL" { SETINTTOKEN( strtoul( yytext, (char**)NULL, 16 ), 0, 4 ) } +-?0x[0-f]+[oO] { SETINTTOKEN( strtol ( yytext, (char**)NULL, 16 ), 1, 1 ) } +-?0x[0-f]+[sS] { SETINTTOKEN( strtol ( yytext, (char**)NULL, 16 ), 1, 2 ) } +-?0x[0-f]+[lL]? { SETINTTOKEN( strtol ( yytext, (char**)NULL, 16 ), 1, 4 ) } + +[0-9]+[cC] { SETINTTOKEN( strtoul( yytext, (char**)NULL, 10 ), 0, 1 ) } +[0-9]+"us"|"US" { SETINTTOKEN( strtoul( yytext, (char**)NULL, 10 ), 0, 2 ) } +[0-9]+"ul"|"UL" { SETINTTOKEN( strtoul( yytext, (char**)NULL, 10 ), 0, 4 ) } +-?[0-9]+[oO] { SETINTTOKEN( strtol ( yytext, (char**)NULL, 10 ), 1, 1 ) } +-?[0-9]+[sS] { SETINTTOKEN( strtol ( yytext, (char**)NULL, 10 ), 1, 2 ) } +-?[0-9]+[lL]? { SETINTTOKEN( strtol ( yytext, (char**)NULL, 10 ), 1, 4 ) } + +-?([0-9]+|([0-9]+(\.[0-9]+)?)([eE][-+]?[0-9]+)?)[dD] { SETFLTTOKEN( strtod( yytext, (char**)NULL ), 8 ) } +-?([0-9]+|([0-9]+(\.[0-9]+)?)([eE][-+]?[0-9]+)?)[fF]? { SETFLTTOKEN( strtod( yytext, (char**)NULL ), 4 ) } + +[ ]+ { columnNo += yyleng; } +\t { columnNo += 3; } +\r { } +\n { columnNo = 1; lineNo++; } +. { SETTOKEN(UNKNOWN, commandToken, UNKNOWN ) } + +%% + +void yyreset() +{ + // Reset the input buffer of the scanner so that the next call of yylex() invokes + // YY_INPUT to fill the buffer with new data. + if ( YY_CURRENT_BUFFER ) + yy_flush_buffer( YY_CURRENT_BUFFER ); + lineNo = 1; + columnNo = 1; + currInfo = 0; +} + + +void llerror( char* s ) +{ + RMInit::logOut << "Lex error: line " << lineNo << ", " << s << " at " << yytext << std::endl; +} diff --git a/qlparser/oql.yy b/qlparser/oql.yy new file mode 100644 index 0000000..006ed88 --- /dev/null +++ b/qlparser/oql.yy @@ -0,0 +1,2185 @@ +%{ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * Grammar for RasQL + * + * + * COMMENTS: + * - token BY unused + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, yacc parser: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/oql.y,v 1.95 2006/01/03 00:21:40 rasdev Exp $"; + +#include "qlparser/qtconversion.hh" +#include "qlparser/qtmarrayop.hh" +#include "qlparser/qtcondense.hh" +#include "qlparser/qtbinaryinduce2.hh" +#include "qlparser/qtbinaryfunc.hh" +#include "qlparser/qtoid.hh" +#include "qlparser/qtcondenseop.hh" +#include "qlparser/qtstringdata.hh" +#include "qlparser/qtconst.hh" +#include "qlparser/qtintervalop.hh" +#include "qlparser/qtmintervalop.hh" +#include "qlparser/qtunaryfunc.hh" +#include "qlparser/qtupdate.hh" +#include "qlparser/qtinsert.hh" +#include "qlparser/qtdelete.hh" +#include "qlparser/qtjoiniterator.hh" +#include "qlparser/qtselectioniterator.hh" +#include "qlparser/qtoperationiterator.hh" +#include "qlparser/qtcommand.hh" +#include "qlparser/qtunaryinduce.hh" +#include "qlparser/qtiterator.hh" +#include "qlparser/qtcomplexdata.hh" +#include "qlparser/qtmddaccess.hh" +#include "qlparser/querytree.hh" +#include "servercomm/servercomm.hh" + +extern ServerComm::ClientTblElt* currentClientTblElt; +extern ParseInfo *currInfo; + +void yyerror( char* s ); + +extern int yylex(); +extern unsigned int lineNo; +extern unsigned int columnNo; +extern char* yytext; + +//defined in oql.l +extern QueryTree* parseQueryTree; + +ParseInfo* parseError = NULL; + +struct QtUpdateSpecElement +{ + QtOperation* iterator; + QtOperation* domain; +}; + +#define FREESTACK( ARG ) \ + parseQueryTree->removeDynamicObject( ARG.info ); \ + delete ARG.info; \ + ARG.info=NULL; + +// simple context dependancy for marray +#define YYPARSE_PARAM mflag +#define MF_IN_CONTEXT (void *)1 +#define MF_NO_CONTEXT (void *)0 + +%} + +// definition section + +%union { + + struct { + bool value; + ParseInfo* info; + } booleanToken; + + struct { + char value; + ParseInfo* info; + } characterToken; + + struct { + unsigned short negative; // 1 = signed value, 0 = unsigned value + r_Long svalue; // stores the signed value -> negative = 1 + r_ULong uvalue; // stores the unsigned value -> negative = 0; + unsigned short bytes; // stores the length in bytes (1,2,3,4) + ParseInfo* info; + } integerToken; + + struct { + double value; + unsigned short bytes; // stores the length in bytes (4,8) + ParseInfo* info; + } floatToken; + + struct { + char* value; + ParseInfo* info; + } stringToken; + + struct { + int value; + ParseInfo* info; + } typeToken; + + + struct { + int value; + ParseInfo* info; + } commandToken; + + struct { + char* value; + ParseInfo* info; + } identifierToken; + +//-------------------------------------------------- + QtMarrayOp2::mddIntervalType * mddIntervalType; + QtMarrayOp2::mddIntervalListType * mddIntervalListType; +//--------------------------------------------------- + + r_Sinterval* Sinterval; + + QtNode* qtNodeValue; + QtOperation* qtOperationValue; + QtUnaryOperation* qtUnaryOperationValue; + QtDomainOperation* qtDomainValue; + QtMDDAccess* qtMDDAccessValue; + + QtData* qtDataValue; + QtScalarData* qtScalarDataValue; + QtAtomicData* qtAtomicDataValue; + QtComplexData* qtComplexDataValue; + + QtIterator::QtONCStreamList* qtONCStreamListValue; + QtComplexData::QtScalarDataList* qtScalarDataListValue; + QtNode::QtOperationList* qtOperationListValue; + + QtUpdateSpecElement qtUpdateSpecElement; + + Ops::OpType operationValue; + int dummyValue; + + struct { + QtCast::cast_types qtCastType; + ParseInfo *info; + } castTypes; + +} + +%token <identifierToken> Identifier +%token <booleanToken> BooleanLit +%token <characterToken> CharacterLit +%token <integerToken> IntegerLit +%token <floatToken> FloatLit +%token <stringToken> StringLit +%token <typeToken> TUNSIG TBOOL TOCTET TCHAR TSHORT TUSHORT TLONG TULONG TFLOAT TDOUBLE +%token <commandToken> SELECT FROM WHERE AS RESTRICT TO EXTEND BY PROJECT AT DIMENSION ALL SOME + COUNTCELLS ADDCELLS AVGCELLS MINCELLS MAXCELLS SDOM OVER USING LO HI UPDATE + SET ASSIGN MARRAY CONDENSE IN DOT COMMA IS NOT AND OR XOR PLUS MINUS MULT + DIV EQUAL LESS GREATER LESSEQUAL GREATEREQUAL NOTEQUAL COLON SEMICOLON LEPAR + REPAR LRPAR RRPAR LCPAR RCPAR INSERT INTO VALUES DELETE DROP CREATE COLLECTION + MDDPARAM OID SHIFT SCALE SQRT ABS EXP LOG LN SIN COS TAN SINH COSH TANH ARCSIN + ARCCOS ARCTAN OVERLAY BIT UNKNOWN FASTSCALE MEMBERS ADD ALTER LIST + STRCT COMPLEX RE IM TIFF BMP HDF CSV JPEG PNG VFF TOR DEM INV_TIFF INV_BMP INV_HDF + INV_JPEG INV_PNG INV_VFF INV_CSV INV_TOR INV_DEM + +%left COLON VALUES USING WHERE +%left OVERLAY +%left OR XOR +%left AND +%left NOT +%left IS +%left EQUAL LESS GREATER LESSEQUAL GREATEREQUAL NOTEQUAL +%left PLUS MINUS +%left MULT DIV +%left UNARYOP BIT +%left DOT LEPAR SDOM + +// The LEPAR precedence is for the trimming operation. Context dependent +// precedence would be better in that case but it did not work. + +%type <qtUpdateSpecElement> updateSpec +%type <qtMDDAccessValue> iteratedCollection +%type <qtONCStreamListValue> collectionList +%type <qtUnaryOperationValue> reduceIdent structSelection trimExp +%type <qtOperationValue> mddExp inductionExp generalExp resultList reduceExp functionExp spatialOp + integerExp mintervalExp intervalExp condenseExp variable +%type <qtOperationListValue> spatialOpList spatialOpList2 +%type <integerToken> intLitExp +%type <operationValue> condenseOpLit +%type <castTypes> castType +%type <dummyValue> qlfile query selectExp createExp insertExp deleteExp updateExp dropExp +%type <identifierToken> namedCollection collectionIterator typeName attributeIdent pyrName + marrayVariable condenseVariable + +// literal data +%type <qtDataValue> generalLit mddLit oidLit +%type <qtScalarDataValue> scalarLit +%type <qtAtomicDataValue> atomicLit +%type <qtComplexDataValue> complexLit +%type <qtScalarDataListValue> scalarLitList dimensionLitList + +// marray2 with multiple intervals +%type <mddIntervalListType> ivList +%type <mddIntervalType> iv marray_head + +%% // rules section +/*-------------------------------------------------------------------- + * Grammar starts here + *-------------------------------------------------------------------- + */ + +qlfile: query + { + // clear all symbols in table at the end of parsing + QueryTree::symtab.wipe(); + }; + +query: createExp + | dropExp + | selectExp + | updateExp + | insertExp + | deleteExp; + + +createExp: CREATE COLLECTION namedCollection typeName + { + try { + accessControl.wantToWrite(); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 803, $2.info->getToken().c_str(), + $2.info->getLineNo(), $2.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + FREESTACK($4) + QueryTree::symtab.wipe(); + YYABORT; + } + + // create the command node + QtCommand* commandNode = new QtCommand( QtCommand::QT_CREATE_COLLECTION, $3.value, $4.value ); + commandNode->setParseInfo( *($1.info) ); + + // set insert node as root of the Query Tree + parseQueryTree->setRoot( commandNode ); + + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + FREESTACK($4) + }; + +dropExp: DROP COLLECTION namedCollection + { + try { + accessControl.wantToWrite(); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 803, $2.info->getToken().c_str(), + $2.info->getLineNo(), $2.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + QueryTree::symtab.wipe(); + YYABORT; + } + + // create the command node + QtCommand* commandNode = new QtCommand( QtCommand::QT_DROP_COLLECTION, $3.value ); + commandNode->setParseInfo( *($1.info) ); + + // set insert node as root of the Query Tree + parseQueryTree->setRoot( commandNode ); + + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + }; + +selectExp: SELECT resultList FROM collectionList WHERE generalExp + { + try { + accessControl.wantToRead(); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 803, $1.info->getToken().c_str(), + $1.info->getLineNo(), $1.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($3) + FREESTACK($5) + QueryTree::symtab.wipe(); + YYABORT; + } + + for( QtIterator::QtONCStreamList::iterator iter=$4->begin(); iter!=$4->end(); iter++ ) + parseQueryTree->removeDynamicObject( *iter ); + + // create a JoinIterator + QtJoinIterator* ji = new QtJoinIterator(); + ji->setStreamInputs( $4 ); + parseQueryTree->removeDynamicObject( $4 ); + + // create a QtONCStreamList and add the Join Iterator + QtIterator::QtONCStreamList* inputListS = new QtIterator::QtONCStreamList(1); + (*inputListS)[0] = ji; + + // create a SelectionIterator + QtSelectionIterator* si = new QtSelectionIterator(); + si->setStreamInputs( inputListS ); + si->setParseInfo( *($5.info) ); + si->setConditionTree( $6 ); + parseQueryTree->removeDynamicObject( $6 ); + + // create a QtONCStreamList and add the Selection Iterator + QtIterator::QtONCStreamList* inputListO = new QtIterator::QtONCStreamList(1); + (*inputListO)[0] = si; + + // create a OperationIterator and set its inputs + QtOperationIterator* oi = new QtOperationIterator(); + oi->setStreamInputs( inputListO ); + oi->setParseInfo( *($1.info) ); + oi->setOperationTree( $2 ); + parseQueryTree->removeDynamicObject( $2 ); + + // set the OperationIterator as root of the Query Tree + parseQueryTree->setRoot( oi ); + + FREESTACK($1) + FREESTACK($3) + FREESTACK($5) + } + | SELECT resultList FROM collectionList + { + try { + accessControl.wantToRead(); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 803, $1.info->getToken().c_str(), + $1.info->getLineNo(), $1.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($3) + QueryTree::symtab.wipe(); + YYABORT; + } + + for( QtIterator::QtONCStreamList::iterator iter=$4->begin(); iter!=$4->end(); iter++ ) + parseQueryTree->removeDynamicObject( *iter ); + + // create a JoinIterator + QtJoinIterator* ji = new QtJoinIterator(); + ji->setStreamInputs( $4 ); + parseQueryTree->removeDynamicObject( $4 ); + + // create a QtONCStreamList and add the Join Iterator + QtIterator::QtONCStreamList* inputList = new QtIterator::QtONCStreamList(1); + (*inputList)[0] = ji; + + // create a OperationIterator and set its inputs + QtOperationIterator* oi = new QtOperationIterator(); + oi->setStreamInputs( inputList ); + oi->setParseInfo( *($1.info) ); + oi->setOperationTree( $2 ); + parseQueryTree->removeDynamicObject( $2 ); + + // set the OperationIterator as root of the Query Tree + parseQueryTree->setRoot( oi ); + + FREESTACK($1) + FREESTACK($3) + }; + +updateExp: UPDATE iteratedCollection SET updateSpec ASSIGN generalExp WHERE generalExp + { + try { + accessControl.wantToWrite(); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 803, $1.info->getToken().c_str(), + $1.info->getLineNo(), $1.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($3) + FREESTACK($5) + FREESTACK($7) + QueryTree::symtab.wipe(); + YYABORT; + } + + // create a QtONCStreamList and add the QtAccess object of collection Spec + QtIterator::QtONCStreamList* streamList = new QtIterator::QtONCStreamList(1); + (*streamList)[0] = $2; + parseQueryTree->removeDynamicObject( $2 ); + + // create a SelectionIterator + QtSelectionIterator* si = new QtSelectionIterator(); + si->setStreamInputs( streamList ); + si->setConditionTree( $8 ); + si->setParseInfo( *($7.info) ); + parseQueryTree->removeDynamicObject( $8 ); + + // create an update node + QtUpdate* update = new QtUpdate( $4.iterator, $4.domain, $6 ); + update->setStreamInput( si ); + update->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $4.iterator ); + parseQueryTree->removeDynamicObject( $4.domain ); + parseQueryTree->removeDynamicObject( $6 ); + + // set the update node as root of the Query Tree + parseQueryTree->setRoot( update ); + + FREESTACK($1) + FREESTACK($3) + FREESTACK($5) + FREESTACK($7) + } + | UPDATE iteratedCollection SET updateSpec ASSIGN generalExp + { + try { + accessControl.wantToWrite(); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 803, $1.info->getToken().c_str(), + $1.info->getLineNo(), $1.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($3) + FREESTACK($5) + QueryTree::symtab.wipe(); + YYABORT; + } + + // create an update node + QtUpdate* update = new QtUpdate( $4.iterator, $4.domain, $6 ); + update->setStreamInput( $2 ); + update->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $2 ); + parseQueryTree->removeDynamicObject( $4.iterator ); + parseQueryTree->removeDynamicObject( $4.domain ); + parseQueryTree->removeDynamicObject( $6 ); + + // set the update node as root of the Query Tree + parseQueryTree->setRoot( update ); + + FREESTACK($1) + FREESTACK($3) + FREESTACK($5) + }; + +insertExp: INSERT INTO namedCollection VALUES generalExp + { + try { + accessControl.wantToWrite(); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 803, $2.info->getToken().c_str(), + $2.info->getLineNo(), $2.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + FREESTACK($4) + QueryTree::symtab.wipe(); + YYABORT; + } + + // create an update node + QtInsert* insert = new QtInsert( $3.value, $5 ); + insert->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $5 ); + + // set insert node as root of the Query Tree + parseQueryTree->setRoot( insert ); + + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + FREESTACK($4) + }; + +deleteExp: DELETE FROM iteratedCollection WHERE generalExp + { + try { + accessControl.wantToWrite(); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 803, $2.info->getToken().c_str(), + $2.info->getLineNo(), $2.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + QueryTree::symtab.wipe(); + YYABORT; + } + + // create a QtONCStreamList and add the QtAccess object of collection Spec + QtIterator::QtONCStreamList* streamList = new QtIterator::QtONCStreamList(1); + (*streamList)[0] = $3; + parseQueryTree->removeDynamicObject( $3 ); + + // create a SelectionIterator + QtSelectionIterator* si = new QtSelectionIterator(); + si->setStreamInputs( streamList ); + si->setConditionTree( $5 ); + si->setParseInfo( *($4.info) ); + parseQueryTree->removeDynamicObject( $5 ); + + // create delete node + QtDelete* delNode = new QtDelete(); + delNode->setStreamInput( si ); + delNode->setParseInfo( *($1.info) ); + + // set insert node as root of the Query Tree + parseQueryTree->setRoot( delNode ); + + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } +/* // doesn't work yet, somewhere later the server crashes -- PB 2006-jan-03 + | DELETE FROM iteratedCollection + { + try { + accessControl.wantToWrite(); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 803, $2.info->getToken().c_str(), + $2.info->getLineNo(), $2.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($2) + QueryTree::symtab.wipe(); + YYABORT; + } + + // create delete node + QtDelete* delNode = new QtDelete(); + delNode->setStreamInput( $3 ); + delNode->setParseInfo( *($1.info) ); + + // set insert node as root of the Query Tree + parseQueryTree->setRoot( delNode ); + + FREESTACK($1) + FREESTACK($2) + } +*/ + ; + +updateSpec: variable + { + $$.iterator = $1; + $$.domain = 0; + } + | variable mintervalExp + { + $$.iterator = $1; + $$.domain = $2; + }; + +resultList: resultList COMMA generalExp + { + $$ = $3; + FREESTACK($2) + } + | generalExp + { + $$ = $1; + }; + +generalExp: mddExp { $$ = $1; } + | trimExp { $$ = $1; } + | reduceExp { $$ = $1; } + | inductionExp { $$ = $1; } + | functionExp { $$ = $1; } + | integerExp { $$ = $1; } + | condenseExp { $$ = $1; } + | variable { $$ = $1; } + | mintervalExp { $$ = $1; } + | intervalExp { $$ = $1; } + | generalLit + { + $$ = new QtConst( $1 ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->addDynamicObject( $$ ); + }; + +integerExp: generalExp DOT LO + { + $$ = new QtIntervalLoOp( $1 ); + $$->setParseInfo( *($3.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + FREESTACK($3) + } + | generalExp DOT HI + { + $$ = new QtIntervalHiOp( $1 ); + $$->setParseInfo( *($3.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + FREESTACK($3) + }; + +mintervalExp: LEPAR spatialOpList REPAR + { + if (($2->size() > 1) || + ($2->size() == 1 && (*$2)[0]->getNodeType() == QtNode::QT_INTERVALOP)) + { + // Check if the list consists of integers only and + // create a point operation in this case. + int isPoint = 1; + QtNode::QtOperationList::iterator iter; + + for( iter=$2->begin(); iter!=$2->end(); ++iter ) + isPoint &= (*iter)->getNodeType() != QtNode::QT_INTERVALOP; + + for( iter=$2->begin(); iter!=$2->end(); ++iter ) + parseQueryTree->removeDynamicObject( *iter ); + + if( isPoint ) + $$ = new QtPointOp( $2 ); + else + $$ = new QtMintervalOp( $2 ); + + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + } + else + if ($2->size() == 1) + { + // take the single element + $$ = (*$2)[0]; + (*$2)[0] = 0; + delete $2; + } + else + { + RMInit::logOut << "MINTERVAL error: empty expression between brackets encountered!" << std::endl; + // save the parse error info and stop the parser + if ( parseError ) + delete parseError; + // TODO: Define an error number for this one!!!! 312 is not correct. + parseError = new ParseInfo( 312, $1.info->getToken().c_str(), + $1.info->getLineNo(), + $1.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($3) + QueryTree::symtab.wipe(); + YYABORT; + } + FREESTACK($1) + FREESTACK($3) + } + | SDOM LRPAR collectionIterator RRPAR + { + QtVariable* var = new QtVariable( $3.value ); + var->setParseInfo( *($3.info) ); + $$ = new QtSDom( var ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + FREESTACK($4) + }; + +spatialOpList: + { + $$ = new QtNode::QtOperationList(); + } + | spatialOpList2 + { + $$ = $1; + }; + +spatialOpList2: spatialOpList2 COMMA spatialOp + { + $1->push_back( $3 ); + $$ = $1; + FREESTACK($2) + } + | spatialOp + { + $$ = new QtNode::QtOperationList(1); + (*$$)[0] = $1; + }; + +spatialOp: generalExp { $$ = $1; }; + +intervalExp: generalExp COLON generalExp + { + $$ = new QtIntervalOp( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | MULT COLON generalExp + { + QtConst* const1 = new QtConst( new QtStringData("*") ); + const1->setParseInfo( *($1.info) ); + $$ = new QtIntervalOp( const1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + } + | generalExp COLON MULT + { + QtConst* const1 = new QtConst( new QtStringData("*") ); + const1->setParseInfo( *($3.info) ); + $$ = new QtIntervalOp( $1, const1 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + FREESTACK($3) + } + | MULT COLON MULT + { + QtConst* const1 = new QtConst( new QtStringData("*") ); + const1->setParseInfo( *($1.info) ); + QtConst* const2 = new QtConst( new QtStringData("*") ); + const2->setParseInfo( *($3.info) ); + $$ = new QtIntervalOp( const1, const2 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + }; + +condenseExp: CONDENSE condenseOpLit OVER condenseVariable IN generalExp WHERE generalExp USING generalExp + { + $$ = new QtCondenseOp( $2, $4.value, $6, $10, $8 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $6 ); + parseQueryTree->removeDynamicObject( $8 ); + parseQueryTree->removeDynamicObject( $10 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($3) + FREESTACK($4) + FREESTACK($5) + FREESTACK($7) + FREESTACK($9) + } + | CONDENSE condenseOpLit OVER condenseVariable IN generalExp USING generalExp + { + $$ = new QtCondenseOp( $2, $4.value, $6, $8 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $6 ); + parseQueryTree->removeDynamicObject( $8 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($3) + FREESTACK($4) + FREESTACK($5) + FREESTACK($7) + }; + +condenseOpLit: PLUS + { + $$ = Ops::OP_PLUS; + FREESTACK($1) + } + | MINUS + { + $$ = Ops::OP_MINUS; + FREESTACK($1) + } + | MULT + { + $$ = Ops::OP_MULT; + FREESTACK($1) + } + | DIV + { + $$ = Ops::OP_DIV; + FREESTACK($1) + } + | AND + { + $$ = Ops::OP_AND; + FREESTACK($1) + } + | OR + { + $$ = Ops::OP_OR; + FREESTACK($1) + }; + +functionExp: OID LRPAR collectionIterator RRPAR + { + QtVariable* var = new QtVariable( $3.value ); + var->setParseInfo( *($3.info) ); + $$ = new QtOId( var ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + FREESTACK($4) + } + | SHIFT LRPAR generalExp COMMA generalExp RRPAR + { + $$ = new QtShift( $3, $5 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->removeDynamicObject( $5 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + // added -- PB 2005-jun-18 + | EXTEND LRPAR generalExp COMMA generalExp RRPAR + { + $$ = new QtExtend( $3, $5 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->removeDynamicObject( $5 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | SCALE LRPAR generalExp COMMA generalExp RRPAR + { + $$ = new QtScale( $3, $5 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->removeDynamicObject( $5 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | BIT LRPAR generalExp COMMA generalExp RRPAR + { + $$ = new QtBit( $3, $5 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->removeDynamicObject( $5 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | TIFF LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOTIFF, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | TIFF LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOTIFF ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | BMP LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOBMP, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | BMP LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOBMP ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | HDF LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOHDF, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | HDF LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOHDF ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | CSV LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOCSV, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | CSV LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOCSV ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | JPEG LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOJPEG, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | JPEG LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOJPEG ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | PNG LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOPNG, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | PNG LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOPNG ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | VFF LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOVFF, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | VFF LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOVFF ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | TOR LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOTOR, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | TOR LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TOTOR ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | DEM LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TODEM, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | DEM LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_TODEM ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | INV_TIFF LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMTIFF, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | INV_TIFF LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMTIFF ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | INV_BMP LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMBMP, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | INV_BMP LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMBMP ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | INV_HDF LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMHDF, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | INV_HDF LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMHDF ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | INV_CSV LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMCSV, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | INV_CSV LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMCSV ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | INV_JPEG LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMJPEG, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | INV_JPEG LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMJPEG ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | INV_PNG LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMPNG, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | INV_PNG LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMPNG ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | INV_VFF LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMVFF, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | INV_VFF LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMVFF ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | INV_TOR LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMTOR, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | INV_TOR LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMTOR ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | INV_DEM LRPAR generalExp COMMA StringLit RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMDEM, $5.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + } + | INV_DEM LRPAR generalExp RRPAR + { + $$ = new QtConversion( $3, QtConversion::QT_FROMDEM ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + }; + + +structSelection: DOT attributeIdent + { + $$ = new QtDot( $2.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + } + | DOT intLitExp + { + if( $2.negative ) + if( $2.svalue < 0 ) + yyerror("non negative integer expected"); + else + $$ = new QtDot( (unsigned int)$2.svalue ); + else + $$ = new QtDot( (unsigned int)$2.uvalue ); + parseQueryTree->addDynamicObject( $$ ); + $$->setParseInfo( *($1.info) ); + FREESTACK($1) + FREESTACK($2) + }; + +inductionExp: SQRT LRPAR generalExp RRPAR + { + $$ = new QtSqrt( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | ABS LRPAR generalExp RRPAR + { + $$ = new QtAbs( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | EXP LRPAR generalExp RRPAR + { + $$ = new QtExp( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | LOG LRPAR generalExp RRPAR + { + $$ = new QtLog( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | LN LRPAR generalExp RRPAR + { + $$ = new QtLn( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | SIN LRPAR generalExp RRPAR + { + $$ = new QtSin( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | COS LRPAR generalExp RRPAR + { + $$ = new QtCos( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | TAN LRPAR generalExp RRPAR + { + $$ = new QtTan( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | SINH LRPAR generalExp RRPAR + { + $$ = new QtSinh( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | COSH LRPAR generalExp RRPAR + { + $$ = new QtCosh( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | TANH LRPAR generalExp RRPAR + { + $$ = new QtTanh( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | ARCSIN LRPAR generalExp RRPAR + { + $$ = new QtArcsin( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | ARCCOS LRPAR generalExp RRPAR + { + $$ = new QtArccos( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | ARCTAN LRPAR generalExp RRPAR + { + $$ = new QtArctan( $3 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + } + | generalExp DOT RE + { + $$ = new QtRealPartOp( $1 ); + $$->setParseInfo( *($3.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + FREESTACK($3) + } + | generalExp DOT IM + { + $$ = new QtImaginarPartOp( $1 ); + $$->setParseInfo( *($3.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + FREESTACK($3) + } + | NOT generalExp + { + $$ = new QtNot( $2 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->removeDynamicObject( $2 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | generalExp OVERLAY generalExp + { + $$ = new QtOverlay ( $3, $1 ); + $$->setParseInfo( *($2.info) ); + FREESTACK($2) + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + } + | generalExp IS generalExp + { + $$ = new QtIs ( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp AND generalExp + { + $$ = new QtAnd( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp OR generalExp + { + $$ = new QtOr ( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp XOR generalExp + { + $$ = new QtXor( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp PLUS generalExp + { + $$ = new QtPlus ( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp MINUS generalExp + { + $$ = new QtMinus( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp MULT generalExp + { + $$ = new QtMult ( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp DIV generalExp + { + $$ = new QtDiv ( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp EQUAL generalExp + { + $$ = new QtEqual( $1, $3 ); + $$->setParseInfo( *($2.info) ); + FREESTACK($2) + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + } + | generalExp LESS generalExp + { + $$ = new QtLess( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp GREATER generalExp + { + $$ = new QtLess( $3, $1 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp LESSEQUAL generalExp + { + $$ = new QtLessEqual( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp GREATEREQUAL generalExp + { + $$ = new QtLessEqual( $3, $1 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | generalExp NOTEQUAL generalExp + { + $$ = new QtNotEqual ( $1, $3 ); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | PLUS generalExp %prec UNARYOP + { + $$ = $2; + FREESTACK($1) + } + | MINUS generalExp %prec UNARYOP + { + $$ = new QtMult( $2, new QtConst( new QtAtomicData( (r_Long)-1, 1 ) ) ); + parseQueryTree->removeDynamicObject( $2 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | LRPAR castType RRPAR generalExp %prec UNARYOP + { + $$ = new QtCast($4, $2.qtCastType); + $$->setParseInfo( *($2.info) ); + parseQueryTree->removeDynamicObject($4); + parseQueryTree->addDynamicObject($$); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + } + | LRPAR generalExp RRPAR + { + $$ = $2; + FREESTACK($1) + FREESTACK($3) + } + | generalExp structSelection + { + $2->setInput($1); + $$ = $2; + parseQueryTree->removeDynamicObject( $1 ); + }; + +castType: TBOOL { $$.info = $1.info; $$.qtCastType = QtCast::t_bool; } + | TCHAR { $$.info = $1.info; $$.qtCastType = QtCast::t_char; } + | TOCTET { $$.info = $1.info; $$.qtCastType = QtCast::t_octet; } + | TSHORT { $$.info = $1.info; $$.qtCastType = QtCast::t_short; } + | TUSHORT { $$.info = $1.info; $$.qtCastType = QtCast::t_ushort; } + | TLONG { $$.info = $1.info; $$.qtCastType = QtCast::t_long; } + | TULONG { $$.info = $1.info; $$.qtCastType = QtCast::t_ulong; } + | TFLOAT { $$.info = $1.info; $$.qtCastType = QtCast::t_float; } + | TDOUBLE { $$.info = $1.info; $$.qtCastType = QtCast::t_double; } + | TUNSIG TSHORT { $$.info = $1.info; $$.qtCastType = QtCast::t_ushort; } + | TUNSIG TLONG { $$.info = $1.info; $$.qtCastType = QtCast::t_ulong; }; + +collectionList: collectionList COMMA iteratedCollection + { + // add the QtMDDAccess object and give back the list + $1->push_back($3); + $$ = $1; + FREESTACK($2) + } + | iteratedCollection + { + // create a new list and add the QtMDDAccess object + $$ = new QtIterator::QtONCStreamList(); + $$->push_back($1); + parseQueryTree->addDynamicObject( $$ ); + }; + +iteratedCollection: namedCollection AS collectionIterator + { + $$ = new QtMDDAccess( $1.value, $3.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + } + | namedCollection collectionIterator + { + $$ = new QtMDDAccess( $1.value, $2.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + } + | namedCollection + { + $$ = new QtMDDAccess( $1.value, $1.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + }; + +variable: Identifier + { + $$ = new QtVariable( $1.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + }; + +namedCollection: Identifier; + +collectionIterator: Identifier; + +pyrName: Identifier; + +attributeIdent: Identifier; + +typeName: Identifier; + +marrayVariable: Identifier; + +condenseVariable: Identifier; + +reduceExp: reduceIdent LRPAR generalExp RRPAR + { + $1->setInput( $3 ); + $$ = $1; + parseQueryTree->removeDynamicObject( $3 ); + FREESTACK($2) + FREESTACK($4) + }; + +reduceIdent: ALL + { + $$ = new QtAll(); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | SOME + { + $$ = new QtSome(); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | COUNTCELLS + { + $$ = new QtCountCells(); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | ADDCELLS + { + $$ = new QtAddCells(); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | AVGCELLS + { + $$ = new QtAvgCells(); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | MINCELLS + { + $$ = new QtMinCells(); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | MAXCELLS + { + $$ = new QtMaxCells(); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + }; + +intLitExp: IntegerLit { $$ = $1; }; + +generalLit: scalarLit { $$ = $1; } + | mddLit { $$ = $1; } + | StringLit + { + $$ = new QtStringData( std::string($1.value) ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | oidLit { $$ = $1; }; + +oidLit: LESS StringLit GREATER + { + r_OId oid; + try { + oid = r_OId( $2.value ); + } + catch(...) { + // save the parse error info and stop the parser + if ( parseError ) delete parseError; + parseError = new ParseInfo( 303, $2.info->getToken().c_str(), + $2.info->getLineNo(), $2.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + QueryTree::symtab.wipe(); + YYABORT; + } + + // test if database match the current one + int mismatch = oid.get_base_name() == 0; + + if( !mismatch ) { + // check for question mark + char* baseName = strdup( oid.get_base_name() ); + char* end = strchr( baseName, '?' ); + if( end ) + *end = '\0'; + mismatch = strcmp( baseName, currentClientTblElt->database.getName() ) !=0; + free( baseName ); + baseName = 0; + } + + if( mismatch ) { + // save the parse error info and stop the parser + if( parseError ) delete parseError; + parseError = new ParseInfo( 386, $2.info->getToken().c_str(), + $2.info->getLineNo(), $2.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + QueryTree::symtab.wipe(); + YYABORT; + } + + // take the local oid + $$ = new QtAtomicData( oid.get_local_oid(), 8 ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($3) + }; + +mddLit: LESS mintervalExp dimensionLitList GREATER + { + // create a QtMDD object representing the literal + try { + $$ = new QtMDD( $2, $3 ); + } + catch( ParseInfo& obj ) { + delete $3; + + // save the parse error info and stop the parser + if( parseError ) delete parseError; + parseError = new ParseInfo( obj.getErrorNo(), $1.info->getToken().c_str(), + $1.info->getLineNo(), $1.info->getColumnNo() ); + FREESTACK($1) + FREESTACK($4) + QueryTree::symtab.wipe(); + YYABORT; + } + $$->setParseInfo( *($1.info) ); + + for( std::list<QtScalarData*>::iterator iter=$3->begin(); iter!=$3->end(); iter++ ) { + delete *iter; + parseQueryTree->removeDynamicObject( *iter ); + } + + delete $2; + delete $3; + parseQueryTree->removeDynamicObject( $2 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($4) + } + | MDDPARAM + { + try { + $$ = new QtMDD( $1.value ); + } + catch( ParseInfo& obj ) { + // save the parse error info and stop the parser + if( parseError ) delete parseError; + parseError = new ParseInfo( obj.getErrorNo(), $1.info->getToken().c_str(), + $1.info->getLineNo(), $1.info->getColumnNo() ); + FREESTACK($1) + QueryTree::symtab.wipe(); + YYABORT; + } + parseQueryTree->addDynamicObject( $$ ); + $$->setParseInfo( *($1.info) ); + FREESTACK($1) + }; + +dimensionLitList: dimensionLitList SEMICOLON scalarLitList + { + // concatenate the lists + $1->splice( $1->end(), *$3 ); + $$ = $1; + delete $3; + FREESTACK($2) + } + | scalarLitList + { + // simply take the list + $$ = $1; + }; + +scalarLit: complexLit + { + $$ = $1; + } + | atomicLit + { + $$ = $1; + }; + +atomicLit: BooleanLit + { + $$ = new QtAtomicData( $1.value ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | IntegerLit + { + if( $1.negative ) + $$ = new QtAtomicData( $1.svalue, $1.bytes ); + else + $$ = new QtAtomicData( $1.uvalue, $1.bytes ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | FloatLit + { + $$ = new QtAtomicData( $1.value, $1.bytes ); + $$->setParseInfo( *($1.info) ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + } + | COMPLEX LRPAR FloatLit COMMA FloatLit RRPAR + { + // this should construct a complex type + // for both float and double cell type + if($3.bytes + $5.bytes == 2 * sizeof(float) || $3.bytes + $5.bytes == 2 * sizeof(double)) + $$ = new QtAtomicData($3.value, $5.value, $3.bytes + $5.bytes); + else { + if(parseError) delete parseError; + parseError = new ParseInfo(311, $2.info->getToken().c_str(), + $2.info->getLineNo(), $2.info->getColumnNo()); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + QueryTree::symtab.wipe(); + YYABORT; + } + $$->setParseInfo(*($3.info)); + parseQueryTree->addDynamicObject($$); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + FREESTACK($6) + }; + +complexLit: LCPAR scalarLitList RCPAR + { + for( std::list<QtScalarData*>::iterator iter=$2->begin(); iter!=$2->end(); iter++ ) + parseQueryTree->removeDynamicObject( *iter ); + $$ = new QtComplexData( $2 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($3) + } + | STRCT LCPAR scalarLitList RCPAR + { + for( std::list<QtScalarData*>::iterator iter=$3->begin(); iter!=$3->end(); iter++ ) + parseQueryTree->removeDynamicObject( *iter ); + $$ = new QtComplexData( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($1) + FREESTACK($2) + FREESTACK($4) + }; + +scalarLitList: scalarLitList COMMA scalarLit + { + // add the literal element and give back the list + $1->push_back($3); + $$ = $1; + FREESTACK($2) + } + | scalarLit + { + // create a new list and add the literal element + $$ = new QtComplexData::QtScalarDataList(); + $$->push_back($1); + }; + + + + +trimExp: generalExp mintervalExp + { + QtDomainOperation *dop = new QtDomainOperation( $2 ); + dop->setInput( $1 ); // e.g. variable name + parseQueryTree->removeDynamicObject( $1 ); + parseQueryTree->removeDynamicObject( $2 ); + parseQueryTree->addDynamicObject( dop ); + $$ = dop; + if (mflag == MF_IN_CONTEXT) + parseQueryTree->addDomainObject( dop ); + }; + +marray_head: + MARRAY + { + mflag = MF_IN_CONTEXT; + QueryTree::symtab.initScope(); + } + iv + { + $$ = $3; + $$->parseInfo = *($1.info); + FREESTACK($1) + }; + +mddExp: marray_head VALUES generalExp + { + // create a new list and add the element + QtMarrayOp2::mddIntervalListType *dlist = new QtMarrayOp2::mddIntervalListType(); + dlist->push_back(*($1)); + + // concatenate intervals and variable names, then do a domain rewrite + QtMarrayOp2 *qma = new QtMarrayOp2( dlist, $3 ); + qma->setOldMarray(true); + qma->rewriteVars( ); + + char *stra = strdup( $1->variable.c_str() ); + $$ = new QtMarrayOp( stra, $1->tree, qma->getInput()); + parseQueryTree->addCString(stra); + + QueryTree::symtab.exitScope(); + mflag = MF_NO_CONTEXT; + + // release memory + while (!(dlist->empty())) + { + dlist->erase(dlist->begin()); + } + delete dlist; + delete qma; + delete $1; + parseQueryTree->removeDynamicObject( $3 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + } + | marray_head COMMA ivList VALUES generalExp + { + // create a new list and add the element + QtMarrayOp2::mddIntervalListType *dlist = new QtMarrayOp2::mddIntervalListType(); + dlist->push_back(*($1)); + + // concatenate the lists + dlist->insert( + dlist->end(), + $3->begin(), + $3->end() + ); + + // concatenate intervals and variable names, then do a domain rewrite + QtMarrayOp2 *qma = new QtMarrayOp2( dlist, $5 ); + qma->setOldMarray(false); + qma->rewriteVars( ); + if (!(qma->concatenateIntervals())) + { + // TODO: change error code! + // save the parse error info and stop the parser + if ( parseError ) + delete parseError; + parseError = new ParseInfo( 313, ($1->parseInfo).getToken().c_str(), + ($1->parseInfo).getLineNo(), + ($1->parseInfo).getColumnNo() ); + QueryTree::symtab.exitScope(); + mflag = MF_NO_CONTEXT; + + // release memory + while (!(dlist->empty())) + { + dlist->erase(dlist->begin()); + } + delete dlist; + delete qma; + delete $1; + parseQueryTree->removeDynamicObject( $5 ); + FREESTACK($2) + FREESTACK($4) + YYABORT; + } + + r_Minterval *dinterval = new r_Minterval(qma->greatDomain); + std::string *dvariable = new std::string(qma->greatIterator); + parseQueryTree->rewriteDomainObjects(dinterval, dvariable, dlist); + + // initialize old good QtMarray with the translated data + QtMintervalData *mddIntervalData = new QtMintervalData(*dinterval); + $$ = new QtMarrayOp( dvariable->c_str(), new QtConst(mddIntervalData), qma->getInput()); +// $$->setParseInfo( *($1.info) ); + + QueryTree::symtab.exitScope(); + mflag = MF_NO_CONTEXT; + + // release memory + while (!(dlist->empty())) + { + dlist->erase(dlist->begin()); + } + delete dlist; + delete qma; + delete $1; + parseQueryTree->removeDynamicObject( $5 ); + parseQueryTree->addDynamicObject( $$ ); + FREESTACK($2) + FREESTACK($4) + }; + +ivList: ivList COMMA iv + { + // add the element and give back the list + $1->push_back(*($3)); + $$ = $1; + delete $3; + FREESTACK($2) + } + | iv + { + // create a new list and add the element + $$ = new QtMarrayOp2::mddIntervalListType(); + $$->push_back(*($1)); + delete $1; + }; + +iv: marrayVariable IN generalExp + { + if (!QueryTree::symtab.putSymbol($1.value, 1)) // instead of 1 put the dimensionality + { + // save the parse error info and stop the parser + if ( parseError ) + delete parseError; + parseError = new ParseInfo( 312, $1.info->getToken().c_str(), + $1.info->getLineNo(), + $1.info->getColumnNo() ); + parseQueryTree->removeDynamicObject( $3 ); + FREESTACK($2) + QueryTree::symtab.wipe(); + YYABORT; + } + $$ = new QtMarrayOp2::mddIntervalType(); + $$->variable = $1.value; + $$->tree = $3; + $$->parseInfo = *($1.info); + parseQueryTree->removeDynamicObject( $3 ); + FREESTACK($2); + }; + +/*-------------------------------------------------------------------- + * Grammar ends here + *-------------------------------------------------------------------- + */ +%% // C code section + +void yyerror( char* /*s*/ ) { + if( !parseError ) { + + if( yytext[0] == '\0' ) { + // unexpected end of query + parseError = new ParseInfo( 308, yytext, lineNo, columnNo - strlen(yytext) ); + } + else { + // general parse error + parseError = new ParseInfo( 300, yytext, lineNo, columnNo - strlen(yytext) ); + } + } +} diff --git a/qlparser/parseinfo.cc b/qlparser/parseinfo.cc new file mode 100644 index 0000000..d16dad6 --- /dev/null +++ b/qlparser/parseinfo.cc @@ -0,0 +1,102 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, ParseInfo: $Id: parseinfo.cc,v 1.6 2002/06/19 14:36:23 coman Exp $"; + +#include <iostream> +using namespace std; + +#include "qlparser/parseinfo.hh" + + +ParseInfo::ParseInfo() + : errorNo( 0 ), + token( "" ), + lineNo( 0 ), + columnNo( 0 ) +{ +} + +ParseInfo::ParseInfo(const ParseInfo& old) + : errorNo( 0 ), + token( "" ), + lineNo( 0 ), + columnNo( 0 ) +{ + errorNo=old.errorNo; + lineNo=old.lineNo; + columnNo=old.columnNo; + token=old.token; +} + +ParseInfo::ParseInfo( const char* initToken, unsigned int initLineNo, unsigned initColumnNo ) + : errorNo( 0 ), + token( "" ), + lineNo( initLineNo ), + columnNo( initColumnNo ) +{ + if(initToken) { + token=initToken; + } +} + + + +ParseInfo::ParseInfo( unsigned long initErrorNo, const char* initToken, unsigned int initLineNo, unsigned initColumnNo ) + : errorNo( initErrorNo ), + token( "" ), + lineNo( initLineNo ), + columnNo( initColumnNo ) +{ + if(initToken) { + token=initToken; + } +} + +ParseInfo& +ParseInfo::operator=(const ParseInfo& old) +{ + if(this != &old) { + errorNo=old.errorNo; + lineNo=old.lineNo; + columnNo=old.columnNo; + token=old.token; + } + return *this; +} + +void +ParseInfo::printStatus( ostream& s ) const +{ + s << "Error number: " << errorNo << " Token: " << token.c_str() << " Line: " << lineNo << " Column: " << columnNo << endl; +} + diff --git a/qlparser/parseinfo.hh b/qlparser/parseinfo.hh new file mode 100644 index 0000000..7097139 --- /dev/null +++ b/qlparser/parseinfo.hh @@ -0,0 +1,111 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _PARSEINFO_ +#define _PARSEINFO_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + This class holds some information about a token and its + location in the parse string. Additionally, it can keep + an error number which is used in the query tree to report + error with some context information within the query string. + +*/ + +class ParseInfo +{ + public: + + /// default constructor + ParseInfo(); + + /// constructor getting error number, token and location information + ParseInfo( unsigned long errorNo, const char* token, unsigned int lineNo, unsigned columnNo ); + + /// copy constructor + ParseInfo( const ParseInfo& old); + + /// constructor getting token and location information + ParseInfo( const char* token, unsigned int lineNo, unsigned columnNo ); + + //@Man: Read/Write methods + //@{ + /// + inline unsigned long getErrorNo() const; + /// + inline const std::string& getToken() const; + /// + inline unsigned int getLineNo() const; + /// + inline unsigned int getColumnNo() const; + /// + inline void setErrorNo( unsigned long errorNo ); + /// + inline void setToken( const std::string& text ); + /// + inline void setToken( const char* text ); + /// + inline void setLineNo( unsigned int lineNo ); + /// + inline void setColumnNo( unsigned int columnNo ); + /// + //@} + + void printStatus( std::ostream& s= std::cout ) const; + + ParseInfo& operator=(const ParseInfo& old); + + private: + //@Man: Attributes + //@{ + /// + unsigned long errorNo; + /// + unsigned int lineNo; + /// + unsigned int columnNo; + /// + std::string token; + /// + //@} +}; + +#include "parseinfo.icc" + +#endif diff --git a/qlparser/parseinfo.icc b/qlparser/parseinfo.icc new file mode 100644 index 0000000..91e2dd0 --- /dev/null +++ b/qlparser/parseinfo.icc @@ -0,0 +1,100 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline +unsigned long +ParseInfo::getErrorNo() const +{ + return errorNo; +} + + + +inline const std::string& +ParseInfo::getToken() const +{ + return token; +} + + + +inline +unsigned int +ParseInfo::getLineNo() const +{ + return lineNo; +} + + + +inline unsigned int +ParseInfo::getColumnNo() const +{ + return columnNo; +} + + + +inline void +ParseInfo::setErrorNo( unsigned long newNo ) +{ + errorNo = newNo; +} + + + +inline void +ParseInfo::setToken( const std::string& text ) +{ + token = text; +} + + + +inline void +ParseInfo::setToken( const char* text ) +{ + token = std::string(text); +} + + + +inline void +ParseInfo::setLineNo( unsigned int newNo ) +{ + lineNo = newNo; +} + + + +inline void +ParseInfo::setColumnNo( unsigned int newNo ) +{ + columnNo = newNo; +} diff --git a/qlparser/qtatomicdata.cc b/qlparser/qtatomicdata.cc new file mode 100644 index 0000000..a8b12f8 --- /dev/null +++ b/qlparser/qtatomicdata.cc @@ -0,0 +1,212 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtAtomicData: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtatomicdata.cc,v 1.18 2003/12/27 20:51:28 rasdev Exp $"; + +#include "qlparser/qtatomicdata.hh" +#include "relcatalogif/basetype.hh" +#include "relcatalogif/alltypes.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +#include <iostream> + +#include "raslib/rmdebug.hh" + + +QtAtomicData::QtAtomicData() + : QtScalarData() +{ +} + + + +QtAtomicData::QtAtomicData( r_Long value, unsigned short byteLength ) + : QtScalarData() +{ + switch( byteLength ) + { + case 1: valueType = TypeFactory::mapType("Octet"); break; + case 2: valueType = TypeFactory::mapType("Short"); break; + case 4: valueType = TypeFactory::mapType("Long"); break; + + default: + RMInit::logOut << "Error: QtAtomicData::QtAtomicData() - signed integer value with length " + << byteLength << " is not supported." << endl; + } + + if( valueType ) + { + r_Long temp = value; + valueBuffer = new char[ valueType->getSize() ]; + valueType->makeFromCLong( valueBuffer, &temp ); + } +} + + +QtAtomicData::QtAtomicData( r_ULong value, unsigned short byteLength ) + : QtScalarData() +{ + switch( byteLength ) + { + case 1: valueType = TypeFactory::mapType("Char"); break; + case 2: valueType = TypeFactory::mapType("UShort"); break; + case 4: valueType = TypeFactory::mapType("ULong"); break; + + default: + RMInit::logOut << "Error: QtAtomicData::QtAtomicData() - unsigned integer value with length " + << byteLength << " is not supported." << endl; + } + + + if( valueType ) + { + r_ULong temp = value; + valueBuffer = new char[ valueType->getSize() ]; + valueType->makeFromCULong( valueBuffer, &temp ); + } +} + + + +QtAtomicData::QtAtomicData( bool value ) + : QtScalarData() +{ + r_ULong valueULong = (r_ULong)value; + + valueType = TypeFactory::mapType("Bool"); + valueBuffer = new char[ valueType->getSize() ]; + valueType->makeFromCULong( valueBuffer, &valueULong ); +} + + + +QtAtomicData::QtAtomicData( double value, unsigned short byteLength ) + : QtScalarData() +{ + switch( byteLength ) + { + case 4: valueType = TypeFactory::mapType("Float"); break; + case 8: valueType = TypeFactory::mapType("Double"); break; + + default: + RMInit::logOut << "Error: QtAtomicData::QtAtomicData() - float value with length " + << byteLength << " is not supported." << endl; + } + + + if( valueType ) + { + valueBuffer = new char[ valueType->getSize() ]; + valueType->makeFromCDouble( valueBuffer, &value ); + } +} + + + + +QtAtomicData::QtAtomicData( const QtAtomicData& obj ) + : QtScalarData( obj ) +{ +} + +QtAtomicData::~QtAtomicData() +{ +} + +r_ULong +QtAtomicData::getUnsignedValue() const +{ + r_ULong value=0; + + if( valueType ) + valueType->convertToCULong( valueBuffer, &value ); + + return value; +} + + + +r_Long +QtAtomicData::getSignedValue() const +{ + r_Long value=0; + + if( valueType ) + valueType->convertToCLong( valueBuffer, &value ); + + return value; +} + + + +double +QtAtomicData::getDoubleValue() const +{ + double value=0; + + if( valueType ) + valueType->convertToCDouble( valueBuffer, &value ); + + return value; +} + + + +void +QtAtomicData::printStatus( ostream& stream ) const +{ + stream << "atomic, " << flush; + + QtScalarData::printStatus( stream ); +} + + +// for complex types +QtAtomicData::QtAtomicData(double valRe, double valIm, unsigned short size) +: QtScalarData() { + double dummyRe = valRe; + double dummyIm = valIm; + + if(size == 2 * sizeof(float)) + valueType = TypeFactory::mapType("Complex1"); + else + valueType = TypeFactory::mapType("Complex2"); + + valueBuffer = new char[valueType->getSize()]; + valueType->makeFromCDouble(valueBuffer + ((GenericComplexType *)valueType)->getReOffset(), &dummyRe); + valueType->makeFromCDouble(valueBuffer + ((GenericComplexType *)valueType)->getImOffset(), &dummyIm); +} + diff --git a/qlparser/qtatomicdata.hh b/qlparser/qtatomicdata.hh new file mode 100644 index 0000000..769744d --- /dev/null +++ b/qlparser/qtatomicdata.hh @@ -0,0 +1,134 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _QTATOMICDATA_HH_ +#define _QTATOMICDATA_HH_ + +#include "qlparser/qtscalardata.hh" +#include "raslib/odmgtypes.hh" + +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents an atomic value handled by the query tree. + +*/ + +class QtAtomicData : public QtScalarData +{ + public: + /// default constructor + QtAtomicData(); + + /// constructor getting signed integer data + QtAtomicData( r_Long value, unsigned short byteLength ); + /** + The value for {\tt byteLength} specifies the type of the constant. + + \begin{tabular}{lll} + 1 && OCTET\\ + 2 && SHORT\\ + 4 && LONG\\ + \end{tabular} + */ + + /// constructor getting unsigned integer data + QtAtomicData( r_ULong value, unsigned short byteLength ); + /** + The value for {\tt byteLength} specifies the type of the constant. + + \begin{tabular}{lll} + 1 && CHAR\\ + 2 && USHORT\\ + 4 && ULONG\\ + \end{tabular} + */ + + /// constructor getting boolean data + QtAtomicData( bool value ); + + /// constructor getting float data + QtAtomicData( double value, unsigned short byteLength ); + /** + The value for {\tt byteLength} specifies the type of the constant. + + \begin{tabular}{lll} + 4 && FLOAT\\ + 8 && DOUBLE\\ + \end{tabular} + */ + + /// constructor getting complex data + QtAtomicData(double valRe, double valIm, unsigned short size); + + /// copy constructor + QtAtomicData( const QtAtomicData& obj ); + + /// destructor + virtual ~QtAtomicData(); + + /// returning unsigned value of an unsigned atomic type if it is one, 0 otherwise + r_ULong getUnsignedValue() const; + + /// returning signed value of a signed atomic type if it is one, 0 otherwise + r_Long getSignedValue() const; + + /// returning double value if it is one, 0 otherwise + double getDoubleValue() const; + + /// print status of the object to the specified stream + virtual void printStatus( std::ostream& stream = std::cout ) const; +}; + +#include "qlparser/qtatomicdata.icc" + +#endif + + + + + + + + + + + + + + + + + + + + + + diff --git a/qlparser/qtatomicdata.icc b/qlparser/qtatomicdata.icc new file mode 100644 index 0000000..2651f9c --- /dev/null +++ b/qlparser/qtatomicdata.icc @@ -0,0 +1,29 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + diff --git a/qlparser/qtbinaryfunc.cc b/qlparser/qtbinaryfunc.cc new file mode 100644 index 0000000..9b77888 --- /dev/null +++ b/qlparser/qtbinaryfunc.cc @@ -0,0 +1,1174 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * - QtScale is expected to have rounding errors with >1 tiles + * - shift, extend, scale release input tiles only at end; this + * shouldbe optimized (release immediately after evaluating) + * - why is this file called "binary"? all ops have just one MDD! + * - QtShift(), QtExtend() deliver for >1 tiles under PG an error + * "libpq 'select' did not yield 1 result but 0" + * which however does not seem to affect the result. + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtMintervalSelect, QtShift: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtbinaryfunc.cc,v 1.37 2005/09/03 20:17:55 rasdev Exp $"; + +#include "mymalloc/mymalloc.h" + +#include "mymalloc/mymalloc.h" + +#include "qlparser/qtbinaryfunc.hh" +#include "qlparser/qtdata.hh" +#include "qlparser/qtintervaldata.hh" +#include "qlparser/qtmintervaldata.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtpointdata.hh" + +#include "mddmgr/mddobj.hh" +#include "tilemgr/tile.hh" + +#include "raslib/rmdebug.hh" +#include "raslib/dlist.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + + +// --- QtShift -------------------------------------------------- + +const QtNode::QtNodeType QtShift::nodeType = QT_SHIFT; + +QtShift::QtShift( QtOperation* mddOp, QtOperation* pointOp ) + : QtBinaryOperation( mddOp, pointOp ) +{ +} + + + +bool +QtShift::isCommutative() const +{ + return false; // NOT commutative +} + + + +QtData* +QtShift::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtShift", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtData* operand1 = NULL; + QtData* operand2 = NULL; + + // evaluate sub-nodes to obtain operand values + if( getOperands( inputList, operand1, operand2 ) ) + { + // + // This implementation simply creates a new transient MDD object with the new + // domain while copying the data. Optimization of this is left for future work. + // + + QtMDD* qtMDDObj = (QtMDD*)operand1; + const r_Point& transPoint = ((QtPointData*)operand2)->getPointData(); + MDDObj* currentMDDObj = qtMDDObj->getMDDObject(); + + if( transPoint.dimension() != qtMDDObj->getLoadDomain().dimension() ) + { + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + RMInit::logOut << "Error: QtShift::evaluate( QtDataList* ) - dimensionality of MDD and point expression do not match." << endl; + parseInfo.setErrorNo(407); + throw parseInfo; + } + + // compute new domain + r_Minterval destinationDomain( qtMDDObj->getLoadDomain().create_translation( transPoint ) ); + + // create a transient MDD object for the query result + MDDObj* resultMDD = new MDDObj( currentMDDObj->getMDDBaseType(), destinationDomain ); + + // get all tiles + vector<Tile* >* tiles = currentMDDObj->intersect( qtMDDObj->getLoadDomain() ); + + // iterate over source tiles + for( vector<Tile*>::iterator tileIter = tiles->begin(); tileIter != tiles->end(); tileIter++ ) + { + // get relevant area of source tile + r_Minterval sourceTileDomain = qtMDDObj->getLoadDomain().create_intersection( (*tileIter)->getDomain() ); + + // compute translated tile domain + r_Minterval destinationTileDomain = sourceTileDomain.create_translation( transPoint ); + + // create a new transient tile, copy the transient data, and insert it into the mdd object + // FIXME: how can this work without tile area allocation??? -- PB 2005-jun-19 + Tile* newTransTile = new Tile( destinationTileDomain, currentMDDObj->getCellType() ); + newTransTile->copyTile( destinationTileDomain, *tileIter, sourceTileDomain ); + resultMDD->insertTile( newTransTile ); + } + + // create a new QtMDD object as carrier object for the transient MDD object + returnValue = new QtMDD( (MDDObj*)resultMDD ); + + // delete the tile vector, the tiles itself are deleted when the destructor + // of the MDD object is called + delete tiles; + tiles=NULL; + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + } + + return returnValue; +} + + + +void +QtShift::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtShift Object " << getNodeType() << endl; + + QtBinaryOperation::printTree( tab, s, mode ); +} + + + +void +QtShift::printAlgebraicExpression( ostream& s ) +{ + s << "shift("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ","; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +void +QtShift::optimizeLoad( QtTrimList* trimList ) +{ + RMDBCLASS( "QtShift", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) + + QtNode::QtTrimList *list1=NULL, *list2=NULL; + + if( input1 && input2 ) + { + QtNode::QtTrimList::iterator iter; + + // + // The result of input2 has to be a constant expression. + // + + // shift of trimList is just possible, if no open bounds are available + bool openBounds = false; + for( iter=trimList->begin(); iter!=trimList->end() && !openBounds; iter++ ) + openBounds = !((*iter)->interval.is_low_fixed()) || !((*iter)->interval.is_high_fixed()); + + if( openBounds ) + { + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + + RMInit::logOut << "Error: QtShift::optimizeLoad() - spatial domain shift of open bounds is not supported" << endl; + parseInfo.setErrorNo(409); + throw parseInfo; + } + + QtData* operand = input2->evaluate(NULL); + + if( !operand ) + { + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + + RMInit::logOut << "Error: QtShift::optimizeLoad() - second operand of shift function must be a constant expression." << endl; + parseInfo.setErrorNo(408); + throw parseInfo; + } + + if( operand->getDataType() != QT_POINT ) + { + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + + operand->deleteRef(); + + RMInit::logOut << "Error: QtShift::optimizeLoad() - second operand must be of type Point." << endl; + parseInfo.setErrorNo(406); + throw parseInfo; + } + + // get transPoint + const r_Point& transPoint = ((QtPointData*)operand)->getPointData(); + + // shift trim elements by -transPoint + for( iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + QtTrimElement* elem = *iter; + + if( elem->dimension <= transPoint.dimension() ) + elem->interval.set_interval( elem->interval.low() - transPoint[elem->dimension], elem->interval.high() - transPoint[elem->dimension] ); + } + + // point is not needed anymore + operand->deleteRef(); + + input1->optimizeLoad( trimList ); + } + else + { + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + } +} + + + +const QtTypeElement& +QtShift::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtShift", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input1 && input2 ) + { + + // get input types + const QtTypeElement& inputType1 = input1->checkType( typeTuple ); + const QtTypeElement& inputType2 = input2->checkType( typeTuple ); + + if( inputType1.getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtShift::checkType() - first operand must be of type MDD." << endl; + parseInfo.setErrorNo(405); + throw parseInfo; + } + + if( inputType2.getDataType() != QT_POINT ) + { + RMInit::logOut << "Error: QtShift::checkType() - second operand must be of type Point." << endl; + parseInfo.setErrorNo(406); + throw parseInfo; + } + + // pass MDD type + dataStreamType = inputType1; + } + else + RMInit::logOut << "Error: QtShift::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + + +// --- QtExtend -------------------------------------------------- + +const QtNode::QtNodeType QtExtend::nodeType = QT_EXTEND; + +QtExtend::QtExtend( QtOperation* mddOp, QtOperation* mintervalOp ) + : QtBinaryOperation( mddOp, mintervalOp ) +{ +} + + + +bool +QtExtend::isCommutative() const +{ + return false; // NOT commutative +} + + + +QtData* +QtExtend::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtExtend", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; // operation result + QtData* operand1 = NULL; // 1st operand: MDD expression + QtData* operand2 = NULL; // 2nd operand: Minterval expression + vector<Tile*> completeAreaList; // list of tiles comprising the whole area (possibly with holes); needed for 1-code below + + if( getOperands( inputList, operand1, operand2 ) ) + { + // + // This implementation simply creates a single new transient MDD object with the new + // domain while copying the data. + // FIXME: create a tiled object + // + + QtMDD* qtMDDObj = (QtMDD*)operand1; // object to be extended + r_Minterval targetDomain = ((QtMintervalData*)operand2)->getMintervalData(); // new domain of extended object + MDDObj* currentMDDObj = qtMDDObj->getMDDObject(); + + // precondition checks (we call the MDD C and the Minterval M): + // - dim(C) == dim(M) + if( targetDomain.dimension() != qtMDDObj->getLoadDomain().dimension() ) + { + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + RMInit::logOut << "Error: QtExtend::evaluate( QtDataList* ) - dimensionality of MDD and point expression do not match." << endl; + parseInfo.setErrorNo(407); + throw parseInfo; + } + + // - M does not contain open bounds (i.e., "*") + if( ! targetDomain.is_origin_fixed() || ! targetDomain.is_high_fixed() ) + { + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + RMInit::logOut << "Error: QtExtend::evaluate( QtDataList* ) - target domain must not have open bounds." << endl; + parseInfo.setErrorNo(420); + throw parseInfo; + } + // - M.subset( sdom(C) ); can we relieve this? + if( ! targetDomain.covers( qtMDDObj->getLoadDomain() ) ) + { + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + RMInit::logOut << "Error: QtExtend::evaluate( QtDataList* ) - new interval does not cover MDD to be extended." << endl; + parseInfo.setErrorNo(421); + throw parseInfo; + } + + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ) - extending MDD with basetype " << currentMDDObj->getMDDBaseType() << " and load domain " << qtMDDObj->getLoadDomain() << " to domain " << targetDomain << endl; + + // create a transient MDD object for the query result + MDDObj* resultMDD = new MDDObj( currentMDDObj->getMDDBaseType(), targetDomain ); + + // --- 1: put all existing tiles into their place ------------------------ + + // get all tiles + vector<Tile* >* tiles = currentMDDObj->intersect( qtMDDObj->getLoadDomain() ); + + // iterate over source tiles + // Note that source and target MDD have the same coordinate basis + for( vector<Tile*>::iterator tileIter = tiles->begin(); tileIter != tiles->end(); tileIter++ ) + { + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ) - load domain is " << qtMDDObj->getLoadDomain() << endl; + // get relevant area of source tile + r_Minterval sourceTileDomain = qtMDDObj->getLoadDomain().create_intersection( (*tileIter)->getDomain() ); + + Tile* newTransTile = new Tile( sourceTileDomain, currentMDDObj->getCellType() ); + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ) - adding source part " << sourceTileDomain << " of tile " << (*tileIter)->getDomain() << endl; + newTransTile->copyTile( sourceTileDomain, *tileIter, sourceTileDomain ); + + resultMDD->insertTile( newTransTile ); // needed for 2-code below + // completeAreaList.push_back( newTransTile ); // needed for 1-code below + } + + // --- 2: fill up new space with null values ----------------------------- + +#if 0 // this 1-code does the same thing as the 2-code, but easier & more efficiently -- PB 2005-jun-24 + // INCOMPLETE! + // create minimal (1x1) tiles at origin and high end, but only if the source domain isn't there + if (targetDomain.get_origin() != qtMDDObj->getLoadDomain().get_origin()) + { + RMInit::logOut << "QtExtend::evaluate( QtDataList* ) - adding aux tile at origin." << endl; +-> Tile* originTile = new Tile( origin..origin+1 , currentMDDObj->getCellType() ); + extendDomainList.push_back( originTile ); + } + if (targetDomain.get_high() != qtMDDObj->getLoadDomain().get_high()) + { + RMInit::logOut << "QtExtend::evaluate( QtDataList* ) - adding aux tile at high." << endl; +-> Tile* highTile = new Tile( high-1..high, currentMDDObj->getCellType() ); + extendDomainList.push_back( highTile ); + } + + // merge all tiles into one & free not-used-any-longer stuff + Tile* completeTile = new Tile( extendDomainList ); + delete[] extendDomainList; + resultMDD->insertTile( completeTile ); + delete completeTile; + +#else // 2-code; unused -- PB 2005-jun-24 + // the part below does the trick explicitly, leading to a larger number of result tiles. + // establish list of domains + vector<r_Minterval> extendDomainList; + + // inspect 2*d lower/upper neighbours + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ): - inspect 2*d lower/upper neighbours, dimension is " << targetDomain.dimension() << endl; + for (r_Dimension d=0; d<targetDomain.dimension(); d++) + { + // is there any space left of original MDD; ie, has MDD been extended left? + if (targetDomain.get_origin()[d] < qtMDDObj->getLoadDomain().get_origin()[d]) + { + // this domain is identical to original MDD except for dim d where it is left of original + r_Minterval lowerNeighbour = qtMDDObj->getLoadDomain(); + lowerNeighbour[d] = r_Sinterval( targetDomain.get_origin()[d], qtMDDObj->getLoadDomain().get_origin()[d]-1 ); + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ): adding lower neighbour domain " << lowerNeighbour << endl; + extendDomainList.push_back( lowerNeighbour ); + } + // is there any space right of original MDD; ie, has MDD been extended right? + if (targetDomain.get_high()[d] > qtMDDObj->getLoadDomain().get_high()[d]) + { + // this domain is identical to original MDD except for dim d where it is right of original + r_Minterval upperNeighbour = qtMDDObj->getLoadDomain(); + upperNeighbour[d] =r_Sinterval( qtMDDObj->getLoadDomain().get_high()[d]+1, targetDomain.get_high()[d] ); + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ): adding upper neighbour domain " << upperNeighbour << endl; + extendDomainList.push_back( upperNeighbour ); + } + } + + // inspect 2^d corner points + + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ): - inspect 2^d corner neighbours, dimension is " << targetDomain.dimension() << endl; + r_Minterval cornerBoxDomain = r_Minterval( targetDomain.dimension() ); + QtExtend::extendGetCornerTiles( targetDomain, qtMDDObj->getLoadDomain(), 0, targetDomain.dimension(), cornerBoxDomain, &extendDomainList ); + + // merge where possible to minimize tile number + // ...just an optimization, tbd later + + // create tiles for all domains found + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ): - creating " << extendDomainList.size() << " tiles..." << endl; + for( vector<r_Minterval>::iterator domainIter = extendDomainList.begin(); domainIter != extendDomainList.end(); domainIter++ ) + { + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ): creating tile for domain " << (*domainIter) << endl; + Tile* newTransTile = new Tile( *domainIter, currentMDDObj->getCellType() ); + resultMDD->insertTile( newTransTile ); + } +#endif 0 + + // --- 3: package into MDD object & finalize ----------------------------- + + // create a new QtMDD object as carrier object for the transient MDD object + returnValue = new QtMDD( (MDDObj*)resultMDD ); + + // delete the tile vector, the tiles itself are deleted when the destructor + // of the MDD object is called + + delete tiles; + tiles=NULL; + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + // temporary: dump result tile + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ) - result tile = " << newTransTile->printStatus() << endl; + // newTransTile->printStatus(99,RMInit::logOut); + } + + // RMInit::logOut << "QtExtend::evaluate( QtDataList* ) - done." << endl; + return returnValue; +} + +#if 1 // needed for 1-code above -- PB 2005-jun-24 +/** +aux function for QtExtend::evaluate(): build up (recursing the dimension) a list of all spatial domains that sit in the corners between outerDomain and innerDomain; at the recursion bottom the resulting domain is added to the cornerList. +**/ + +void +QtExtend::extendGetCornerTiles( r_Minterval outerDomain, r_Minterval innerDomain, const r_Dimension currentDim, const r_Dimension maxDim, r_Minterval currentInterval, vector<r_Minterval>* cornerList ) +{ + // RMInit::logOut << "QtExtend::extendGetCornerTiles( " << outerDomain << ", " << innerDomain << ", " << currentDim << ", " << maxDim << ", " << currentInterval << ", _ ) start" << endl; + + // not yet addressed all dimensions in the current coordinate? +// note: what about 1D? 0D? + if (currentDim < maxDim) + { + // add domain's lower end, continue building up the minterval + // ...but only if the area is nonempty + if (outerDomain.get_origin()[currentDim] < innerDomain.get_origin()[currentDim]) + { + // make local working copy + r_Minterval extendedInterval( currentInterval ); + // add i-th coordinate to domain, up to (but excluding) innerDomain + extendedInterval[currentDim] = r_Sinterval( outerDomain.get_origin()[currentDim], innerDomain.get_origin()[currentDim]-1 ); + // inspect next dimension + // RMInit::logOut << "QtExtend::extendGetCornerTiles(): recursing for lower end box in next dimension " << currentDim+1 << " using extendedInterval " << extendedInterval << endl; + extendGetCornerTiles( outerDomain, innerDomain, currentDim+1, maxDim, extendedInterval, cornerList ); + } + // add domain's upper end, continue building up the minterval + if (innerDomain.get_high()[currentDim] < outerDomain.get_high()[currentDim]) + { + // make local working copy + r_Minterval extendedInterval( currentInterval ); + // add i-th coordinate to domain, starting from (but excluding) innerDomain + extendedInterval[currentDim] = r_Sinterval( innerDomain.get_high()[currentDim]+1, outerDomain.get_high()[currentDim] ); + // inspect next dimension + // RMInit::logOut << "QtExtend::extendGetCornerTiles(): recursing for upper end box in next dimension " << currentDim+1 << " using extendedInterval " << extendedInterval << endl; + extendGetCornerTiles( outerDomain, innerDomain, currentDim+1, maxDim, extendedInterval, cornerList ); + } + } + else if (currentDim > maxDim) + { + // this is an error, see preconditions + RMInit::logOut << "QtExtend::extendGetCornerTiles(): error: dimension overflow." << endl; + } + else // then we've reached currentDim==maxDim + { + // add this minterval to the tile domain list + cornerList->push_back( currentInterval ); + // RMInit::logOut << "QtExtend::extendGetCornerTiles(): added " << currentInterval << " to tile domain list." << endl; + } + + // RMInit::logOut << "QtExtend::extendGetCornerTiles() done." << endl; +} +#endif 1 + +void +QtExtend::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtExtend Object " << getNodeType() << endl; + + QtBinaryOperation::printTree( tab, s, mode ); +} + + + +void +QtExtend::printAlgebraicExpression( ostream& s ) +{ + s << "extend("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ","; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +void +QtExtend::optimizeLoad( QtTrimList* trimList ) +{ + RMDBCLASS( "QtExtend", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) + + QtNode::QtTrimList *list1=NULL, *list2=NULL; + + if( input1 && input2 ) + { +#if 0 // not yet sure what to do -- PB 2005-06-18 + + QtNode::QtTrimList::iterator iter; + + // + // The result of input2 has to be a constant expression. + // + + // shift of trimList is just possible, if no open bounds are available + bool openBounds = false; + for( iter=trimList->begin(); iter!=trimList->end() && !openBounds; iter++ ) + openBounds = !((*iter)->interval.is_low_fixed()) || !((*iter)->interval.is_high_fixed()); + + if( openBounds ) + { + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + + RMInit::logOut << "Error: QtExtend::optimizeLoad() - spatial domain shift of open bounds is not supported" << endl; +// XXX need new error code + parseInfo.setErrorNo(409); + throw parseInfo; + } + + QtData* operand = input2->evaluate(NULL); + + if( !operand ) + { + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + + RMInit::logOut << "Error: QtExtend::optimizeLoad() - second operand of extend function must be a constant expression." << endl; +// XXX correct new error code + parseInfo.setErrorNo(408); + throw parseInfo; + } + + if( operand->getDataType() != QT_MINTERVAL ) + { + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + + operand->deleteRef(); + + RMInit::logOut << "Error: QtExtend::optimizeLoad() - second operand must be of type Minterval." << endl; +// XXX correct new error code + parseInfo.setErrorNo(406); + throw parseInfo; + } + + // get extend target domain + const r_Minterval& targetDomain = ((QtPointData*)operand)->getMintervalData(); + + // shift trim elements by -transPoint + // XXX replace with extend() code + for( iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + QtTrimElement* elem = *iter; + + if( elem->dimension <= transPoint.dimension() ) + elem->interval.set_interval( elem->interval.low() - transPoint[elem->dimension], elem->interval.high() - transPoint[elem->dimension] ); + } + + // point is not needed anymore + operand->deleteRef(); +#endif 0 // not yet sure what to do -- PB 2005-06-18 + + input1->optimizeLoad( trimList ); + } + else + { + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + } +} + + + +const QtTypeElement& +QtExtend::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtExtend", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input1 && input2 ) + { + + // get input types + const QtTypeElement& inputType1 = input1->checkType( typeTuple ); + const QtTypeElement& inputType2 = input2->checkType( typeTuple ); + + if( inputType1.getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtExtend::checkType() - first operand must be of type MDD." << endl; + parseInfo.setErrorNo(405); + throw parseInfo; + } + + if( inputType2.getDataType() != QT_MINTERVAL ) + { + RMInit::logOut << "Error: QtExtend::checkType() - second operand must be of type Minterval." << endl; + parseInfo.setErrorNo(422); + throw parseInfo; + } + + // pass MDD type + dataStreamType = inputType1; + } + else + RMInit::logOut << "Error: QtExtend::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + + + +// --- QtScale -------------------------------------------------- + +const QtNode::QtNodeType QtScale::nodeType = QT_SCALE; + +QtScale::QtScale( QtOperation* mddOp, QtOperation* pointOp ) + : QtBinaryOperation( mddOp, pointOp ) +{ +} + + + +bool +QtScale::isCommutative() const +{ + return false; // NOT commutative +} + +#include <iomanip> +#include <math.h> + +// this define was used during testing, we had a problem +inline double FLOOR(double a) { + return floor(a); +} + +QtData* +QtScale::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtScale", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtData* operand1 = NULL; + QtData* operand2 = NULL; + + if(!getOperands( inputList, operand1, operand2 ) ) + return returnValue; + + QtMDD* qtMDDObj = (QtMDD*)operand1; + MDDObj* currentMDDObj = qtMDDObj->getMDDObject(); + vector<r_Double> scaleVector(0); + + scaleVector = vector<r_Double>( qtMDDObj->getLoadDomain().dimension() ); + + r_Minterval sourceDomain = qtMDDObj->getLoadDomain(); + r_Minterval targetDomain; + r_Point origin1 = sourceDomain.get_origin(); + r_Point origin2 = qtMDDObj->getMDDObject()->getCurrentDomain().get_origin(); + + r_Minterval wishedTargetDomain; + r_Point translation; + + //used for scale with wishedIv + bool isWishedTargetSet = false; + r_Double sourceRange=0., targetRange=0., f=0., Tl=0., Th=0.; + + switch( operand2->getDataType() ) + { + case QT_POINT: + { + const r_Point& transPoint = ((QtPointData*)operand2)->getPointData(); + + if( transPoint.dimension() != qtMDDObj->getLoadDomain().dimension() ) + { + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + RMInit::logOut << "Error: QtScale::evaluate( QtDataList* ) - dimensionalities of MDD and scale expression are not matching." << endl; + parseInfo.setErrorNo(418); + throw parseInfo; + } + + for( int i=0; i<scaleVector.size(); i++ ) + scaleVector[i] = transPoint[i]; + } + break; + + case QT_CHAR: + case QT_USHORT: + case QT_ULONG: + { + for( int i=0; i<scaleVector.size(); i++ ) + scaleVector[i] = ((QtAtomicData*)operand2)->getUnsignedValue();; + } + break; + + case QT_OCTET: + case QT_SHORT: + case QT_LONG: + { + for( int i=0; i<scaleVector.size(); i++ ) + scaleVector[i] = ((QtAtomicData*)operand2)->getSignedValue();; + } + break; + + case QT_DOUBLE: + case QT_FLOAT: + { + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtScale", "Scaling: " << ((QtAtomicData*)operand2)->getDoubleValue() ) + for( int i=0; i<scaleVector.size(); i++ ) + scaleVector[i] = ((QtAtomicData*)operand2)->getDoubleValue(); + } + break; + + case QT_MINTERVAL: + { + wishedTargetDomain = ((QtMintervalData*)operand2)->getMintervalData(); + isWishedTargetSet=true; + + if( wishedTargetDomain.dimension() != sourceDomain.dimension()) + { + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + RMInit::logOut << "Error: QtScale::evaluate( QtDataList* ) - dimensionalities of MDD and scale expression are not matching." << endl; + parseInfo.setErrorNo(418); + throw parseInfo; + } + + for( int i=0; i<scaleVector.size(); i++ ) + { + sourceRange = (r_Double)sourceDomain[i].get_extent(); + targetRange = (r_Double)wishedTargetDomain[i].get_extent(); + + if(sourceRange != 0.) + { + scaleVector[i] = targetRange / sourceRange; + f = scaleVector[i]; + + Tl = FLOOR(f*sourceDomain[i].low()); + //correction by 1e-6 to avoid the strage bug when Th was a + //integer value and floor return value-1(e.g. query 47.ql) + Th = FLOOR(f*(sourceDomain[i].high()+1) + 0.000001)-1; + +// FIXME BUG if(Tl != Th) +// Th--; + + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtScale", "Scale: before f="<<setprecision(12)<<f) + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtScale", "Scale: " << endl + <<"precalculated: "<<Tl<<':'<<Th<<"<-->"<<wishedTargetDomain[i].low()<<':'<<wishedTargetDomain[i].high()<<endl + <<"pro memoria: "<<(r_Range)(f*(sourceDomain[i].high()+1))<<", "<<(f*(sourceDomain[i].high()+1)) + <<", "<<floor(f*(sourceDomain[i].high()+1)) + <<", "<<ceil(f*(sourceDomain[i].high()+1))) + + if( (Th-Tl+1) != targetRange ) + { + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtScale", "Scale: correction necessary: "<<Tl<<':'<<Th<<"<-->"<<wishedTargetDomain[i].low()<<':'<<wishedTargetDomain[i].high()) + + f = f + (targetRange - (Th-Tl+1))/sourceRange; + + // cout<<"f="<<setprecision(12)<<f<<" scale[i]="<<setprecision(12)<<scaleVector[i]<<endl; + + Tl = FLOOR(f*sourceDomain[i].low()); + //correction by 1e-6 to avoid the strage bug when Th was a + //integer value and floor return value-1(e.g. query 47.ql) + Th = FLOOR(f*(sourceDomain[i].high()+1) + 0.000001)-1; +// FIXME BUG if(Tl != Th) +// Th--; + + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtScale", "Scale: ->: "<<Tl<<':'<<Th<<"<-->"<<wishedTargetDomain[i].low()<<':'<<wishedTargetDomain[i].high()) + + scaleVector[i]=f; + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtScale", "Scale: after f="<<setprecision(12)<<f) + } + } + else + { + scaleVector[i] =0; //exception? it can't heapen, this error is filtered long before reaching this point + } + } + } + break; + default: + RMDBGONCE(0, RMDebug::module_qlparser, "r_QtScale", "evaluate() bad type operand2" << operand2->getDataType()); + break; + } + +// ---------------------------------------------------------- + +#ifdef RMANDEBUG + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtScale", "Scale vector : " ) + for( int i=0; i<scaleVector.size(); i++ ) + { + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtScale", scaleVector[i] << "," ) + } +#endif + + // scale domain + if( !scaleDomain( sourceDomain, scaleVector, targetDomain ) ) + { + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + RMInit::logOut << "Error: QtScale::evaluate( QtDataList* ) - empty result after scaling." << endl; + parseInfo.setErrorNo(419); + throw parseInfo; + } + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtBinaryFunc", "Dummy target domain: " << targetDomain << endl ) + + if(isWishedTargetSet) + { + translation = wishedTargetDomain.get_origin() - targetDomain.get_origin(); + targetDomain.translate(translation); + } + + // create a transient MDD object for the query result + MDDObj* resultMDD = new MDDObj( currentMDDObj->getMDDBaseType(), targetDomain ); + + //********************** + origin1 = r_Point(scaleVector.size()); // all zero!! + //********************** + + // get all tiles + vector<Tile* >* tiles = currentMDDObj->intersect( qtMDDObj->getLoadDomain() ); + + //tile domain before & after + r_Minterval sourceTileDomain, destinationTileDomain; + + // + // Algorithm A: Scale each Tile + // + + // iterate over source tiles + for( vector<Tile*>::iterator tileIter = tiles->begin(); tileIter != tiles->end(); tileIter++ ) + { + // get relevant area of source tile + sourceTileDomain = qtMDDObj->getLoadDomain().create_intersection( (*tileIter)->getDomain() ); + + // compute scaled tile domain and check if it exists + if( (*tileIter)->scaleGetDomain( sourceTileDomain, scaleVector, destinationTileDomain) ) + { + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtBinaryFunc", "Destination tile domain: " << destinationTileDomain << endl ) + // create a new transient tile + Tile* newTransTile = new Tile( destinationTileDomain, currentMDDObj->getCellType() ); + newTransTile->execScaleOp( *tileIter, sourceTileDomain, origin1, scaleVector ); + + if(isWishedTargetSet) + ((r_Minterval&)newTransTile->getDomain()).translate(translation); + + resultMDD->insertTile( newTransTile ); + } + } + + // create a new QtMDD object as carrier object for the transient MDD object + returnValue = new QtMDD( (MDDObj*)resultMDD ); + + // delete the tile vector, the tiles itself are deleted when the destructor + // of the MDD object is called + delete tiles; + tiles=NULL; + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + return returnValue; +} + + +void +QtScale::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtScale Object " << getNodeType() << endl; + + QtBinaryOperation::printTree( tab, s, mode ); +} + + + +void +QtScale::printAlgebraicExpression( ostream& s ) +{ + s << "scale("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ","; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +void +QtScale::optimizeLoad( QtTrimList* trimList ) +{ + RMDBCLASS( "QtScale", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) + + // by default, pass load domain to input1 + if( input1 ) + input1->optimizeLoad( trimList ); + else + { + delete trimList; + trimList=NULL; + } +} + + + +const QtTypeElement& +QtScale::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtScale", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input1 && input2 ) + { + + // get input types + const QtTypeElement& inputType1 = input1->checkType( typeTuple ); + const QtTypeElement& inputType2 = input2->checkType( typeTuple ); + + if( inputType1.getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtScale::checkType() - first operand must be of type MDD." << endl; + parseInfo.setErrorNo(416); + throw parseInfo; + } + + if( inputType2.getDataType() != QT_POINT && inputType2.getDataType() != QT_MINTERVAL && + inputType2.getDataType() != QT_FLOAT && inputType2.getDataType() != QT_DOUBLE && + !inputType2.isInteger() ) + { + RMInit::logOut << "Error: QtScale::checkType() - second operand must be either of type Point, Integer or Float." << endl; + parseInfo.setErrorNo(417); + throw parseInfo; + } + + // pass MDD type + dataStreamType = inputType1; + } + else + RMInit::logOut << "Error: QtScale::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + + +int QtScale::scaleDomain( const r_Minterval& areaOp, + const vector<double>& scaleFactors, + r_Minterval &areaScaled ) +{ + RMDBGENTER( 2, RMDebug::module_qlparser, "QtScale", + "scaleDomain( D: " << areaOp << ", F: " << scaleFactors << ", D: " << areaScaled << " )" ) + + try + { + areaScaled = areaOp.create_scale(scaleFactors); + } + catch(r_Error) + { + //error scaling + RMInit::logOut << "Error: QtScale::scaleDomain() - exception while determining scale target interval for " << areaOp << " and " << scaleFactors << endl; + return 0; + } + + RMDBGEXIT( 2, RMDebug::module_qlparser, "QtScale", "scaleDomain(...) D: " << areaOp << " mapped to D: " << areaScaled ) + + return 1; +} + +// origin1 von getLoadDomain +// origin2 von getCurrentDomain + +int QtScale::scaleDomain( const r_Minterval& areaOp, const r_Point& origin1, const r_Point& origin2, + const vector<double>& scaleFactors, r_Minterval &areaScaled ) +{ + RMDBGENTER( 2, RMDebug::module_qlparser, + "QtScale", "scaleDomain( D: " << areaOp << ", O1: " << origin1 << ", O2: " << origin2 + << ", F: " << scaleFactors << " D: " << areaScaled << " )" ) + + r_Minterval tempIv=areaOp; + + //reverse_translated with origin1 + tempIv.reverse_translate(origin1); + + //scale it normaly + if(!scaleDomain(tempIv, scaleFactors, areaScaled)) + return 0; + + //translate areaScaled to origin2 + areaScaled.translate(origin2); + + RMDBGEXIT( 2, RMDebug::module_qlparser, "QtScale", "scaledDomain(...) D: " << areaOp << " translated to D: " << areaScaled ) + + return 1; +} + diff --git a/qlparser/qtbinaryfunc.hh b/qlparser/qtbinaryfunc.hh new file mode 100644 index 0000000..a96a877 --- /dev/null +++ b/qlparser/qtbinaryfunc.hh @@ -0,0 +1,201 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _QTBINARYFUNC_ +#define _QTBINARYFUNC_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtbinaryoperation.hh" +#include "raslib/sinterval.hh" +#include "raslib/minterval.hh" +#include <vector> +/************************************************************* + * + * + * COMMENTS: + * - why is this "binary"? they all have just one MDD! + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents a shift operation on MDD objects. + +*/ + +class QtShift : public QtBinaryOperation +{ + public: + /// constructor getting the two operands + QtShift( QtOperation* mddOp, QtOperation* pointOp ); + + /// returns FALSE saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + /** + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents an extend operation on MDD objects. + +*/ + +class QtExtend : public QtBinaryOperation +{ + public: + /// constructor getting the two operands + QtExtend( QtOperation* mddOp, QtOperation* mintervalOp ); + /** + FIXME: creates one single output tile, but should have a result tiling + */ + + /// returns FALSE saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + /** + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /** + aux function for QtExtend::evaluate(): build up (recursing the dimension) a list of all spatial domains that sit in the corners between outerDomain and innerDomain; at the recursion bottom the resulting domain is added to the cornerList. + Preconditions: + - outerDomain, innerDomain defined values, of dimension maxDim + - currentDimension <= maxDim + - currentInterval has coordinates (no "*") set up to dimension currentDimension + @params outerDomain extended domain + @params innerDomain inner domain + @params currentDim current dimension to be inspected (0..maxDim) + @params maxDim maximum dimension to be inspected (#dimensions-1, suitable for indexing an r_Point or r_Minterval) + @params currentInterval current interval which is being built by iterating over its dimensions + @params cornerList list of corner intervals that is to be built; has to be deallocated by caller. + **/ + void extendGetCornerTiles( r_Minterval outerDomain, r_Minterval innerDomain, r_Dimension currentDim, r_Dimension maxDim, r_Minterval currentInterval, vector<r_Minterval>* cornerList ); + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents a scale operation on MDD objects. + +*/ + +class QtScale : public QtBinaryOperation +{ + public: + /// constructor getting the two operands + QtScale( QtOperation* mddOp, QtOperation* pointOp ); + + /// returns FALSE saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + /** + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + /// scale domains - initial version + virtual int scaleDomain( const r_Minterval& areaOp, const r_Point& origin1, const r_Point& origin2, const vector<double>& scaleFactors, r_Minterval &areaScaled ); + + /// scale domains - the used version + virtual int scaleDomain( const r_Minterval& areaOp, const vector<double>& scaleFactors, r_Minterval &areaScaled ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtbinaryfunc.icc" + +#endif + diff --git a/qlparser/qtbinaryfunc.icc b/qlparser/qtbinaryfunc.icc new file mode 100644 index 0000000..a808b4a --- /dev/null +++ b/qlparser/qtbinaryfunc.icc @@ -0,0 +1,47 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtShift::getNodeType() const +{ + return nodeType; +} + +inline const QtNode::QtNodeType +QtExtend::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtScale::getNodeType() const +{ + return nodeType; +} diff --git a/qlparser/qtbinaryinduce.cc b/qlparser/qtbinaryinduce.cc new file mode 100644 index 0000000..9f7b1ba --- /dev/null +++ b/qlparser/qtbinaryinduce.cc @@ -0,0 +1,959 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtBinaryInduce: $Id: qtbinaryinduce.cc,v 1.47 2003/12/27 20:39:35 rasdev Exp $"; + +#include "raslib/rmdebug.hh" +#include "debug.hh" + +#include "qlparser/qtbinaryinduce.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtcomplexdata.hh" +#include "qlparser/qtconst.hh" +#include "qlparser/qtstringdata.hh" + +#include "mddmgr/mddobj.hh" + +#include "catalogmgr/typefactory.hh" +#include "relcatalogif/mdddomaintype.hh" + +#include "tilemgr/tile.hh" + +#include <iostream> +#include <string> +#include <vector> +#include <memory> +using namespace std; + +const QtNode::QtNodeType QtBinaryInduce::nodeType = QtNode::QT_BINARY_INDUCE; + +QtBinaryInduce::QtBinaryInduce( QtOperation* initInput1, QtOperation* initInput2, Ops::OpType initOpType ) + : QtBinaryOperation( initInput1, initInput2 ), + opType( initOpType ) +{ +} + + + +QtData* +QtBinaryInduce::computeOp( QtData* operand1, QtData* operand2 ) +{ + RMDBCLASS( "QtBinaryInduce", "computeOp( QtData*, QtData* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + + if ( operand1->getDataType() == QT_MDD && + operand2->getDataType() == QT_MDD ) + { + QtMDD* mdd1 = (QtMDD*) operand1; + QtMDD* mdd2 = (QtMDD*) operand2; + + const BaseType* resultBaseType = ((MDDBaseType*)(dataStreamType.getType()))->getBaseType(); + + returnValue = computeBinaryMDDOp( mdd1, mdd2, resultBaseType ); + } + else if( operand1->getDataType() == QT_MDD && + operand2->isScalarData() ) + { + QtMDD* mdd = (QtMDD*) operand1; + QtScalarData* scalar = (QtScalarData*) operand2; + + const BaseType* resultBaseType = ((MDDBaseType*)(dataStreamType.getType()))->getBaseType(); + + returnValue = computeUnaryMDDOp( mdd, scalar, resultBaseType, 2 ); + } + else if( operand1->isScalarData() && + operand2->getDataType() == QT_MDD ) + { + QtMDD* mdd = (QtMDD*) operand2; + QtScalarData* scalar = (QtScalarData*) operand1; + + const BaseType* resultBaseType = ((MDDBaseType*)(dataStreamType.getType()))->getBaseType(); + + returnValue = computeUnaryMDDOp( mdd, scalar, resultBaseType, 1 ); + } + else if( operand1->isScalarData() && + operand2->isScalarData() ) + { + QtScalarData* scalar1 = (QtScalarData*) operand1; + QtScalarData* scalar2 = (QtScalarData*) operand2; + + BaseType* resultBaseType = (BaseType*)(dataStreamType.getType()); + + returnValue = computeBinaryOp( scalar1, scalar2, resultBaseType ); + } + else if( operand1->getDataType() == QT_STRING && operand2->getDataType() == QT_STRING ) + { + // opType == Ops::OP_EQUAL + QtStringData* strObj1 = (QtStringData*) operand1; + QtStringData* strObj2 = (QtStringData*) operand2; + + bool booleanResult = strObj1->getStringData() == strObj2->getStringData(); + + returnValue = new QtAtomicData( booleanResult ); + } + + return returnValue; +} + + + +QtData* +QtBinaryInduce::computeUnaryMDDOp( QtMDD* operand1, QtScalarData* operand2, const BaseType* resultBaseType, int scalarPos ) +{ + RMDBCLASS( "QtBinaryInduce", "computeUnaryMDDOp( QtMDD*, QtScalarData*, BaseType*, int )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + + // get the MDD object + MDDObj* op = operand1->getMDDObject(); + + // create ULong type with QtIntData value + const BaseType* constBaseType = operand2->getValueType(); + const char* constValue = operand2->getValueBuffer(); + + // get the area, where the operation has to be applied + const r_Minterval &areaOp = operand1->getLoadDomain(); + + // contains all tiles of the operand + vector<Tile*>* allTiles=NULL; + + // iterator for tiles + vector<Tile*>::iterator tileIt; + + // create MDDObj for result + MDDDomainType* mddBaseType = new MDDDomainType( "tmp", resultBaseType, areaOp ); + TypeFactory::addTempType( mddBaseType ); + + MDDObj* mddres = new MDDObj( mddBaseType, areaOp ); + + // get all tiles in relevant area + allTiles = op->intersect(areaOp); + tileIt = allTiles->begin(); + //auto_ptr<BinaryOp> myOp(NULL); + BinaryOp* myOp = NULL; + if (tileIt != allTiles->end()) + { + if (scalarPos == 1) + //myOp.reset(Ops::getBinaryOp(opType, resultBaseType, constBaseType, (*tileIt)->getType())); + myOp = (Ops::getBinaryOp(opType, resultBaseType, constBaseType, (*tileIt)->getType())); + else + //myOp.reset(Ops::getBinaryOp(opType, resultBaseType, (*tileIt)->getType(), constBaseType)); + myOp = (Ops::getBinaryOp(opType, resultBaseType, (*tileIt)->getType(), constBaseType)); + } + // and iterate over them + for( ; tileIt != allTiles->end(); tileIt++ ) + { + // domain of the actual tile + const r_Minterval &tileDom = (*tileIt)->getDomain(); + + // domain of the relevant area of the actual tile + r_Minterval intersectDom( tileDom.create_intersection( areaOp ) ); + + // create tile for result + Tile* resTile = new Tile( intersectDom, resultBaseType ); + + // + // carry out operation on the relevant area of the tiles + // + + RMDBGIF( 4, RMDebug::module_qlparser, "QtScale", \ + char* typeStructure = resTile->getType()->getTypeStructure(); \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " result tile, area " << intersectDom << \ + ", type " << resTile->getType()->getTypeName() << \ + ", structure " << typeStructure << endl ) \ + free( typeStructure ); typeStructure=NULL; \ + \ + typeStructure = (*tileIt)->getType()->getTypeStructure(); \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " operand1 tile, area " << intersectDom << \ + ", type " << (*tileIt)->getType()->getTypeName() << \ + ", structure " << typeStructure << endl ) \ + free( typeStructure ); typeStructure=NULL; \ + + typeStructure = constBaseType->getTypeStructure(); \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " constant type " << constBaseType->getTypeName() << \ + ", structure " << typeStructure << \ + ", value " ) \ + free( typeStructure ); typeStructure=NULL; \ + \ + for( int x=0; x<constBaseType->getSize(); x++ ) \ + RMInit::dbgOut << hex << (int)(constValue[x]); \ + RMInit::dbgOut << dec << endl; \ + ) + + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " before execConstOp" << endl ) + + resTile->execConstOp( myOp, intersectDom, (*tileIt), intersectDom, constValue, scalarPos ); + //resTile->execConstOp( opType, intersectDom, (*tileIt), intersectDom, constValue, constBaseType, scalarPos ); + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " after execConstOp" << endl ) + + // insert Tile in result tile + mddres->insertTile( resTile ); + } + delete myOp; + myOp = NULL; + + // delete tile vector + delete allTiles; + allTiles=NULL; + + // create a new QtMDD object as carrier object for the transient MDD object + returnValue = new QtMDD( (MDDObj*)mddres ); + + // The following is now done, when the last reference is deleted. + // delete the obsolete MDD object + // delete op; + + return returnValue; +} + + + +QtData* +QtBinaryInduce::computeBinaryMDDOp( QtMDD* operand1, QtMDD* operand2, const BaseType* resultBaseType ) +{ + RMDBCLASS( "QtBinaryInduce", "computeBinaryMDDOp( QtMDD*, QtMDD*, BaseType* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + + // get the MDD objects + MDDObj* op1 = operand1->getMDDObject(); + MDDObj* op2 = operand2->getMDDObject(); + + // get the areas, where the operation has to be applied + const r_Minterval &areaOp1 = operand1->getLoadDomain(); + const r_Minterval &areaOp2 = operand2->getLoadDomain(); + + // Check, if the domains are compatible which means that they have the same + // dimensionality and each dimension has the same number of elements. + if( areaOp1.get_extent() == areaOp2.get_extent() ) + { + // contains all tiles of op1 + vector<Tile*>* allTilesOp1=NULL; + + // contains all tiles of op2 which intersect a given op1 Tile in the relevant area. + vector<Tile*>* intersectTilesOp2=NULL; + + // iterators for tiles of the MDDs + vector<Tile*>::iterator tileOp1It; + vector<Tile*>::iterator intersectTileOp2It; + + // intersection of domains in relevant area. + r_Minterval intersectDom; + + // pointer to generated result tile + Tile* resTile=NULL; + + // MDDObj for result + MDDObj* mddres=NULL; + + // translations between the two areas + r_Point offset12(areaOp1.dimension()); + r_Point offset21(areaOp1.dimension()); + + // calculate translations + r_Point originOp1 = areaOp1.get_origin(); + r_Point originOp2 = areaOp2.get_origin(); + for(r_Dimension i = 0; i<areaOp1.dimension(); i++) + { + offset12[i] = originOp2[i] - originOp1[i]; + offset21[i] = originOp1[i] - originOp2[i]; + } + + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " Domain op1 " << areaOp1 << " op2 " << areaOp2 ) + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " Translation vector " << offset12 ) + + // create MDDObj for result + MDDDomainType* mddBaseType = new MDDDomainType( "tmp", resultBaseType, areaOp1 ); + TypeFactory::addTempType( mddBaseType ); + + mddres = new MDDObj( mddBaseType, areaOp1 ); + + // get all tiles in relevant area of MDD op1 + allTilesOp1 = op1->intersect(areaOp1); + + // cout << "INTERSECT" << areaOp1 << endl; + // for( tileOp1It = allTilesOp1->begin(); tileOp1It != allTilesOp1->end(); tileOp1It++ ) + // cout << (*tileOp1It)->getDomain() << endl; + + // and iterate over them + auto_ptr<BinaryOp> myOp(Ops::getBinaryOp(opType, mddBaseType->getBaseType(), op1->getCellType(), op2->getCellType())); + for( tileOp1It = allTilesOp1->begin(); tileOp1It != allTilesOp1->end(); tileOp1It++ ) + { + // domain of the op1 tile + const r_Minterval &tileOp1Dom = (*tileOp1It)->getDomain(); + + // relevant area of op1's domain + r_Minterval intersectionTileOp1Dom( tileOp1Dom.create_intersection( areaOp1 ) ); + + // intersect relevant area of the tile with MDD op2 (including translation) + intersectTilesOp2 = op2->intersect(intersectionTileOp1Dom.create_translation(offset12)); + + // cout << "INTERSECT" << tileOp1Dom.create_translation(offset12) << endl; + // for( intersectTileOp2It = intersectTilesOp2->begin(); + // intersectTileOp2It != intersectTilesOp2->end(); + // intersectTileOp2It++ ) + // cout << (*intersectTileOp2It)->getDomain() << endl; + + // iterate over intersecting tiles + for( intersectTileOp2It = intersectTilesOp2->begin(); + intersectTileOp2It != intersectTilesOp2->end(); + intersectTileOp2It++ ) + { + const r_Minterval &tileOp2Dom = (*intersectTileOp2It)->getDomain(); + + // the relevant domain is the intersection of the + // domains of the two tiles with the relevant area. + intersectDom = tileOp1Dom.create_intersection(tileOp2Dom.create_translation(offset21)); + + intersectDom.intersection_with(areaOp1); + + // create tile for result + resTile = new Tile( intersectDom, resultBaseType ); + + // + // carry out operation on the relevant area of the tiles + // + + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " before execBinaryOp" << endl ) + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " result tile, area " << intersectDom << + ", type " << resTile->getType()->getTypeName() << endl ) + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " operand1 tile, area " << intersectDom << + ", type " << (*tileOp1It)->getType()->getTypeName() << endl ) + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " operand2 tile, type " << (*tileOp1It)->getType()->getTypeName() << endl ) + resTile->execBinaryOp(&(*myOp), intersectDom, (*tileOp1It), intersectDom, (*intersectTileOp2It), intersectDom.create_translation(offset12)); + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", " after execBinaryOp" << endl ) + + // insert Tile in result mddobj + mddres->insertTile( resTile ); + } + + delete intersectTilesOp2; + intersectTilesOp2=NULL; + } + + delete allTilesOp1; + allTilesOp1=NULL; + + // create a new QtMDD object as carrier object for the transient MDD object + returnValue = new QtMDD( (MDDObj*)mddres ); + } + else + { + RMInit::logOut << "Error: QtBinaryInduce::computeBinaryMDDOp() - domains of the operands are incompatible." << endl; + RMInit::logOut << "areaOp1 " << areaOp1 << " with extent " << areaOp1.get_extent() << endl; + RMInit::logOut << "areaOp2 " << areaOp2 << " with extent " << areaOp2.get_extent() << endl; + + parseInfo.setErrorNo(351); + throw parseInfo; + } + + // The following is now done, when the last reference is deleted. + // delete obsolete MDD objects + // delete op1; + // delete op2; + + return returnValue; +} + + + +QtData* +QtBinaryInduce::computeBinaryOp( QtScalarData* operand1, QtScalarData* operand2, const BaseType* resultBaseType ) +{ + RMDBCLASS( "QtBinaryInduce", "computeBinaryOp( QtScalarData*, QtScalarData*, BaseType*, Ops::OpType )", "qlparser", __FILE__, __LINE__ ) + + QtScalarData* scalarDataObj = NULL; + + // allocate memory for the result + char* resultBuffer = new char[ resultBaseType->getSize() ]; + + Ops::execBinaryConstOp( opType, resultBaseType, + operand1->getValueType(), operand2->getValueType(), + resultBuffer, + operand1->getValueBuffer(), operand2->getValueBuffer() ); + + if( resultBaseType->getType() == STRUCT ) + scalarDataObj = new QtComplexData(); + else + scalarDataObj = new QtAtomicData(); + + scalarDataObj->setValueType ( resultBaseType ); + scalarDataObj->setValueBuffer( resultBuffer ); + + return scalarDataObj; +} + + + +QtData* +QtBinaryInduce::evaluate( QtDataList* inputList ) +{ + QtData* returnValue = NULL; + QtData* operand1 = NULL; + QtData* operand2 = NULL; + + if( getOperands( inputList, operand1, operand2 ) ) + { + returnValue = computeOp( operand1, operand2 ); + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + } + return returnValue; +} + + + +const QtTypeElement& +QtBinaryInduce::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtBinaryInduce", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input1 && input2 ) + { + + // get input types + const QtTypeElement& inputType1 = input1->checkType( typeTuple ); + const QtTypeElement& inputType2 = input2->checkType( typeTuple ); + + RMDBGIF( 1, RMDebug::module_qlparser, "QtBinaryInduce", \ + RMInit::dbgOut << "Operand 1: " << flush; \ + inputType1.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + \ + RMInit::dbgOut << "Operand 2: " << flush; \ + inputType2.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtBinaryInduce", "Operation " << opType ) \ + ) + + if( inputType1.getDataType() == QT_MDD && + inputType2.getDataType() == QT_MDD ) + { + const BaseType* baseType1 = ((MDDBaseType*)(inputType1.getType()))->getBaseType(); + const BaseType* baseType2 = ((MDDBaseType*)(inputType2.getType()))->getBaseType(); + + const BaseType* resultBaseType = Ops::getResultType( opType, baseType1, baseType2 ); + + if( !resultBaseType ) + { + RMInit::logOut << "Error: QtBinaryInduce::checkType() - binary induce (MDD + MDD): operand types are incompatible." << endl; + parseInfo.setErrorNo(363); + throw parseInfo; + } + + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + + dataStreamType.setType( resultMDDType ); + } + else if( inputType1.getDataType() == QT_MDD && + inputType2.isBaseType() ) + { + const BaseType* baseType1 = ((MDDBaseType*)(inputType1.getType()))->getBaseType(); + BaseType* baseType2 = (BaseType*)(inputType2.getType()); + + const BaseType* resultBaseType = Ops::getResultType( opType, baseType1, baseType2 ); + + if( !resultBaseType ) + { + RMInit::logOut << "Error: QtBinaryInduce::checkType() - unary induce (MDD + BaseType): operand types are incompatible." << endl; + parseInfo.setErrorNo(364); + throw parseInfo; + } + + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + + dataStreamType.setType( resultMDDType ); + } + else if( inputType1.isBaseType() && + inputType2.getDataType() == QT_MDD ) + { + BaseType* baseType1 = (BaseType*)(inputType1.getType()); + const BaseType* baseType2 = ((MDDBaseType*)(inputType2.getType()))->getBaseType(); + + const BaseType* resultBaseType = Ops::getResultType( opType, baseType1, baseType2 ); + + if( !resultBaseType ) + { + RMInit::logOut << "Error: QtBinaryInduce::checkType() - unary induce (BaseType + MDD): operand types are incompatible." << endl; + parseInfo.setErrorNo(364); + throw parseInfo; + } + + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + + dataStreamType.setType( resultMDDType ); + } + else if( inputType1.isBaseType() && + inputType2.isBaseType() ) + { + BaseType* baseType1 = (BaseType*)(inputType1.getType()); + BaseType* baseType2 = (BaseType*)(inputType2.getType()); + + const BaseType* resultBaseType = Ops::getResultType( opType, baseType1, baseType2 ); + + if( !resultBaseType ) + { + RMInit::logOut << "Error: QtBinaryInduce::checkType() - BaseType + BaseType : operand types are incompatible." << endl; + + parseInfo.setErrorNo(365); + throw parseInfo; + } + + dataStreamType.setType( resultBaseType ); + } + else if( inputType1.getDataType() == QT_STRING && + inputType2.getDataType() == QT_STRING ) + { + if( opType != Ops::OP_EQUAL ) + { + RMInit::logOut << "Error: QtBinaryInduce::checkType() - String + String : operation is not supported on strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + + dataStreamType.setDataType( QT_BOOL ); + } + else + { + RMInit::logOut << "Error: QtBinaryInduce::checkType() - operation is not supported on these data types." << endl; + parseInfo.setErrorNo(403); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtBinaryInduce::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + + + +const QtNode::QtNodeType QtPlus::nodeType = QT_PLUS; + +QtPlus::QtPlus( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_PLUS ) +{ +} + + +/* +void +QtPlus::rewriteOps() +{ + RMDBCLASS( "QtPlus", "rewriteOps()", "qlparser", __FILE__, __LINE__ ) + + if( input1 && input2 ) + { + if( nodeType == input2->getNodeType() ) + { + // changed from log to debug output -- PB 2003-nov-20 + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtPlus", "rewriteOps: rule (left deep tree): A+(B+C) -> (B+C)+A" ); + + // more than one equal binary operator, make standard form of the tree + + QtBinaryOperation* nodeR = (QtBinaryOperation*) input2; + QtOperation* nodeRL = nodeR->getInput1(); + + getParent()->setInput( this, nodeR ); + nodeR->setInput1( this ); + this->setInput2( nodeRL ); + nodeR->rewriteOps(); + } + else + { + input1->rewriteOps(); + input2->rewriteOps(); + } + } + else + RMInit::logOut << "Error: QtPlus::rewriteOps() - the operand branch is invalid." << endl; +} +*/ + +/* +void +QtPlus::sortAssociativeOps() +{ + ENTER( "QtPlus::sortAssociativeOps() -- input1 is " << (input1?"not null":"null") << ", input 2 is " << (input2?"not null":"null") ); + + if( input1 && input2 ) + { + if( nodeType == input1->getNodeType() ) + { + // associative law is applicable + + QtOperation* node = input1->getUniqueOrder( nodeType ); + + if( node && node->getSpelling().compare( input2->getSpelling() ) > 0 ) + { + node->getParent()->setInput( node, input2 ); + setInput2( node ); + } + } + else + { + bool compare = ( input1->getSpelling().compare( input2->getSpelling() ) > 0 ); + TALK( "QtPlus::sortAssociativeOps(): compare -> " << compare ); + if( compare ) + { + // changed from log to debug output -- PB 2003-nov-20 + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtPlus", "sortAssociativeOps: applying rule 'associativity'" ); + + QtOperation* node = input1; + + setInput1( input2 ); + setInput2( node ); + }; + + }; + + input1->sortAssociativeOps(); + } + else + RMInit::logOut << "Error: QtPlus::sortAssociativeOps() - the operand branch is invalid." << endl; + + LEAVE( "QtPlus::sortAssociativeOps()" ); +} +*/ + + +QtOperation* +QtPlus::getUniqueOrder( const QtNode::QtNodeType ID ) +{ + RMDBCLASS( "QtPlus", "getUniqueOrder( const QtNode::QtNodeType )", "qlparser", __FILE__, __LINE__ ) + + QtOperation* returnValue = NULL; + + if( nodeType == ID ) + { + QtOperation* node = input1->getUniqueOrder( nodeType ); + + if( node ) + { + if( ( node->getSpelling().compare( input2->getSpelling() ) ) > 0 ) + returnValue = node; + else + returnValue = input2; + } + else + RMInit::logOut << "Error: QtMult::getUniqueOrder(): Query tree invalid" << endl; + } + else + returnValue = this; + + return returnValue; +} + + + +void +QtPlus::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtPlus Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + + +void +QtPlus::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " + "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtNode::QtNodeType QtMinus::nodeType = QT_MINUS; + +QtMinus::QtMinus( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_MINUS ) +{ +} + + + +bool +QtMinus::isCommutative() const +{ + return false; // NOT commutative +} + + + +void +QtMinus::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtMinus Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + + +void +QtMinus::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " - "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + + +const QtNode::QtNodeType QtMult::nodeType = QT_MULT; + +QtMult::QtMult( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_MULT ) +{ +} + + +/* +void +QtMult::rewriteOps() +{ + RMDBCLASS( "QtMult", "rewriteOps()", "qlparser", __FILE__, __LINE__ ) + + if( input1 && input2 ) + { + if( nodeType == input2->getNodeType() ) + { + RMInit::logOut << "> rule (left deep tree): A*(B*C) -> (B*C)*A" << endl; + + // more than one equal binary operator, make standard form of the tree + + QtBinaryOperation* nodeR = (QtBinaryOperation*) input2; + QtOperation* nodeRL = nodeR->getInput1(); + + getParent()->setInput( this, nodeR ); + nodeR->setInput1( this ); + this->setInput2( nodeRL ); + nodeR->rewriteOps(); + } + else + { + input1->rewriteOps(); + input2->rewriteOps(); + } + } + else + RMInit::logOut << "Error: QtMult::rewriteOps() - the operand branch is invalid." << endl; +} +*/ + +/* +void +QtMult::sortAssociativeOps() +{ + RMDBCLASS( "QtMult", "sortAssociativeOps()", "qlparser", __FILE__, __LINE__ ) + + if( input1 && input2 ) + { + if( nodeType == input1->getNodeType() ) + { + // associative law is applicable + + QtOperation* node = input1->getUniqueOrder( nodeType ); + + if( node && node->getSpelling().compare( input2->getSpelling() ) > 0 ) + { + node->getParent()->setInput( node, input2 ); + setInput2( node ); + }; + } + else + { + if( input1->getSpelling().compare( input2->getSpelling() ) > 0 ) + { + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtMult", "sortAssociativeOps: rule (associativity): A * B -> B * A" ); + + QtOperation* node = input1; + + setInput1( input2 ); + setInput2( node ); + }; + } + + input1->sortAssociativeOps(); + } + else + RMInit::logOut << "Error: QtMult::sortAssociativeOps() - the operand branch is invalid." << endl; +} +*/ + + +QtOperation* +QtMult::getUniqueOrder( const QtNode::QtNodeType ID ) +{ + RMDBCLASS( "QtMult", "getUniqueOrder( const string )", "qlparser", __FILE__, __LINE__ ) + + QtOperation* returnValue = NULL; + + if( nodeType == ID ) + { + QtOperation* node = input1->getUniqueOrder( nodeType ); + + if( node ) + { + if( node->getSpelling().compare( input2->getSpelling() ) > 0 ) + returnValue = node; + else + returnValue = input2; + } + else + RMInit::logOut << "Error: QtMult::getUniqueOrder(): Query tree invalid" << endl; + } + else + returnValue = this; + + return returnValue; +} + + + +void +QtMult::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtMult Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + + +void +QtMult::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " * "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtNode::QtNodeType QtDiv::nodeType = QT_DIV; + +QtDiv::QtDiv( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_DIV ) +{ +} + + + +bool +QtDiv::isCommutative() const +{ + return false; // NOT commutative +} + + + +void +QtDiv::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtDiv Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + + +void +QtDiv::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " / "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + diff --git a/qlparser/qtbinaryinduce.hh b/qlparser/qtbinaryinduce.hh new file mode 100644 index 0000000..de744e3 --- /dev/null +++ b/qlparser/qtbinaryinduce.hh @@ -0,0 +1,261 @@ +#ifndef _QTBINARYINDUCE_ +#define _QTBINARYINDUCE_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtbinaryoperation.hh" +#include "qlparser/qtdata.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtscalardata.hh" + +#include "catalogmgr/ops.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: +The class hierarchy guarantees no type safety. Type checking is done at +execution time. + +The operations greater and greater equal are mapped to QtLess and QtLessEqual. +*/ + +class QtBinaryInduce : public QtBinaryOperation +{ + public: + /// constructor getting the two operands + QtBinaryInduce( QtOperation* input1, QtOperation* input2, Ops::OpType initOpType ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + protected: + /// computes the binary operation + QtData* computeOp( QtData* operand1, QtData* operand2 ); + + /// computes an unary induce operation with one MDD object and a scalar value either being atomic or complex constant + QtData* computeUnaryMDDOp( QtMDD* operand1, QtScalarData* operand2, const BaseType* resultBaseType, int scalarPos=1 ); + /** + The method carries out the unary induce operation specified by {\tt operation} on the two operands. {\tt scalarPos } + determines if the scalar value is the first (=1, default) or the second (=2) operand in the operation. For + the result, a new transient MDD object is created and returned. In the end, the MDD object of the first operand + is freed. + */ + + /// computes a binary induce operation on two MDD objects + QtData* computeBinaryMDDOp( QtMDD* operand1, QtMDD* operand2, const BaseType* resultBaseType ); + /** + The method carries out the binary induce operation specified by {\tt operation} on the two operands. For + the result, a new transient MDD object is created and returned. In the end, the MDD objects of the operands + are freed. + */ + + /// computes a binary operation on two scalar objects + QtData* computeBinaryOp( QtScalarData* operand1, QtScalarData* operand2, const BaseType* resultBaseType ); + /** + The method carries out the binary operation specified by {\tt operation} on the two operands. + */ + +// private: + // type of operation + Ops::OpType opType; + + private: + /// atribute for identification of nodes + static const QtNodeType nodeType; + +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtPlus : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtPlus( QtOperation* input1, QtOperation* input2 ); + + /// optimizes the tree +// virtual void rewriteOps(); + + /// optimizes the tree +// virtual void sortAssociativeOps(); + + ///for associative law + virtual QtOperation* getUniqueOrder( const QtNode::QtNodeType ID ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtMinus : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtMinus( QtOperation* input1, QtOperation* input2 ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// returns FALSE saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtMult : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtMult( QtOperation* input1, QtOperation* input2 ); + + /// optimizes the tree +// virtual void rewriteOps(); + + /// optimizes the tree +// virtual void sortAssociativeOps(); + + /// optimizes the tree + virtual QtOperation* getUniqueOrder( const QtNode::QtNodeType ID ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtDiv : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtDiv( QtOperation* input1, QtOperation* input2 ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// returns FALSE saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +#include "qlparser/qtbinaryinduce.icc" + +#endif + + + + + + + + + + + + + + + + + + + + + + diff --git a/qlparser/qtbinaryinduce.icc b/qlparser/qtbinaryinduce.icc new file mode 100644 index 0000000..6a7caa9 --- /dev/null +++ b/qlparser/qtbinaryinduce.icc @@ -0,0 +1,56 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtPlus::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtMinus::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtMult::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtDiv::getNodeType() const +{ + return nodeType; +} + diff --git a/qlparser/qtbinaryinduce2.cc b/qlparser/qtbinaryinduce2.cc new file mode 100644 index 0000000..c12479c --- /dev/null +++ b/qlparser/qtbinaryinduce2.cc @@ -0,0 +1,919 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtBinaryInduce: $Id: qtbinaryinduce2.cc,v 1.25 2002/09/11 14:48:51 hoefner Exp $"; + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtbinaryinduce2.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtconst.hh" + +#include "mddmgr/mddobj.hh" + +#include "catalogmgr/typefactory.hh" + +#include <iostream> +#include <string> +#include <vector> +using namespace std; + +const QtNode::QtNodeType QtIs::nodeType = QT_IS; + +QtIs::QtIs( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_EQUAL ) +{ +} + +/* +void +QtIs::checkIdempotency() +{ + if( input1->getSpelling().compare( input2->getSpelling() ) == 0 ) + { + RMInit::logOut << "> rule (idempotency): A IS A -> TRUE" << endl; + + getParent()->setInput( this, new QtConst( new QtAtomicData( 1 ) ) ); + + // delete the node itself and its descendants + delete this; + }; +} +*/ + +void +QtIs::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtIs Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + +void +QtIs::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " is "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + +const QtNode::QtNodeType QtAnd::nodeType = QT_AND; + +QtAnd::QtAnd( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_AND ) +{ +} + +/* +void +QtAnd::checkIdempotency() +{ + if( input2->getNodeType() == QtNode::QT_CONST && + ((QtConst*)input2)->getDataObj()->getDataType() == QT_BOOL ) + { + QtAtomicData* boolData = (QtAtomicData*)((QtConst*)input2)->getDataObj(); + + if( boolData->getUnsignedValue() ) + { + RMInit::logOut << "> rule (idempotency): A AND TRUE -> A" << endl; + + getParent()->setInput( this, input1 ); + + // delete the node itself and its descendants but not input1 + setInput1(NULL); + delete this; + } + else + { + if( input1->getAreaType() == QtNode::QT_AREA_SCALAR ) + { + RMInit::logOut << "> rule (idempotency): A (scalar) AND FALSE -> FALSE" << endl; + + getParent()->setInput( this, input2 ); + + // delete the node itself and its descendants but not input2 + setInput2(NULL); + delete this; + }; + } + } + else + if( input1->getNodeType() == QtNode::QT_CONST && + ((QtConst*)input1)->getDataObj()->getDataType() == QT_BOOL ) + { + QtAtomicData* boolData = (QtAtomicData*)((QtConst*)input1)->getDataObj(); + + if( boolData->getUnsignedValue() ) + { + RMInit::logOut << "> rule (idempotency): TRUE AND A -> A" << endl; + + getParent()->setInput( this, input2 ); + + // delete the node itself and its descendants but not input2 + setInput2(NULL); + delete this; + } + else + { + if( input2->getAreaType() == QtNode::QT_AREA_SCALAR ) + { + RMInit::logOut << "> rule (idempotency): FALSE AND A (scalar) -> FALSE" << endl; + + getParent()->setInput( this, input1 ); + + // delete the node itself and its descendants but not input1 + setInput1(NULL); + delete this; + }; + }; + } + else + if( input1->getSpelling().compare( input2->getSpelling() ) == 0 ) + { + RMInit::logOut << "> rule (idempotency): A AND A -> A" << endl; + + getParent()->setInput( this, input1 ); + + // delete the node itself and its descendants but not input1 + setInput1(NULL); + delete this; + } +} +*/ + + + +/* +void +QtAnd::rewriteOps() +{ + if( input1 && input2 ) + { + if( input1->getNodeType() == QtNode::QT_SOME && + input2->getNodeType() == QtNode::QT_ALL ) + { + RMInit::logOut << "> rule (condenser order): SOME_CELLS AND ALL_CELLS -> ALL_CELLS AND SOME_CELLS" << endl; + + // order condenser expressions + + QtOperation* node1 = getInput1(); + QtOperation* node2 = getInput2(); + + setInput1( node2 ); + setInput2( node1 ); + }; + } + else + RMInit::logOut << "Error: QtAnd::rewriteOps() - the operand branch is invalid." << endl; +} +*/ + + +QtData* +QtAnd::evaluate( QtDataList* inputList ) +{ + /* + // RUNTIME OPTIMIZATION: FALSE AND A -> MDD(FALSE) + // A AND FALSE -> MDD(FALSE) + // TRUE AND A -> A + // A AND TRUE -> A + */ + + QtData* returnValue = NULL; + + if( input1->getDataStreamType().getDataType() == QT_BOOL && + input2->getDataStreamType().getDataType() == QT_BOOL ) + { + // RUNTIME OPTIMIZATION: FALSE AND A -> FALSE + // TRUE AND A -> A + + QtData* operand1=NULL; + + if( getOperand( inputList, operand1, 1 ) ) + { + bool op1 = ((QtAtomicData*)operand1)->getUnsignedValue(); + + if( op1 ) + { + // first operand is obsolete + if( operand1 ) operand1->deleteRef(); + + QtData* operand2=NULL; + + if( getOperand( inputList, operand2, 2 ) ) + { + returnValue = operand2; + } + } + else + { + returnValue = operand1; + RMDBGONCE(1, RMDebug::module_qlparser, "QtAnd", " -> FALSE AND A evaluates FALSE") + } + } + } + else + returnValue = QtBinaryInduce::evaluate( inputList ); + + return returnValue; +} + + +void +QtAnd::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtAnd Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + +void +QtAnd::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " and "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtNode::QtNodeType QtOr::nodeType = QT_OR; + +QtOr::QtOr( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_OR ) +{ +} + +/* +void +QtOr::checkIdempotency() +{ + if( input2->getNodeType() == QtNode::QT_CONST && + ((QtConst*)input2)->getDataObj()->getDataType() == QT_BOOL ) + { + QtAtomicData* boolData = (QtAtomicData*)((QtConst*)input2)->getDataObj(); + + if( boolData->getUnsignedValue() ) + { + if( input1->getAreaType() == QtNode::QT_AREA_SCALAR ) + { + RMInit::logOut << "> rule (idempotency): A (scalar) OR TRUE -> TRUE" << endl; + + getParent()->setInput( this, input2 ); + + // delete the node itself and its descendants but not input2 + setInput2(NULL); + delete this; + }; + } + else + { + RMInit::logOut << "> rule (idempotency): A OR FALSE -> A" << endl; + + getParent()->setInput( this, input1 ); + + // delete the node itself and its descendants but not input1 + setInput1(NULL); + delete this; + } + } + else + if( input1->getNodeType() == QtNode::QT_CONST && + ((QtConst*)input1)->getDataObj()->getDataType() == QT_BOOL ) + { + QtAtomicData* boolData = (QtAtomicData*)((QtConst*)input1)->getDataObj(); + + if( boolData->getUnsignedValue() ) + { + if( input2->getAreaType() == QtNode::QT_AREA_SCALAR ) + { + RMInit::logOut << "> rule (idempotency): TRUE OR A (scalar) -> TRUE" << endl; + + getParent()->setInput( this, input1 ); + + // delete the node itself and its descendants but not input1 + setInput1(NULL); + delete this; + }; + } + else + { + RMInit::logOut << "> rule (idempotency): FALSE OR A -> A" << endl; + + getParent()->setInput( this, input2 ); + + // delete the node itself and its descendants but not input2 + setInput2(NULL); + delete this; + }; + } + else + if( input1->getSpelling().compare( input2->getSpelling() ) == 0 ) + { + RMInit::logOut << "> rule (idempotency): A OR A -> A" << endl; + + getParent()->setInput( this, input1 ); + + // delete the node itself and its descendants but not input1 + setInput1(NULL); + delete this; + }; +} +*/ + + +/* +void +QtOr::rewriteOps() +{ + if( input1 && input2 ) + { + if( input1->getNodeType() == QtNode::QT_ALL && + input2->getNodeType() == QtNode::QT_SOME ) + { + RMInit::logOut << "> rule (condenser order): ALL_CELLS OR SOME_CELLS -> SOME_CELLS OR ALL_CELLS" << endl; + + // order condenser expressions + + QtOperation* node1 = getInput1(); + QtOperation* node2 = getInput2(); + + setInput1( node2 ); + setInput2( node1 ); + }; + } + else + RMInit::logOut << "Error: QtOr::rewriteOps() - the operand branch is invalid." << endl; +} +*/ + +QtData* +QtOr::evaluate( QtDataList* inputList ) +{ + /* + // RUNTIME OPTIMIZATION: TRUE OR A -> MDD(TRUE) + // A OR TRUE -> MDD(TRUE) + // FALSE OR A -> A + // A OR FALSE -> A + */ + + QtData* returnValue = NULL; + + if( input1->getDataStreamType().getDataType() == QT_BOOL && + input2->getDataStreamType().getDataType() == QT_BOOL ) + { + // RUNTIME OPTIMIZATION: FALSE OR A -> A + // TRUE OR A -> TRUE + + QtData* operand1=NULL; + + if( getOperand( inputList, operand1, 1 ) ) + { + bool op1 = ((QtAtomicData*)operand1)->getUnsignedValue(); + + if( !op1 ) + { + // first operand is obsolete + if( operand1 ) operand1->deleteRef(); + + QtData* operand2=NULL; + + if( getOperand( inputList, operand2, 2 ) ) + { + returnValue = operand2; + } + } + else + { + returnValue = operand1; + RMDBGONCE(1, RMDebug::module_qlparser, "QtOr", " -> TRUE OR A evaluates TRUE") + } + } + } + else + returnValue = QtBinaryInduce::evaluate( inputList ); + + return returnValue; +} + + +void +QtOr::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtOr Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + +void +QtOr::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " or "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtNode::QtNodeType QtXor::nodeType = QT_XOR; + + +QtXor::QtXor( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_XOR ) +{ +} + +/* +void +QtXor::checkIdempotency() +{ + RMDBGENTER(1, RMDebug::module_qlparser, "QtXor", "enter Xor::checkIdempotency()" ) + + if( input1->getSpelling().compare( input2->getSpelling() ) == 0 ) + { + RMInit::logOut << "> rule (idempotency): A XOR A -> FALSE" << endl; + + getParent()->setInput( this, new QtConst( new QtAtomicData( 0 ) ) ); + + // delete the node itself and its descendants + delete this; + }; + + RMDBGEXIT(1, RMDebug::module_qlparser, "QtXor", "exit Xor::checkIdempotency()" ) +} +*/ + +void +QtXor::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtXor Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + +void +QtXor::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " xor "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtNode::QtNodeType QtEqual::nodeType = QT_EQUAL; + +QtEqual::QtEqual( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_EQUAL ) +{ +} + +/* +void +QtEqual::checkIdempotency() +{ + if( input1->getSpelling().compare( input2->getSpelling() ) == 0 ) + { + RMInit::logOut << "> rule (idempotency): A == A -> TRUE" << endl; + + getParent()->setInput( this, new QtConst( new QtAtomicData( 1 ) ) ); + + // delete the node itself and its descendants + delete this; + }; +} +*/ + + +void +QtEqual::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtEqual Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + + +void +QtEqual::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " = "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtNode::QtNodeType QtLess::nodeType = QT_LESS; + + +QtLess::QtLess( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_LESS ) +{ +} + + +bool +QtLess::isCommutative() const +{ + return false; // NOT commutative +} + + + +void +QtLess::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtLess Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + + +void +QtLess::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " < "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtNode::QtNodeType QtLessEqual::nodeType = QT_LESS_EQUAL; + + +QtLessEqual::QtLessEqual( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_LESSEQUAL ) +{ +} + + +bool +QtLessEqual::isCommutative() const +{ + return false; // NOT commutative +} + + + +void +QtLessEqual::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtLessEqual Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + +void +QtLessEqual::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " <= "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtNode::QtNodeType QtNotEqual::nodeType = QT_NOT_EQUAL; + +QtNotEqual::QtNotEqual( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_NOTEQUAL ) +{ +} + +/* +void +QtNotEqual::checkIdempotency() +{ + if( input1->getSpelling().compare( input2->getSpelling() ) == 0 ) + { + RMInit::logOut << "> rule (idempotency): A != A -> FALSE" << endl; + + getParent()->setInput( this, new QtConst( new QtAtomicData( 0 ) ) ); + + // delete the node itself and its descendants + delete this; + }; +} +*/ + +void +QtNotEqual::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtNotEqual Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + + +void +QtNotEqual::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " != "; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + + + +const QtNode::QtNodeType QtOverlay::nodeType = QT_OVERLAY; + +QtOverlay::QtOverlay( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryInduce( initInput1, initInput2, Ops::OP_OVERLAY ) +{ +} + +/* +void QtOverlay::checkIdempotency() +{ +} +*/ + + +bool QtOverlay::isCommutative() const +{ + return false; // NOT commutative +} + + + +void +QtOverlay::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtOverlay Object " << getNodeType() << endl; + + QtBinaryInduce::printTree( tab, s, mode ); +} + + + +void +QtOverlay::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << " overlay "; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + +/******************************************************** + * QtBit + ******************************************************** + */ + + +const QtNode::QtNodeType QtBit::nodeType = QT_BIT; + +QtBit::QtBit(QtOperation* initInput1, QtOperation* initInput2) + : QtBinaryInduce(initInput1, initInput2, Ops::OP_BIT) {} + + +bool QtBit::isCommutative() const { + return false; +} + +void QtBit::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtBit Object " << getNodeType() << endl; + QtBinaryInduce::printTree(tab, s, mode); +} + +void QtBit::printAlgebraicExpression(ostream& s) { + s << "("; + + if( input2 ) + input2->printAlgebraicExpression(s); + else + s << "<nn>"; + + s << " bit "; + + if( input1 ) + input1->printAlgebraicExpression(s); + else + s << "<nn>"; + + s << ")"; +} + +const QtTypeElement& QtBit::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtBit", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType(QT_TYPE_UNKNOWN); + + // check operand branches + if(input1 && input2) + { + + // get input types + const QtTypeElement& inputType1 = input1->checkType(typeTuple); + const QtTypeElement& inputType2 = input2->checkType(typeTuple); + + if(RManDebug >= 4) { + RMInit::dbgOut << "Operand 1: " << flush; + inputType1.printStatus( RMInit::dbgOut ); + RMInit::dbgOut << endl; + + RMInit::dbgOut << "Operand 2: " << flush; + inputType2.printStatus( RMInit::dbgOut ); + RMInit::dbgOut << endl; + + RMDBGONCE( 4, RMDebug::module_qlparser, "QtBit", "Operation " << opType ) + } + + if(inputType2.getDataType() < QT_BOOL || inputType2.getDataType() > QT_LONG) { + RMInit::logOut << "Error: QtBit::checkType() - second operand must be of integral type." << endl; + parseInfo.setErrorNo(418); + throw parseInfo; + } + + if(inputType1.getDataType() == QT_MDD) { + const BaseType* baseType1 = ((MDDBaseType*)(inputType1.getType()))->getBaseType(); + BaseType* baseType2 = (BaseType*)(inputType2.getType()); + + const BaseType* resultBaseType = Ops::getResultType(opType, baseType1, baseType2); + + if(!resultBaseType) { + RMInit::logOut << "Error: QtBit::checkType() - unary induce: operand types are incompatible." << endl; + parseInfo.setErrorNo(364); + throw parseInfo; + } + + MDDBaseType* resultMDDType = new MDDBaseType("tmp", resultBaseType); + TypeFactory::addTempType(resultMDDType); + + dataStreamType.setType(resultMDDType); + } + + else if(inputType1.isBaseType()) { + BaseType* baseType1 = (BaseType*)(inputType1.getType()); + BaseType* baseType2 = (BaseType*)(inputType2.getType()); + + const BaseType* resultBaseType = Ops::getResultType(opType, baseType1, baseType2); + + if(!resultBaseType) { + RMInit::logOut << "Error: QtBit::computeOp() - operand types are incompatible." << endl; + parseInfo.setErrorNo(365); + throw parseInfo; + } + + dataStreamType.setType(resultBaseType); + } + else { + RMInit::logOut << "Error: QtBit::checkType() - operation is not supported on these data types." << endl; + parseInfo.setErrorNo(403); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtBit::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} diff --git a/qlparser/qtbinaryinduce2.hh b/qlparser/qtbinaryinduce2.hh new file mode 100644 index 0000000..96928fb --- /dev/null +++ b/qlparser/qtbinaryinduce2.hh @@ -0,0 +1,358 @@ +#ifndef _QTBINARY2INDUCE_ +#define _QTBINARY2INDUCE_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtbinaryinduce.hh" + +#include "catalogmgr/ops.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtIs : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtIs( QtOperation* input1, QtOperation* input2 ); + + /// check idempetency rules +// virtual void checkIdempotency(); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtAnd : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtAnd( QtOperation* input1, QtOperation* input2 ); + + /// heuristic ordering of operands +// virtual void rewriteOps(); + + /// check idempetency rules +// virtual void checkIdempotency(); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtOr : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtOr( QtOperation* input1, QtOperation* input2 ); + + /// heuristic ordering of operands +// virtual void rewriteOps(); + + /// check idempetency rules + // virtual void checkIdempotency(); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtXor : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtXor( QtOperation* input1, QtOperation* input2 ); + + /// check idempetency rules +// virtual void checkIdempotency(); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtEqual : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtEqual( QtOperation* input1, QtOperation* input2 ); + + /// check idempetency rules +// virtual void checkIdempotency(); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtLess : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtLess( QtOperation* input1, QtOperation* input2 ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// returns false saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtLessEqual : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtLessEqual( QtOperation* input1, QtOperation* input2 ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// returns false saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtNotEqual : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtNotEqual( QtOperation* input1, QtOperation* input2 ); + + /// check idempetency rules +// virtual void checkIdempotency(); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtOverlay : public QtBinaryInduce +{ + public: + /// constructor getting the two operands + QtOverlay( QtOperation* input1, QtOperation* input2 ); + + /// check idempetency rules +// virtual void checkIdempotency(); + + /// check commutativity + bool isCommutative() const; + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +class QtBit : public QtBinaryInduce { +public: + /// constructor getting the two operands + QtBit( QtOperation* input1, QtOperation* input2 ); + + /// check commutativity + bool isCommutative() const; + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// checkType + const QtTypeElement& checkType( QtTypeTuple* typeTuple ); + +private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +#include "qlparser/qtbinaryinduce2.icc" + +#endif + diff --git a/qlparser/qtbinaryinduce2.icc b/qlparser/qtbinaryinduce2.icc new file mode 100644 index 0000000..134b2ea --- /dev/null +++ b/qlparser/qtbinaryinduce2.icc @@ -0,0 +1,95 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtIs::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtAnd::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtOr::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtXor::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtEqual::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtLess::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtLessEqual::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtNotEqual::getNodeType() const +{ + return nodeType; +} + +inline const QtNode::QtNodeType +QtOverlay::getNodeType() const +{ + return nodeType; +} + +inline const QtNode::QtNodeType +QtBit::getNodeType() const +{ + return nodeType; +} diff --git a/qlparser/qtbinaryoperation.cc b/qlparser/qtbinaryoperation.cc new file mode 100644 index 0000000..ed05b79 --- /dev/null +++ b/qlparser/qtbinaryoperation.cc @@ -0,0 +1,432 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtBinaryOperation: $Id: qtbinaryoperation.cc,v 1.25 2002/04/12 09:51:53 coman Exp $"; + +#include "qlparser/qtbinaryoperation.hh" +#include "qlparser/qtconst.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +// constructors + +QtBinaryOperation::QtBinaryOperation() : + QtOperation(), + input1(NULL), + input2(NULL) +{ +} + + +QtBinaryOperation::QtBinaryOperation( QtNode* node ) : + QtOperation( node ), + input1(NULL), + input2(NULL) +{ +} + + +QtBinaryOperation::QtBinaryOperation( QtOperation* initInput1, QtOperation* initInput2 ) : + QtOperation(), + input1( initInput1 ), + input2( initInput2 ) +{ + if ( input1 ) + input1->setParent( this ); + + if ( input2 ) + input2->setParent( this ); +} + +// destructor + +QtBinaryOperation::~QtBinaryOperation() +{ + if ( input1 ) + { + delete input1; + input1=NULL; + } + if ( input2 ) + { + delete input2; + input2=NULL; + } +} + + +// pre-evaluate the operation if the nodes contain constant data + +void +QtBinaryOperation::simplify() +{ + RMDBCLASS( "QtBinaryOperation", "simplify()", "qlparser", __FILE__, __LINE__ ) + + // In order to work bottom up, first inspect the descendants + QtNode::simplify(); + + // Test, if both operands are available. + if( input1 && input2 ) + { + // Test, if both operands are of const type. + if( input1->getNodeType() == QT_CONST && input2->getNodeType() == QT_CONST ) + { + // evaluate the self node with no input list + QtData* newConst = this->evaluate( NULL ); + + if( newConst ) + { + // create a new constant node and fill it with newConst + QtConst* newNode = new QtConst( newConst ); + + // set its data stream type + newNode->checkType( NULL ); + + // link it to the parent + getParent()->setInput( this, newNode ); + + // delete the self node and its descendants + delete this; + } + } + } + +} + + +// compare this to another node + +bool +QtBinaryOperation::equalMeaning( QtNode* node ) +{ + RMDBCLASS( "QtBinaryOperation", "equalMeaning( QtNode* )", "qlparser", __FILE__, __LINE__ ) + + bool result = false; + + // are the nodes of the same type? + if ( getNodeType() == node->getNodeType() ) + { + QtBinaryOperation* binNode = (QtBinaryOperation *) node; // by force + + if ( input1 && input2 ) { + if ( isCommutative() ) + // operation is commutative + result = ( input1->equalMeaning( binNode->getInput1() ) && + input2->equalMeaning( binNode->getInput2() ) ) || + ( input1->equalMeaning( binNode->getInput2() ) && + input2->equalMeaning( binNode->getInput1() ) ); + else + // not commutative + result = input1->equalMeaning( binNode->getInput1() ) && + input2->equalMeaning( binNode->getInput2() ); + }; + }; + + return result; +} + + +// get childs + +QtNode::QtNodeList* +QtBinaryOperation::getChilds( QtChildType flag ) +{ + RMDBCLASS( "QtBinaryOperation", "getChilds( QtChildType )", "qlparser", __FILE__, __LINE__ ) + + QtNodeList* resultList = new QtNodeList(); + + if ( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) { + QtNodeList* subList=NULL; + + if ( input1 ) { + subList = input1->getChilds( flag ); + resultList->splice(resultList->begin(), *subList); + delete subList; + subList=NULL; + }; + + if ( input2 ) { + subList = input2->getChilds( flag ); + resultList->splice(resultList->begin(), *subList); + delete subList; + subList=NULL; + }; + }; + + if ( flag == QT_DIRECT_CHILDS || flag == QT_ALL_NODES ) { + if ( input1 ) + resultList->push_back( input1 ); + if ( input2 ) + resultList->push_back( input2 ); + }; + + return resultList; +} + + +// get the two operands + +bool +QtBinaryOperation::getOperands( QtDataList* inputList, QtData* &operand1, QtData* &operand2 ) +{ + RMDBCLASS( "QtBinaryOperation", "getOperands( QtDataList*, QtData*, QtData* )", "qlparser", __FILE__, __LINE__ ) + + bool success = false; + + // get the operands + try { + if ( input1 ) operand1 = input1->evaluate( inputList ); + if ( input2 ) operand2 = input2->evaluate( inputList ); + } + catch(...) + { + //clean up code + if( operand1 ) { + operand1->deleteRef(); + operand1 = NULL; + } + + if( operand2 ){ + operand2->deleteRef(); + operand2 = NULL; + } + + throw; + } + + // test if the operands are valid + success = operand1 && operand2; + + if( !success ) + { + + if( operand1 ) + { + operand1->deleteRef(); + operand1 = NULL; + } + + if( operand2 ) + { + operand2->deleteRef(); + operand2 = NULL; + } + + RMDBGONCE( 1, RMDebug::module_qlparser, "QtBinaryOperation", "Error: QtBinaryOperation::getOperands() - at least one operand is not provided." ) + + } + + return success; +} + + +// get the first or the second operand + +bool +QtBinaryOperation::getOperand( QtDataList* inputList, QtData* &operand, int number ) +{ + RMDBCLASS( "QtBinaryOperation", "getOperand( QtDataList*, QtData*, int )", "qlparser", __FILE__, __LINE__ ) + + bool success = false; + + // get the operand + if ( number == 1 ) { + if ( input1 ) { + operand = input1->evaluate( inputList ); + } else { + if ( input2 ) + operand = input2->evaluate( inputList ); + } + } else { + if ( input2 ) + operand = input2->evaluate( inputList ); + } + + // test if the operands are valid + if ( operand ) + success = true; + else { + RMDBGONCE( 1, RMDebug::module_qlparser, "QtBinaryOperation", "Error: QtBinaryOperation::getOperand() - operand is not provided." ) + } + + return success; +} + + +// get spelling + +string +QtBinaryOperation::getSpelling() +{ + char tempStr[20]; + sprintf(tempStr, "%ud", (unsigned long)getNodeType()); + string result = string(tempStr); + result.append( "(" ); + + if ( input1 && input2 ) { + string result1 = input1->getSpelling(); + string result2 = input2->getSpelling(); + + if( result1.compare( result2 ) < 0 || !isCommutative() ) + { + result.append( result1 ); + result.append( "," ); + result.append( result2 ); + } + else + { + result.append( result2 ); + result.append( "," ); + result.append( result1 ); + }; + }; + + result.append( ")" ); + RMDBGONCE(2, RMDebug::module_qlparser, "QtBinaryOperation", "Result:" << result.c_str()) + return result; +} + + +// get area type + +QtNode::QtAreaType +QtBinaryOperation::getAreaType() +{ + QtNode::QtAreaType result = QT_AREA_MDD; + + if ( input1 && input2 ) + if ( input1->getAreaType() == QtNode::QT_AREA_SCALAR && + input2->getAreaType() == QtNode::QT_AREA_SCALAR ) + result = QT_AREA_SCALAR; + + return result; +} + + +// idempotent + +/* +void +QtBinaryOperation::checkIdempotency() +{ +} +*/ + +// optimize load + +void +QtBinaryOperation::optimizeLoad( QtTrimList* trimList ) +{ + RMDBCLASS( "QtBinaryOperation", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) + + QtNode::QtTrimList *list1=NULL; + QtNode::QtTrimList *list2=NULL; + + if( input1 && input2 ) + { + list1 = trimList; + + // for list2 make a copy of list1 + list2 = new QtNode::QtTrimList(); + + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + QtTrimElement* elem = new QtTrimElement; + *elem = **iter; + list2->push_back( elem ); + } + + if ( input1 ) + input1->optimizeLoad( list1 ); + + if ( input2 ) + input2->optimizeLoad( list2 ); + + } + else + { + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + } +} + + +void +QtBinaryOperation::printTree( int tab, ostream& s, QtChildType mode ) +{ + if( mode != QT_DIRECT_CHILDS ) + { + if( input1 ) + { + s << SPACE_STR(tab).c_str() << "input1: " << endl; + input1->printTree( tab+2, s, mode ); + } + else + s << SPACE_STR(tab).c_str() << "no input1" << endl; + + if( input2 ) + { + s << SPACE_STR(tab).c_str() << "input2: " << endl; + input2->printTree( tab+2, s, mode ); + } + else + s << SPACE_STR(tab).c_str() << "no input2" << endl; + } +} + + + +bool +QtBinaryOperation::isCommutative() const +{ + return true; // by default, a binary operation is commutative +} + + + + + + + + diff --git a/qlparser/qtbinaryoperation.hh b/qlparser/qtbinaryoperation.hh new file mode 100644 index 0000000..cf15666 --- /dev/null +++ b/qlparser/qtbinaryoperation.hh @@ -0,0 +1,150 @@ +#ifndef _QTBINARYOPERATION_ +#define _QTBINARYOPERATION_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include <stdio.h> + +#include "qlparser/qtoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************** + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +The class serves as superclass for all operation classes taking two +arguments. + +*/ + +class QtBinaryOperation : public QtOperation +{ + public: + /// default constructor + QtBinaryOperation(); + + /// constructor getting the node to the parent + QtBinaryOperation( QtNode* node ); + + /// constructor getting pointers to its operands + QtBinaryOperation( QtOperation* input1, QtOperation* input2 ); + + /// virtual destructor + virtual ~QtBinaryOperation(); + + /// simplifies the tree + virtual void simplify(); + + /// test if the two nodes have an equal meaning in the query tree + virtual bool equalMeaning( QtNode* node ); + /** + The meaning of a binary operation is equal, iff both operands have + the same meaning. In case of a commutative operation, the operands + can be switched. + */ + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// creates a unique name for a subexpression + virtual std::string getSpelling(); + + /// test if the edge to the parent node is of type mdd or atomic + virtual QtAreaType getAreaType(); + + /// method for query rewrite + inline virtual void setInput( QtOperation* inputOld, QtOperation* inputNew ); + + /// method for checking idempotency rules +// virtual void checkIdempotency(); + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + /** + The method deletes the given {\tt trimList} and passes the {\tt optimizeLoad} + message with empty triming lists to its input trees. The method is rewritten + by some subclasses. + */ + + /// debugging method + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + //@Man: read/write methods for the operands + //@{ + /// + /// + inline void setInput1( QtOperation* input ); + /// + inline void setInput2( QtOperation* input ); + /// + inline QtOperation* getInput1(); + /// + inline QtOperation* getInput2(); + /// + //@} + + /// returns commutativity information (by default, an operation IS commutative) + virtual bool isCommutative() const; + + protected: + /// method for testing and evaluating the input branches + bool getOperands( QtDataList* inputList, QtData* &operand1, QtData* &operand2 ); + /** + The method checks if the input branches are valid. Then it passes the evaluate message to its two + operands with the {\tt inputList} as argument. The returned results are provided through the arguments + {\tt operand1} and {\tt operand2} called by reference. The method returns {\tt true} it the operands are + valid, otherwise {\tt false}. + */ + + /// method for testing and evaluating the input branches + bool getOperand( QtDataList* inputList, QtData* &operand1, int number); + /** + The method checks if the by number specified input branch si valid. Then it passes the evaluate message to the + operand with the {\tt inputList} as argument. The returned result are provided through the argument + {\tt operand} called by reference. The method returns {\tt true} it the operand is + valid, otherwise {\tt false}. + */ + + /// first operation operand + QtOperation* input1; + /// second operation operand + QtOperation* input2; +}; + +#include "qlparser/qtbinaryoperation.icc" + +#endif + + diff --git a/qlparser/qtbinaryoperation.icc b/qlparser/qtbinaryoperation.icc new file mode 100644 index 0000000..7cb55cb --- /dev/null +++ b/qlparser/qtbinaryoperation.icc @@ -0,0 +1,89 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline void +QtBinaryOperation::setInput1( QtOperation* input ) +{ + input1 = input; + + if( input ) + input->setParent( this ); +}; + + + +inline void +QtBinaryOperation::setInput2( QtOperation* input ) +{ + input2 = input; + + if( input ) + input->setParent( this ); +}; + + + +inline QtOperation* +QtBinaryOperation::getInput1() +{ + return input1; +}; + + + +inline QtOperation* +QtBinaryOperation::getInput2() +{ + return input2; +}; + + + +inline void +QtBinaryOperation::setInput( QtOperation* inputOld, QtOperation* inputNew ) +{ + if( inputOld == input1 ) + { + setInput1( inputNew ); + + if( inputNew ) + inputNew->setParent( this ); + } + + if( inputOld == input2 ) + { + setInput2( inputNew ); + + if( inputNew ) + inputNew->setParent( this ); + } +}; + + + diff --git a/qlparser/qtcommand.cc b/qlparser/qtcommand.cc new file mode 100644 index 0000000..3574519 --- /dev/null +++ b/qlparser/qtcommand.cc @@ -0,0 +1,182 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtCommand: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtcommand.cc,v 1.21 2005/09/03 20:17:55 rasdev Exp $"; + +#include "qlparser/qtcommand.hh" +#include "mddmgr/mddcoll.hh" +#include "catalogmgr/typefactory.hh" +#include "reladminif/databaseif.hh" +#include "relcatalogif/settype.hh" +#include "servercomm/servercomm.hh" + +#include <iostream> + + +extern ServerComm::ClientTblElt* currentClientTblElt; + +const QtNode::QtNodeType QtCommand::nodeType = QtNode::QT_COMMAND; + + + +QtCommand::QtCommand( QtCommandType initCommand, const std::string& initCollection, const std::string& initType ) + : QtExecute(), + command( initCommand ), + collectionName( initCollection ), + typeName( initType ) +{ +} + + + +QtCommand::QtCommand( QtCommandType initCommand, const std::string& initCollection ) + : QtExecute(), + command( initCommand ), + collectionName( initCollection ) +{ +} + + + +int +QtCommand::evaluate() +{ + RMDBGENTER(2, RMDebug::module_qlparser, "QtCommand", "evaluate()") + + switch( command ) + { + case QT_DROP_COLLECTION: + if( currentClientTblElt ) + if (!MDDColl::dropMDDCollection(collectionName.c_str())) + { + RMInit::logOut << "Error during query evaluation: collection name not found: " << collectionName.c_str() << std::endl; + parseInfo.setErrorNo(957); + throw parseInfo; + } + break; + case QT_CREATE_COLLECTION: + if( currentClientTblElt ) + { + // get collection type + CollectionType* collType = (CollectionType*)TypeFactory::mapSetType( (char*)typeName.c_str() ); + + if( collType ) + { + // allocate a new oid within the current db + OId oid; +#ifdef BASEDB_O2 + if( !OId::allocateMDDCollOId( &oid ) ) + { +#else + OId::allocateOId(oid, OId::MDDCOLLOID); +#endif + try + { + MDDColl* coll = MDDColl::createMDDCollection(collectionName.c_str(), oid, collType); + delete coll; + coll=NULL; + } + catch( r_Error& obj ) + { + RMInit::logOut << "Error during query evaluation: collection name exists already: " << collectionName.c_str() << std::endl; + if (obj.get_kind() != r_Error::r_Error_NameNotUnique) + RMInit::logOut << "Exception: " << obj.what() << std::endl;; + parseInfo.setErrorNo(955); + throw parseInfo; + } +#ifdef BASEDB_O2 + } + else + { + RMInit::logOut << "Error: QtCommand::evaluate() - oid allocation failed" << std::endl; + parseInfo.setErrorNo(958); + throw parseInfo; + } +#endif + } + else + { + RMInit::logOut << "Error during query evaluation: collection type not found: " << (char*)typeName.c_str() << std::endl; + parseInfo.setErrorNo(956); + throw parseInfo; + } + break; + } + } + + RMDBGEXIT(2, RMDebug::module_qlparser, "QtCommand", "evaluate()") + + return 0; +} + + + +void +QtCommand::printTree( int tab, std::ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtCommand Object" << std::endl; + + switch( command ) + { + case QT_DROP_COLLECTION: s << SPACE_STR(tab).c_str() << " drop collection(" << collectionName.c_str() << ")"; break; + case QT_CREATE_COLLECTION: s << SPACE_STR(tab).c_str() << " create collection(" << collectionName.c_str() << ", " << typeName.c_str() <<")"; break; + default: s << "<command unknown>"; + } + + s << std::endl; +} + + + +void +QtCommand::printAlgebraicExpression( std::ostream& s ) +{ + s << "command<"; + + switch( command ) + { + case QT_DROP_COLLECTION: s << "drop collection(" << collectionName.c_str() << ")"; break; + case QT_CREATE_COLLECTION: s << "create collection(" << collectionName.c_str() << ", " << typeName.c_str() <<")"; break; + default: s << "unknown"; + } + + s << ">"; +} + + + +void +QtCommand::checkType() +{ + // nothing to do here +} + diff --git a/qlparser/qtcommand.hh b/qlparser/qtcommand.hh new file mode 100644 index 0000000..76c4375 --- /dev/null +++ b/qlparser/qtcommand.hh @@ -0,0 +1,97 @@ +#ifndef __QTCOMMAND_HH__ +#define __QTCOMMAND_HH___ + +#include "qlparser/qtexecute.hh" + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif +#include <iostream> + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/** + +*/ + +class QtCommand : public QtExecute +{ + public: + enum QtCommandType + { + QT_DROP_COLLECTION, + QT_CREATE_COLLECTION + }; + + /// constructor getting command, collection and type name (create collection) + QtCommand( QtCommandType initCommand, const std::string& initCollection, const std::string& initType ); + + /// constructor getting command and collection name (drop collection) + QtCommand( QtCommandType initCommand, const std::string& initCollection ); + + /// method for evaluating the node + virtual int evaluate(); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking + virtual void checkType(); + + private: + /// command type + QtCommandType command; + + /// attribute for identification of nodes + static const QtNodeType nodeType; + + /// collection name for drop/create collection + std::string collectionName; + + /// type name for create collection + std::string typeName; +}; + +#include "qlparser/qtcommand.icc" + +#endif + + + diff --git a/qlparser/qtcommand.icc b/qlparser/qtcommand.icc new file mode 100644 index 0000000..cb8353b --- /dev/null +++ b/qlparser/qtcommand.icc @@ -0,0 +1,35 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtCommand::getNodeType() const +{ + return nodeType; +} + diff --git a/qlparser/qtcomplexdata.cc b/qlparser/qtcomplexdata.cc new file mode 100644 index 0000000..36a822d --- /dev/null +++ b/qlparser/qtcomplexdata.cc @@ -0,0 +1,109 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtComplexData: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtcomplexdata.cc,v 1.12 2003/12/27 20:51:28 rasdev Exp $"; + +#include "qlparser/qtcomplexdata.hh" +#include "relcatalogif/structtype.hh" +#include <stdio.h> +#include <cstring> + +QtComplexData::QtComplexData() + : QtScalarData() +{ +} + + + +QtComplexData::QtComplexData( QtComplexData::QtScalarDataList* &scalarDataList ) + : QtScalarData() +{ + char elementName[256]; + unsigned int i=0; + std::list<QtScalarData*>::iterator iter; + + // Take care of dynamic memory management: + // + // Types, which are not in the typeFactory, have to be deleted. This means that, in general, + // all complex types have to be deleted because they are constructed temporarily. + + // create a new struct type + StructType* structType = new StructType( "", scalarDataList->size() ); + + // add type elements, the first element inserted has no 0, the second no 1, and so on + for( iter=scalarDataList->begin(), i=0; iter!=scalarDataList->end(); iter++, i++ ) + { + sprintf( elementName, "%d", i ); + structType->addElement( elementName, (*iter)->getValueType() ); + } + + // add type to typeFactory + TypeFactory::addTempType( structType ); + + valueBuffer = new char[ structType->getSize() ]; + valueType = structType; + + // copy data + for( iter=scalarDataList->begin(), i=0; iter!=scalarDataList->end(); iter++, i++ ) + { + char* destination = ((char*)valueBuffer) + structType->getOffset( i ); + + memcpy( (void*)destination, (void*)((*iter)->getValueBuffer()), (*iter)->getValueType()->getSize() ); + } + + // delete the list of type elements + // release( scalarDataList->begin(), scalarDataList->end() ); + for( iter=scalarDataList->begin(); iter!=scalarDataList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete scalarDataList; + scalarDataList = NULL; +} + + + +QtComplexData::QtComplexData( const QtComplexData& obj ) + : QtScalarData( obj ) +{ +} + + + +void +QtComplexData::printStatus( ostream& stream ) const +{ + stream << "complex, " << std::flush; + QtScalarData::printStatus( stream ); + stream << std::endl; +} diff --git a/qlparser/qtcomplexdata.hh b/qlparser/qtcomplexdata.hh new file mode 100644 index 0000000..51178b8 --- /dev/null +++ b/qlparser/qtcomplexdata.hh @@ -0,0 +1,92 @@ +#ifndef _QTCOMPLEXDATA_HH +#define _QTCOMPLEXDATA_HH + +#include "qlparser/qtscalardata.hh" + +#include <list> + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/** + + The class represents a complex scalar value handled by the query tree. + +*/ + +class QtComplexData : public QtScalarData +{ + public: + /// list of \Ref{QtScalarData} objects + typedef std::list<QtScalarData*> QtScalarDataList; + + /// default constructor + QtComplexData(); + + /// constructor getting a pointer to a list of \Ref{QtScalarData} objects + QtComplexData( QtScalarDataList* &scalarDataList ); + /** + Construct an object with \Ref{QtScalarData} elements of the list and + destroy the list afterwards. {\ttscalarDataList} is set to zero. + */ + + /// copy constructor + QtComplexData( const QtComplexData& obj ); + + /// print status of the object to the specified stream + virtual void printStatus( std::ostream& stream = std::cout ) const; +}; + +#include "qlparser/qtcomplexdata.icc" + +#endif + + + + + + + + + + + + + + + + + + + + + + diff --git a/qlparser/qtcomplexdata.icc b/qlparser/qtcomplexdata.icc new file mode 100644 index 0000000..2651f9c --- /dev/null +++ b/qlparser/qtcomplexdata.icc @@ -0,0 +1,29 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + diff --git a/qlparser/qtcondense.cc b/qlparser/qtcondense.cc new file mode 100644 index 0000000..7a17b93 --- /dev/null +++ b/qlparser/qtcondense.cc @@ -0,0 +1,801 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtCondense: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtcondense.cc,v 1.47 2005/09/03 20:17:55 rasdev Exp $"; + +#include "raslib/rmdebug.hh" +#include "debug.hh" + +#include "qlparser/qtcondense.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtscalardata.hh" +#include "qlparser/qtcomplexdata.hh" +#include "qlparser/qtbinaryinduce.hh" +#include "qlparser/qtbinaryinduce2.hh" + +#include "mddmgr/mddobj.hh" + +#include "catalogmgr/typefactory.hh" +#include "catalogmgr/ops.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +const QtNode::QtNodeType QtCondense::nodeType = QtNode::QT_CONDENSE; + +QtCondense::QtCondense( Ops::OpType newOpType ) + : QtUnaryOperation(), opType( newOpType ) +{ +} + + + +QtCondense::QtCondense( Ops::OpType newOpType, QtOperation* initInput ) + : QtUnaryOperation( initInput ), opType( newOpType ) +{ +} + + +QtNode::QtAreaType +QtCondense::getAreaType() +{ + return QT_AREA_SCALAR; +} + + + +void +QtCondense::optimizeLoad( QtTrimList* trimList ) +{ + // reset trimList because optimization enters a new MDD area + + // delete list + // release( trimList->begin(), trimList->end() ); + vector<QtNode::QtTrimElement*>::iterator iter; + for( iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + + delete trimList; + trimList=NULL; + + if( input ) + input->optimizeLoad( new QtNode::QtTrimList ); +} + + + +QtData* +QtCondense::computeFullCondense( QtDataList* inputList, r_Minterval& areaOp ) +{ + RMDBCLASS( "QtCondense", "computeFullCondense( QtDataList*, r_Minterval& )", "qlparser", __FILE__, __LINE__ ) + + QtScalarData* returnValue = NULL; + + // get the operand + QtData* operand = input->evaluate( inputList ); + + if( operand ) + { + +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() != QT_MDD ) + { + RMInit::logOut << "Internal error in QtCountCells::computeFullCondense() - " + << "runtime type checking failed (MDD)." << endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + return 0; + } +#endif + + QtMDD* mdd = (QtMDD*)operand; + +#ifdef QT_RUNTIME_TYPE_CHECK + if( opType == Ops::OP_SOME || opType == Ops::OP_ALL || opType == Ops::OP_COUNT ) + { + if( mdd->getCellType()->getType() != BOOLTYPE ) + { + RMInit::logOut << "Internal error in QtCondense::computeFullCondense() - " + << "runtime type checking failed (BOOL)." << endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + return 0; + } + } +#endif + + // get result type + const BaseType* resultType = Ops::getResultType( opType, mdd->getCellType() ); + + // get the MDD object + MDDObj* op = ((QtMDD*)operand)->getMDDObject(); + + // get the area, where the operation has to be applied + areaOp = mdd->getLoadDomain(); + +TALK( "computeFullCondense-last-good\n" ); + // get all tiles in relevant area + vector<Tile*>* allTiles = op->intersect(areaOp); + +TALK( "computeFullCondense-8\n" ); + // get new operation object + CondenseOp* condOp = Ops::getCondenseOp( opType, resultType, mdd->getCellType() ); + +TALK( "computeFullCondense-9\n" ); + // and iterate over them + for( vector<Tile*>::iterator tileIt = allTiles->begin(); + tileIt!=allTiles->end(); tileIt++ ) + { + // domain of the actual tile + r_Minterval tileDom = (*tileIt)->getDomain(); + + // domain of the relevant area of the actual tile + r_Minterval intersectDom = tileDom.create_intersection( areaOp ); + + (*tileIt)->execCondenseOp( condOp, intersectDom ); + } + + // delete tile vector + delete allTiles; + allTiles=NULL; + +TALK( "computeFullCondense-a\n" ); + // create result object + if( resultType->getType() == STRUCT ) + returnValue = new QtComplexData(); + else + returnValue = new QtAtomicData(); + +TALK( "computeFullCondense-b\n" ); + // allocate buffer for the result + char* resultBuffer = new char[resultType->getSize()]; + memcpy( (void*)resultBuffer, (void*)condOp->getAccuVal(), (size_t)resultType->getSize() ); + +TALK( "computeFullCondense-c\n" ); + returnValue->setValueType ( resultType ); + returnValue->setValueBuffer( resultBuffer ); + +TALK( "computeFullCondense-d\n" ); + // delete operation object + delete condOp; + condOp=NULL; + +TALK( "computeFullCondense-e\n" ); + // delete old operand + if( operand ) operand->deleteRef(); + } + +RMDBGIF(3, RMDebug::module_qlparser, "QtCondense", \ + RMInit::dbgOut << endl << "opType of QtCondense::computeFullCondense(): " << opType << endl; \ + RMInit::dbgOut << "Result.....................................: " << flush; \ + returnValue->printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; ) + return returnValue; +} + + + +const QtTypeElement& +QtCondense::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtCondense", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input ) + { + + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + +RMDBGIF(3, RMDebug::module_qlparser, "QtCondense", \ + RMInit::dbgOut << "Class..: " << getClassName() << endl; \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; ) + + if( inputType.getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtCondense::evaluate() - operand must be multidimensional." << endl; + parseInfo.setErrorNo(353); + throw parseInfo; + } + + const BaseType* baseType = ((const MDDBaseType*)(inputType.getType()))->getBaseType(); + + if( opType == Ops::OP_SOME || opType == Ops::OP_ALL ) + { + if( baseType->getType() != BOOLTYPE ) + { + RMInit::logOut << "Error: QtCondense::evaluate() - operand of quantifiers must be of type r_Marray<d_Boolean>." << endl; + parseInfo.setErrorNo(354); + throw parseInfo; + } + } + + if( opType == Ops::OP_COUNT ) + { + if( baseType->getType() != BOOLTYPE ) + { + RMInit::logOut << "Error: QtCondense::evaluate() - operand of count_cells must be of type r_Marray<d_Boolean>." << endl; + parseInfo.setErrorNo(415); + throw parseInfo; + } + } + + const BaseType* resultType = Ops::getResultType( opType, baseType ); + + if( getNodeType() == QT_AVGCELLS ) + { + // consider division by the number of cells + + const BaseType* DoubleType = TypeFactory::mapType("Double"); + const BaseType* finalResultType = Ops::getResultType( Ops::OP_DIV, resultType, DoubleType ); + + resultType = finalResultType; + } + + dataStreamType.setType( resultType ); + } + else + RMInit::logOut << "Error: QtCondense::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + + +void +QtCondense::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << getClassName() << " object" << endl; + + QtUnaryOperation::printTree( tab, s, mode ); +} + + + +void +QtCondense::printAlgebraicExpression( ostream& s ) +{ + s << getAlgebraicName() << "("; + + if( input ) + input->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtNode::QtNodeType QtSome::nodeType = QtNode::QT_SOME; + + +QtSome::QtSome() + : QtCondense( Ops::OP_SOME ) +{ +} + + +QtSome::QtSome( QtOperation* inputNew ) + : QtCondense( Ops::OP_SOME, inputNew ) +{ +} + +/* +void +QtSome::rewriteOps() +{ + if( input ) + { + if( input->getNodeType() == QtNode::QT_OR ) + { + // pushdown of condenser expression + + QtOr* orNode = (QtOr*) input; + QtOperation* node1 = orNode->getInput1(); + QtOperation* node2 = orNode->getInput2(); + + if( node1 && node2 && + node1->getAreaType() == QtNode::QT_AREA_MDD && + node2->getAreaType() == QtNode::QT_AREA_MDD ) + { + RMInit::logOut << "> rule (pushdown condenser): SOME_CELLS(A OR B) -> SOME_CELLS(A) OR SOME_CELLS(B)" << endl; + + QtSome* newNode = new QtSome( node1 ); + setInput( node2 ); + newNode->setDataStreamType( QtTypeElement(QT_BOOL) ); + + this->getParent()->setInput( this, orNode ); + orNode->setInput1( newNode ); + orNode->setInput2( this ); + orNode->setDataStreamType( QtTypeElement(QT_BOOL) ); + + newNode->rewriteOps(); + } + }; + + input->rewriteOps(); + } + else + RMInit::logOut << "Error: QtSome::rewriteOps() - the operand branch is invalid." << endl; +} +*/ + +QtData* +QtSome::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtSome", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + r_ULong dummy=0; // needed for conversion to and from CULong + + // get the operand + QtData* operand = input->evaluate( inputList ); + + if( operand ) + { +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() != QT_MDD ) + { + RMInit::logOut << "Internal error in QtSome::evaluate() - " + << "runtime type checking failed (MDD)." << endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + return 0; + } +#endif + + QtMDD* mdd = (QtMDD*)operand; + + // get result type + BaseType* resultType = (BaseType*)dataStreamType.getType(); + +#ifdef QT_RUNTIME_TYPE_CHECK + if( mdd->getCellType()->getType() != BOOLTYPE ) + RMInit::logOut << "Internal error in QtSome::evaluate() - " + << "runtime type checking failed (BOOL)." << endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + return 0; + } +#endif + + // get the MDD object + MDDObj* op = mdd->getMDDObject(); + + // get the area, where the operation has to be applied + r_Minterval areaOp = mdd->getLoadDomain(); + + // get all tiles in relevant area + vector<Tile*>* allTiles = op->intersect(areaOp); + + // allocate buffer for the result + unsigned int typeSize = resultType->getSize(); + char* resultBuffer = new char[typeSize]; + + // initialize result buffer with false + dummy = 0; + resultType->makeFromCULong( resultBuffer, &dummy ); + CondenseOp* condOp = Ops::getCondenseOp(Ops::OP_SOME, resultType, resultBuffer, resultType, 0, 0); + + // and iterate over them + for( vector<Tile*>::iterator tileIt = allTiles->begin(); tileIt != allTiles->end() && !dummy ; tileIt++ ) + { + // domain of the actual tile + r_Minterval tileDom = (*tileIt)->getDomain(); + + // domain of the relevant area of the actual tile + r_Minterval intersectDom = tileDom.create_intersection( areaOp ); + (*tileIt)->execCondenseOp( condOp, intersectDom ); + resultType->convertToCULong( condOp->getAccuVal(), &dummy ); + } + + delete condOp; + condOp = NULL; + // delete tile vector + delete allTiles; + allTiles=NULL; + + // create QtAtomicData object for the result + returnValue = new QtAtomicData( (bool)(dummy) ); + + // delete result buffer + delete[] resultBuffer; + resultBuffer = NULL; + + // The following is now then when deleting the last reference to the operand. + // delete the obsolete MDD object + // delete op; + + // delete old operand + if( operand ) operand->deleteRef(); + } + + return returnValue; +} + + + +const QtAll::QtNodeType QtAll::nodeType = QtNode::QT_ALL; + + +QtAll::QtAll() + : QtCondense( Ops::OP_ALL ) +{ +} + + +QtAll::QtAll( QtOperation* inputNew ) + : QtCondense( Ops::OP_ALL, inputNew ) +{ +} + +/* +void +QtAll::rewriteOps() +{ + if( input ) + { + if( input->getNodeType() == QtNode::QT_AND ) + { + // pushdown of condenser expression + + QtAnd* andNode = (QtAnd*) input; + QtOperation* node1 = andNode->getInput1(); + QtOperation* node2 = andNode->getInput2(); + + if( node1 && node2 && + node1->getAreaType() == QtNode::QT_AREA_MDD && + node2->getAreaType() == QtNode::QT_AREA_MDD ) + { + RMInit::logOut << "> rule (pushdown condenser): ALL_CELLS(A AND B) -> ALL_CELLS(A) AND ALL_CELLS(B)" << endl; + + QtAll* newNode = new QtAll( node1 ); + setInput( node2 ); + newNode->setDataStreamType( QtTypeElement(QT_BOOL) ); + + this->getParent()->setInput( this, andNode ); + andNode->setInput1( newNode ); + andNode->setInput2( this ); + andNode->setDataStreamType( QtTypeElement(QT_BOOL) ); + + newNode->rewriteOps(); + } + }; + + input->rewriteOps(); + + } + else + RMInit::logOut << "Error: QtAll::rewriteOps() - the operand branch is invalid." << endl; +} +*/ + +QtData* +QtAll::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtAll", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + r_ULong dummy=0; // needed for conversion to and from CULong + + // get the operand + QtData* operand = input->evaluate( inputList ); + + if( operand ) + { + +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() != QT_MDD ) + { + RMInit::logOut << "Internal error in QtAll::evaluate() - " + << "runtime type checking failed (MDD)." << endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + return 0; + } +#endif + + QtMDD* mdd = (QtMDD*)operand; + + // get result type + const BaseType* resultType = (BaseType*)dataStreamType.getType(); + +#ifdef QT_RUNTIME_TYPE_CHECK + if( mdd->getCellType()->getType() != BOOLTYPE ) + RMInit::logOut << "Internal error in QtAll::evaluate() - " + << "runtime type checking failed (BOOL)." << endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + return 0; + } +#endif + + // get the MDD object + MDDObj* op = ((QtMDD*)operand)->getMDDObject(); + + // get the area, where the operation has to be applied + r_Minterval areaOp = mdd->getLoadDomain(); + + // get all tiles in relevant area + vector<Tile*>* allTiles = op->intersect(areaOp); + + // allocate buffer for the result + unsigned int tempTypeSize = resultType->getSize(); + char* resultBuffer = new char[tempTypeSize]; + + // initialize result buffer with true + dummy = 1; + resultType->makeFromCULong( resultBuffer, &dummy ); + CondenseOp* condOp = Ops::getCondenseOp(Ops::OP_ALL, resultType, resultBuffer, resultType, 0, 0); + + for( std::vector<Tile*>::iterator tileIt = allTiles->begin(); tileIt!=allTiles->end() && dummy; tileIt++ ) + { + // domain of the actual tile + r_Minterval tileDom = (*tileIt)->getDomain(); + + // domain of the relevant area of the actual tile + r_Minterval intersectDom = tileDom.create_intersection( areaOp ); + + (*tileIt)->execCondenseOp( condOp, intersectDom ); + resultType->convertToCULong( condOp->getAccuVal(), &dummy ); + } + delete condOp; + condOp = NULL; + // delete tile vector + delete allTiles; + allTiles=NULL; + + // create QtBoolData object for the result + returnValue = new QtAtomicData( (bool)(dummy) ); + + // delete result buffer done in delete CondOp + delete[] resultBuffer; + resultBuffer=NULL; + + // delete old operand + if( operand ) operand->deleteRef(); + } + + return returnValue; +} + + + +const QtCountCells::QtNodeType QtCountCells::nodeType = QtNode::QT_COUNTCELLS; + + +QtCountCells::QtCountCells() + : QtCondense( Ops::OP_COUNT ) +{ +} + + +QtCountCells::QtCountCells( QtOperation* inputNew ) + : QtCondense( Ops::OP_COUNT, inputNew ) +{ +} + + +QtData* +QtCountCells::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtCountCells", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) +r_Minterval dummyint; + QtData* returnValue = QtCondense::computeFullCondense( inputList, dummyint ); + + return returnValue; +} + + + +const QtAddCells::QtNodeType QtAddCells::nodeType = QtNode::QT_ADDCELLS; + + +QtAddCells::QtAddCells() + : QtCondense( Ops::OP_SUM ) +{ +} + + +QtAddCells::QtAddCells( QtOperation* inputNew ) + : QtCondense( Ops::OP_SUM, inputNew ) +{ +} + + +QtData* +QtAddCells::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtAddCells", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) +r_Minterval dummyint; + + QtData* returnValue = QtCondense::computeFullCondense( inputList, dummyint ); + + return returnValue; +} + + + +const QtAvgCells::QtNodeType QtAvgCells::nodeType = QtNode::QT_AVGCELLS; + + +QtAvgCells::QtAvgCells() + : QtCondense( Ops::OP_SUM ) +{ +} + + +QtAvgCells::QtAvgCells( QtOperation* inputNew ) + : QtCondense( Ops::OP_SUM, inputNew ) +{ +} + + +QtData* +QtAvgCells::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtAvgCells", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + // domain for condensing operation + r_Minterval areaOp; + + QtData* dataCond = QtCondense::computeFullCondense( inputList, areaOp ); + + // + // divide by the number of cells + // + + QtScalarData* scalarDataResult = NULL; + QtScalarData* scalarDataCond = (QtScalarData*)dataCond; + BaseType* resultType = (BaseType*)dataStreamType.getType(); + + + // allocate memory for the result + char* resultBuffer = new char[ resultType->getSize() ]; + + // allocate ulong constant with number of cells + r_ULong constValue = areaOp.cell_count(); + const BaseType* constType = TypeFactory::mapType("ULong"); + char* constBuffer = new char[ constType->getSize() ]; + + constType->makeFromCULong( constBuffer, &constValue ); + +RMDBGIF(3, RMDebug::module_qlparser, "QtCondense", \ + RMInit::dbgOut << "Number of cells....: " << flush; \ + constType->printCell( RMInit::dbgOut, constBuffer ); \ + RMInit::dbgOut << endl; ) + + Ops::execBinaryConstOp( Ops::OP_DIV, resultType, + scalarDataCond->getValueType(), constType, + resultBuffer, + scalarDataCond->getValueBuffer(), constBuffer ); + + delete[] constBuffer; + constBuffer=NULL; + delete dataCond; + dataCond=NULL; + + if( resultType->getType() == STRUCT ) + scalarDataResult = new QtComplexData(); + else + scalarDataResult = new QtAtomicData(); + + scalarDataResult->setValueType ( resultType ); + scalarDataResult->setValueBuffer( resultBuffer ); + +RMDBGIF(3, RMDebug::module_qlparser, "QtCondense", \ + RMInit::dbgOut << endl << "Result.............: " << flush; \ + scalarDataResult->printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; ) + + return scalarDataResult; +} + + +const QtMinCells::QtNodeType QtMinCells::nodeType = QtNode::QT_MINCELLS; + + +QtMinCells::QtMinCells() + : QtCondense( Ops::OP_MIN ) +{ +} + + +QtMinCells::QtMinCells( QtOperation* inputNew ) + : QtCondense( Ops::OP_MIN, inputNew ) +{ +} + + +QtData* +QtMinCells::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtMinCells", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) +r_Minterval dummyint; + + QtData* returnValue = QtCondense::computeFullCondense( inputList, dummyint ); + + return returnValue; +} + + + +const QtMaxCells::QtNodeType QtMaxCells::nodeType = QtNode::QT_MAXCELLS; + + +QtMaxCells::QtMaxCells() + : QtCondense( Ops::OP_MAX ) +{ +} + + +QtMaxCells::QtMaxCells( QtOperation* inputNew ) + : QtCondense( Ops::OP_MAX, inputNew ) +{ +} + + +QtData* +QtMaxCells::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtMaxCells", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) +r_Minterval dummyint; + + QtData* returnValue = QtCondense::computeFullCondense( inputList, dummyint ); + + return returnValue; +} diff --git a/qlparser/qtcondense.hh b/qlparser/qtcondense.hh new file mode 100644 index 0000000..46f2fac --- /dev/null +++ b/qlparser/qtcondense.hh @@ -0,0 +1,352 @@ +#ifndef _QTCONDENSE_ +#define _QTCONDENSE_ + +#include "qlparser/qtunaryoperation.hh" +#include "raslib/minterval.hh" +#include "catalogmgr/ops.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************** + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents a condense operation in the query tree. + +*/ + +class QtCondense : public QtUnaryOperation +{ + public: + /// constructor getting operation + QtCondense( Ops::OpType newOpType); + + /// constructor getting operation and operand + QtCondense( Ops::OpType newOpType, QtOperation* input ); + + /// method for computing full condense operation (without early termination option) + QtData* computeFullCondense( QtDataList* inputList, r_Minterval& areaOp);// = r_Minterval() ); + + /// test if the edge to the parent node is of type mdd or atomic + virtual QtAreaType getAreaType(); + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + /** + The method deletes the given {\tt trimList} and passes the {\tt optimizeLoad} + message with empty triming list to its operand tree. + + Optimization process enters a new MDD area. + */ + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method returning class name + inline virtual const char* getClassName() const; + + /// method returning algebraic identifier + inline virtual const char* getAlgebraicName() const; + + protected: + /// operation type + Ops::OpType opType; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the specialized condenser {\tt some_cells()} in the query tree. + +*/ + +class QtSome : public QtCondense +{ + public: + /// default constructor + QtSome(); + + /// constructor getting the operand + QtSome( QtOperation* input ); + + /// optimizes the tree +// virtual void rewriteOps(); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method returning class name + inline virtual const char* getClassName() const; + + /// method returning algebraic identifier + inline virtual const char* getAlgebraicName() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the specialized condenser {\tt all_cells()} in the query tree. + +*/ + +class QtAll : public QtCondense +{ + public: + /// default constructor + QtAll(); + + /// constructor getting the operand + QtAll( QtOperation* input ); + + /// optimizes the tree +// virtual void rewriteOps(); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method returning class name + inline virtual const char* getClassName() const; + + /// method returning algebraic identifier + inline virtual const char* getAlgebraicName() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the specialized condenser {\tt count_cells()} in the query tree. + +*/ + +class QtCountCells : public QtCondense +{ + public: + /// default constructor + QtCountCells(); + + /// constructor getting the operand + QtCountCells( QtOperation* input ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method returning class name + inline virtual const char* getClassName() const; + + /// method returning algebraic identifier + inline virtual const char* getAlgebraicName() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the specialized condenser {\tt add_cells()} in the query tree. + +*/ + +class QtAddCells : public QtCondense +{ + public: + /// default constructor + QtAddCells(); + + /// constructor getting the operand + QtAddCells( QtOperation* input ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method returning class name + inline virtual const char* getClassName() const; + + /// method returning algebraic identifier + inline virtual const char* getAlgebraicName() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the specialized condenser {\tt avg_cells()} in the query tree. + +*/ + +class QtAvgCells : public QtCondense +{ + public: + /// default constructor + QtAvgCells(); + + /// constructor getting the operand + QtAvgCells( QtOperation* input ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method returning class name + inline virtual const char* getClassName() const; + + /// method returning algebraic identifier + inline virtual const char* getAlgebraicName() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the specialized condenser {\tt min_cells()} in the query tree. + +*/ + +class QtMinCells : public QtCondense +{ + public: + /// default constructor + QtMinCells(); + + /// constructor getting the operand + QtMinCells( QtOperation* input ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method returning class name + inline virtual const char* getClassName() const; + + /// method returning algebraic identifier + inline virtual const char* getAlgebraicName() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the specialized condenser {\tt max_cells()} in the query tree. + +*/ + +class QtMaxCells : public QtCondense +{ + public: + /// default constructor + QtMaxCells(); + + /// constructor getting the operand + QtMaxCells( QtOperation* input ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method returning class name + inline virtual const char* getClassName() const; + + /// method returning algebraic identifier + inline virtual const char* getAlgebraicName() const; + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +#include "qlparser/qtcondense.icc" + +#endif + diff --git a/qlparser/qtcondense.icc b/qlparser/qtcondense.icc new file mode 100644 index 0000000..81d8552 --- /dev/null +++ b/qlparser/qtcondense.icc @@ -0,0 +1,197 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline const char* +QtCondense::getClassName() const +{ + return "QtCondense"; +} + + +inline const char* +QtCondense::getAlgebraicName() const +{ + return "condense_cells"; +} + + + +inline const QtNode::QtNodeType +QtSome::getNodeType() const +{ + return nodeType; +} + + +inline const char* +QtSome::getClassName() const +{ + return "QtSome"; +} + + +inline const char* +QtSome::getAlgebraicName() const +{ + return "some_cells"; +} + + + +inline const QtNode::QtNodeType +QtAll::getNodeType() const +{ + return nodeType; +} + + +inline const char* +QtAll::getClassName() const +{ + return "QtAll"; +} + + +inline const char* +QtAll::getAlgebraicName() const +{ + return "all_cells"; +} + + +inline const QtNode::QtNodeType +QtCountCells::getNodeType() const +{ + return nodeType; +} + + +inline const char* +QtCountCells::getClassName() const +{ + return "QtCountCells"; +} + + +inline const char* +QtCountCells::getAlgebraicName() const +{ + return "count_cells"; +} + + +inline const QtNode::QtNodeType +QtAddCells::getNodeType() const +{ + return nodeType; +} + + +inline const char* +QtAddCells::getClassName() const +{ + return "QtAddCells"; +} + + +inline const char* +QtAddCells::getAlgebraicName() const +{ + return "add_cells"; +} + + +inline const QtNode::QtNodeType +QtAvgCells::getNodeType() const +{ + return nodeType; +} + + +inline const char* +QtAvgCells::getClassName() const +{ + return "QtAvgCells"; +} + + +inline const char* +QtAvgCells::getAlgebraicName() const +{ + return "avg_cells"; +} + + + +inline const QtNode::QtNodeType +QtMinCells::getNodeType() const +{ + return nodeType; +} + + +inline const char* +QtMinCells::getClassName() const +{ + return "QtMinCells"; +} + + +inline const char* +QtMinCells::getAlgebraicName() const +{ + return "min_cells"; +} + + + +inline const QtNode::QtNodeType +QtMaxCells::getNodeType() const +{ + return nodeType; +} + + +inline const char* +QtMaxCells::getClassName() const +{ + return "QtMaxCells"; +} + + +inline const char* +QtMaxCells::getAlgebraicName() const +{ + return "max_cells"; +} + + + + diff --git a/qlparser/qtcondenseop.cc b/qlparser/qtcondenseop.cc new file mode 100644 index 0000000..a20f956 --- /dev/null +++ b/qlparser/qtcondenseop.cc @@ -0,0 +1,440 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * 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 <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +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( "<nn>" ); + + 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 << "<nn>"; + + s << ","; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + 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; +} + + diff --git a/qlparser/qtcondenseop.hh b/qlparser/qtcondenseop.hh new file mode 100644 index 0000000..d1c3e8e --- /dev/null +++ b/qlparser/qtcondenseop.hh @@ -0,0 +1,131 @@ +#ifndef _QTCONDENSEOP_ +#define _QTCONDENSEOP_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtbinaryoperation.hh" + +#include "catalogmgr/ops.hh" +#include <stdio.h> + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the root of a cond expression. + +*/ + +class QtCondenseOp : public QtBinaryOperation +{ + public: + /// constructor getting iterator, minterval exp, cell exp, and cell condition exp (optional) + QtCondenseOp( Ops::OpType newOperation, + const std::string& initIteratorName, + QtOperation* mintervalExp, + QtOperation* cellExp, + QtOperation* condExp = NULL ); + + /// virtual destructor + ~QtCondenseOp(); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// test if the two nodes have an equal meaning in a subtree + virtual bool equalMeaning( QtNode* node ); + + /// creates a unique name for a common subexpression + virtual std::string getSpelling(); + + /// method for query rewrite + virtual void setInput( QtOperation* inputOld, QtOperation* inputNew ); + + /// optimizing load access + void optimizeLoad( QtTrimList* trimList ); + + /// simplifies the tree + virtual void simplify(); + + /// returns FALSE saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + /** + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + //@Man: Read/Write methods: + //@{ + /// + + /// + inline QtOperation* getCondOp(); + + /// + //@} + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; + + /// attribute storing the iterator name + std::string iteratorName; + + /// attribute storing optional cell condition expression + QtOperation* condOp; + + /// attribute storing condensing operation + Ops::OpType operation; +}; + + +#include "qlparser/qtcondenseop.icc" + +#endif + diff --git a/qlparser/qtcondenseop.icc b/qlparser/qtcondenseop.icc new file mode 100644 index 0000000..6ba6fad --- /dev/null +++ b/qlparser/qtcondenseop.icc @@ -0,0 +1,44 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtCondenseOp::getNodeType() const +{ + return nodeType; +} + + + +inline QtOperation* +QtCondenseOp::getCondOp() +{ + return condOp; +} + + diff --git a/qlparser/qtconst.cc b/qlparser/qtconst.cc new file mode 100644 index 0000000..b4896f0 --- /dev/null +++ b/qlparser/qtconst.cc @@ -0,0 +1,265 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtConst: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtconst.cc,v 1.22 2005/07/06 22:48:34 rasdev Exp $"; + +#include "qlparser/qtconst.hh" +#include "qlparser/qtscalardata.hh" +#include "qlparser/qtstringdata.hh" + +#include "qlparser/qtmdd.hh" // these three can be deleted with new memory management + +#include "relcatalogif/basetype.hh" +#include "mddmgr/mddobj.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +#include <iostream> + +// deprecated, not available any longer -- PB 2005-jan-14 +// #include <strstream.h> + +const QtNode::QtNodeType QtConst::nodeType = QtNode::QT_CONST; + + +QtConst::QtConst( QtData* newDataObj ) + : QtOperation(), + dataObj( newDataObj ) +{ + // store parse info of the data object + setParseInfo( dataObj->getParseInfo() ); +} + + + +QtConst::~QtConst() +{ + if( dataObj ) dataObj->deleteRef(); +} + + + +bool +QtConst::equalMeaning( QtNode* node ) +{ + RMDBCLASS( "QtConst", "equalMeaning( QtNode* )", "qlparser", __FILE__, __LINE__ ) + + bool result = false; + + if( nodeType == node->getNodeType() ) + { + QtConst* constObj = (QtConst*) node; + + result = dataObj->equal( constObj->getDataObj() ); + } + + return result; +} + + +string +QtConst::getSpelling() +{ + char tempStr[20]; + sprintf(tempStr, "%ud", (unsigned long)getNodeType()); + string result = string(tempStr); + result.append( dataObj->getSpelling() ); + + return result; +} + + +QtNode::QtAreaType +QtConst::getAreaType() +{ + if( dataObj && dataObj->getDataType() == QT_MDD ) + return QT_AREA_MDD; + else + return QT_AREA_SCALAR; +} + + +void +QtConst::optimizeLoad( QtTrimList* trimList ) +{ + RMDBCLASS( "QtConst", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) + + if( trimList ) + { + if( trimList->size() ) + { + if( dataObj && dataObj->getDataType() == QT_MDD ) + { + // 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 + r_Minterval loadDomain(maxDimension+1); + + // fill the loadDomain object with the QtTrimList specifications + for( i=trimList->begin(); i!=trimList->end(); i++ ) + loadDomain[(*i)->dimension] = (*i)->interval; + + ((QtMDD*)dataObj)->setLoadDomain( loadDomain ); + } + + // release( trimList->begin(), trimList->end() ); + vector<QtNode::QtTrimElement*>::iterator iter; + for( iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + } + + delete trimList; + trimList=NULL; + } +} + + +QtData* +QtConst::evaluate( QtDataList* /*inputList*/ ) +{ + RMDBCLASS( "QtConst", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + + if( dataObj ) + { + dataObj->incRef(); + returnValue = dataObj; + } + + return returnValue; +} + + + +void +QtConst::printTree( int tab, ostream& s, QtChildType /*mode*/ ) +{ + s << SPACE_STR(tab).c_str() << "QtConst Object: type " << flush; + dataStreamType.printStatus( s ); + s << endl; + + s << SPACE_STR(tab).c_str() << " "; + + if( dataObj ) + dataObj->printStatus( s ); + else + s << "<no data object>"; + + s << endl; +} + + + +void +QtConst::printAlgebraicExpression( ostream& s ) +{ + if( dataObj->isScalarData() ) + { + QtScalarData* scalarDataObj = (QtScalarData*)dataObj; + + if( scalarDataObj->getValueType() ) + { + // Print the value but first cut leading blanks. + char valueString[1024]; + // replaced deprecated ostrstream -- PB 2005-jan-14 + // ostrstream valueStream( valueString, 1024 ); + ostringstream valueStream( valueString ); + + scalarDataObj->getValueType()->printCell( valueStream, scalarDataObj->getValueBuffer() ); + + valueStream << ends; + + char* p = valueString; + while( *p == ' ' ) p++; + + s << p; + } + else + s << "<nn>"; + } + else if( dataObj->getDataType() == QT_STRING ) + { + s << ((QtStringData*)dataObj)->getStringData().c_str(); + } + else + s << "<nn>"; +} + + + +const QtTypeElement& +QtConst::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtConst", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + if( dataObj ) + { + switch( dataObj->getDataType() ) + { + case QT_STRING: + case QT_INTERVAL: + case QT_MINTERVAL: + case QT_POINT: + dataStreamType.setDataType( dataObj->getDataType() ); + break; + case QT_MDD: + if( ((QtMDD*)dataObj)->getMDDObject() ) + dataStreamType.setType((Type*)((QtMDD*)dataObj)->getMDDObject()->getMDDBaseType() ); + break; + default: + dataStreamType.setType( ((QtScalarData*)dataObj)->getValueType() ); + } + } + + return dataStreamType; +} + + + diff --git a/qlparser/qtconst.hh b/qlparser/qtconst.hh new file mode 100644 index 0000000..6dce957 --- /dev/null +++ b/qlparser/qtconst.hh @@ -0,0 +1,117 @@ +#ifndef _QTCONST_ +#define _QTCONST_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtdata.hh" +#include "qlparser/qtoperation.hh" +#include <stdio.h> + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class serves as a carrier for a {\tt QtData} object + and, additionally, provides functionality necessary in + the query tree. + +*/ + +class QtConst : public QtOperation +{ + public: + /// constructor getting a pointer to the data object + QtConst( QtData* newDataObj ); + /** + Lifetime of {\tt newDataObj} is managed by this class from now on. + */ + + /// virtual destructor + virtual ~QtConst(); + + /// test if the two nodes have an equal meaning in the query tree + virtual bool equalMeaning( QtNode* node ); + + /// creates a unique name for a common subexpression + virtual std::string getSpelling(); + + /// test if the edge to the parent node is of type mdd or atomic + virtual QtAreaType getAreaType(); + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + //@Man: Operations of the ONC protocol: + //@{ + /// + QtDataList* next(); + //@} + + //@Man: Read/Write methods: + //@{ + /// + /// return the data object + inline QtData* getDataObj(); + /// + //@} + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// pointer to the data object + QtData* dataObj; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtconst.icc" + +#endif + diff --git a/qlparser/qtconst.icc b/qlparser/qtconst.icc new file mode 100644 index 0000000..9d968d6 --- /dev/null +++ b/qlparser/qtconst.icc @@ -0,0 +1,43 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtConst::getNodeType() const +{ + return nodeType; +} + + + +inline QtData* +QtConst::getDataObj() +{ + return dataObj; +} + diff --git a/qlparser/qtconversion.cc b/qlparser/qtconversion.cc new file mode 100644 index 0000000..72d751f --- /dev/null +++ b/qlparser/qtconversion.cc @@ -0,0 +1,590 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtConversion: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtconversion.cc,v 1.36 2003/12/27 20:51:28 rasdev Exp $"; + +#include "raslib/rmdebug.hh" +#include "raslib/basetype.hh" +#include "raslib/structuretype.hh" +#include "conversion/convertor.hh" +#include "conversion/convfactory.hh" + +#include "qlparser/qtconversion.hh" +#include "qlparser/qtmdd.hh" + +#include "mddmgr/mddobj.hh" +#include "tilemgr/tile.hh" + +#include "catalogmgr/typefactory.hh" +#include "relcatalogif/typeiterator.hh" +#include "relcatalogif/structtype.hh" +#include "relcatalogif/chartype.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +const QtNode::QtNodeType QtConversion::nodeType = QtNode::QT_CONVERSION; + + +QtConversion::QtConversion( QtOperation* newInput, QtConversionType +newConversionType, const char* s ) + : conversionType( newConversionType ), QtUnaryOperation( newInput ), paramStr(s) +{ + RMDBGONCE(2, RMDebug::module_qlparser, "QtConversion", "QtConversion()" ) +} + +void +QtConversion::setConversionTypeByName( string formatName ) +{ + if(string("bmp") == formatName) + conversionType = QtConversion::QT_TOBMP; + else if(string("hdf") == formatName ) + conversionType = QtConversion::QT_TOHDF; + else if(string("png") == formatName) + conversionType = QtConversion::QT_TOPNG; + else if (string("jpeg") == formatName) + conversionType = QtConversion::QT_TOJPEG; + else if (string("tiff") == formatName) + conversionType = QtConversion::QT_TOTIFF; + else if (string("vff") == formatName) + conversionType = QtConversion::QT_TOVFF; + else if (string("csv") == formatName) + conversionType = QtConversion::QT_TOCSV; + else if (string("tor") == formatName) + conversionType = QtConversion::QT_TOTOR; + else if (string("dem") == formatName) + conversionType = QtConversion::QT_TODEM; + else if(string("inv_bmp") == formatName ) + conversionType = QtConversion::QT_FROMBMP; + else if(string("inv_hdf") == formatName ) + conversionType = QtConversion::QT_FROMHDF; + else if(string("inv_csv") == formatName ) + conversionType = QtConversion::QT_FROMCSV; + else if(string("inv_png") == formatName) + conversionType = QtConversion::QT_FROMPNG; + else if (string("inv_jpeg") == formatName) + conversionType = QtConversion::QT_FROMJPEG; + else if (string("inv_tiff") == formatName) + conversionType = QtConversion::QT_FROMTIFF; + else if (string("inv_vff") == formatName) + conversionType = QtConversion::QT_FROMVFF; + else if (string("inv_tor") == formatName) + conversionType = QtConversion::QT_FROMTOR; + else if (string("inv_dem") == formatName) + conversionType = QtConversion::QT_FROMDEM; + else + conversionType = QtConversion::QT_UNKNOWN; +} + +bool +QtConversion::lookupConversionTypeByName( string formatName ) +{ + return (( string("bmp") == formatName ) || ( string("hdf") == formatName ) || + ( string("png") == formatName ) || ( string("jpeg") == formatName ) || + ( string("dem") == formatName ) || ( string("tor") == formatName ) || + ( string("csv") == formatName ) || ( string("inv_csv") == formatName ) || + ( string("tiff") == formatName ) || ( string("vff") == formatName ) || + ( string("inv_bmp") == formatName ) || ( string("inv_hdf") == formatName ) || + ( string("inv_png") == formatName ) || ( string("inv_jpeg") == formatName ) || + ( string("inv_dem") == formatName ) || ( string("inv_tor") == formatName ) || + ( string("inv_tiff") == formatName ) || ( string("inv_vff") == formatName )); + +} + +bool +QtConversion::equalMeaning( QtNode* node ) +{ + + bool result = false; + + if( nodeType == node->getNodeType() ) + { + QtConversion* convNode; + convNode = (QtConversion*) node; // by force + + result = input->equalMeaning( convNode->getInput() ); + + result &= conversionType == convNode->conversionType; + }; + + return ( result ); +} + + +QtData* +QtConversion::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtConversion", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtData* operand = NULL; + + if( conversionType == QT_UNKNOWN ) + { + RMInit::logOut << "Error: QtConversion::evaluate() - unknown conversion format." << std::endl; + parseInfo.setErrorNo(382); + throw parseInfo; + } + + operand = input->evaluate( inputList ); + + if( operand ) + { +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() != QT_MDD ) + { + RMInit::logOut << "Internal error in QtConversion::evaluate() - " + << "runtime type checking failed (MDD)." << std::endl; + + // delete old operand + if( operand ) operand->deleteRef(); + return 0; + } +#endif + + QtMDD* qtMDD = (QtMDD*) operand; + MDDObj* currentMDDObj = qtMDD->getMDDObject(); + Tile* sourceTile = NULL; + vector< Tile* >* tiles = NULL; + if (qtMDD->getLoadDomain().is_origin_fixed() && qtMDD->getLoadDomain().is_high_fixed()) + { + // get relevant tiles + tiles = currentMDDObj->intersect( qtMDD->getLoadDomain() ); + } + else { + RMDBGONCE(2, RMDebug::module_qlparser, "QtConversion", "evalutate() - no tile available to convert." ) + return operand; + } + + // check the number of tiles + if( !tiles->size() ) + { + RMDBGONCE(2, RMDebug::module_qlparser, "QtConversion", "evalutate() - no tile available to convert." ) + return operand; + } + + // create one single tile with the load domain + sourceTile = new Tile( tiles, qtMDD->getLoadDomain() ); + + // delete the tile vector + delete tiles; + tiles = NULL; + + // get type structure of the operand base type + char* typeStructure = qtMDD->getCellType()->getTypeStructure(); + + // convert structure to r_Type + r_Type* baseSchema = r_Type::get_any_type( typeStructure ); + + free( typeStructure ); + typeStructure = NULL; + RMDBGONCE(2, RMDebug::module_qlparser, "QtConversion", "evalutate() - no tile available to convert." ) + RMDBGIF(2, RMDebug::module_qlparser, "QtConversion", \ + RMInit::dbgOut << "Cell base type for conversion: " << std::flush; \ + baseSchema->print_status( RMInit::dbgOut ); \ + RMInit::dbgOut << std::endl; ) + + // + // real conversion + // + + r_convDesc convResult; + r_Minterval tileDomain = sourceTile->getDomain(); + + //convertor type + r_Data_Format convType = r_Array; + //result type from convertor + r_Data_Format convFormat = r_Array; + + switch (conversionType) + { + case QT_TOTIFF: + convType = r_TIFF; + convFormat = r_TIFF; + break; + case QT_FROMTIFF: + convType = r_TIFF; + convFormat = r_Array; + break; + case QT_TOBMP: + convType = r_BMP; + convFormat = r_BMP; + break; + case QT_FROMBMP: + convType = r_BMP; + convFormat = r_Array; + break; + case QT_TOHDF: + convType = r_HDF; + convFormat = r_HDF; + break; + case QT_TOCSV: + convType = r_CSV; + convFormat = r_CSV; + break; + case QT_FROMHDF: + convType = r_HDF; + convFormat = r_Array; + break; + case QT_FROMCSV: + convType = r_CSV; + convFormat = r_Array; + break; + case QT_TOJPEG: + convType = r_JPEG; + convFormat = r_JPEG; + break; + case QT_FROMJPEG: + convType = r_JPEG; + convFormat = r_Array; + break; + case QT_TOPNG: + convType = r_PNG; + convFormat = r_PNG; + break; + case QT_FROMPNG: + convType = r_PNG; + convFormat = r_Array; + break; + case QT_TOVFF: + convType = r_VFF; + convFormat = r_VFF; + break; + case QT_FROMVFF: + convType = r_VFF; + convFormat = r_Array; + break; + case QT_TOTOR: + convType = r_TOR; + convFormat = r_TOR; + break; + case QT_FROMTOR: + convType = r_TOR; + convFormat = r_Array; + break; + case QT_TODEM: + convType = r_DEM; + convFormat = r_DEM; + break; + case QT_FROMDEM: + convType = r_DEM; + convFormat = r_Array; + break; + default: + RMInit::logOut << "Error: QtConversion::evaluate(): unsupported format " << conversionType << std::endl; + throw r_Error(CONVERSIONFORMATNOTSUPPORTED); + break; + } + convFormat = r_Array; + + r_Convertor *convertor = NULL; + + try { + convertor = r_Convertor_Factory::create(convType, sourceTile->getContents(), tileDomain, baseSchema); + if(conversionType < QT_FROMTIFF) { + RMDBGONCE(2, RMDebug::module_qlparser, "QtConversion", "evalutate() - convertor " << convType << " converting to " << convFormat << "..."); + convResult = convertor->convertTo(paramStr); + } + else { + RMDBGONCE(2, RMDebug::module_qlparser, "QtConversion", "evalutate() - convertor " << convType << " converting from " << convFormat << "..."); + convResult = convertor->convertFrom(paramStr); + } + } + catch (r_Error &err) { + RMInit::logOut << "Error: QtConversion::evaluate(): conversion failed" << std::endl; + delete sourceTile; + sourceTile = NULL; + delete baseSchema; + baseSchema = NULL; + // delete old operand + if( operand ) operand->deleteRef(); + if (convertor != NULL) { + delete convertor; + convertor=NULL; + } + + parseInfo.setErrorNo(381); + throw parseInfo; + } + if (convertor != NULL) { + delete convertor; + convertor=NULL; + } + + RMDBGMIDDLE(2, RMDebug::module_qlparser, "QtConversion", "evalutate() - ok") + + + // + // done + // + + // delete sourceTile + delete sourceTile; + sourceTile = NULL; + + // create a transient tile for the compressed data + const BaseType* myType = NULL; + const r_Type* currStruct = NULL; + if(convResult.destType->isPrimitiveType()) { + myType=TypeFactory::mapType(convResult.destType->name()); + if(myType == NULL) { + RMInit::logOut << "Error: QtConversion::evaluate() no primitive type compatible found" << std::endl; + delete convResult.destType; + convResult.destType=NULL; + delete convResult.dest; + convResult.dest=NULL; + throw r_Error(BASETYPENOTSUPPORTED); + } + + if(strcasecmp( dataStreamType.getType()->getTypeName(), myType->getTypeName())) { + //FIXME here we have to change the dataStreamType.getType(), is not char for + //conversion from_DEF all the time, we don't know the result type until we parse the data + MDDBaseType* mddBaseType = new MDDBaseType( "tmp", TypeFactory::mapType(myType->getTypeName()) ); + TypeFactory::addTempType( mddBaseType ); + + dataStreamType.setType( mddBaseType ); + RMInit::logOut << " QtConversion::evaluate() for conversion " << conversionType << " real result is " << std::flush; + dataStreamType.printStatus(RMInit::logOut); + RMInit::logOut << std::endl; + } + } + else { //we assume that we deal with structure types + TypeIterator<StructType> structIter = TypeFactory::createStructIter(); + while(structIter.not_done()) { + // get type structure of current structtype + typeStructure = structIter.get_element()->getTypeStructure(); + // convert structure to r_Type + currStruct = r_Type::get_any_type( typeStructure ); + + if(currStruct == NULL) { + RMInit::logOut << "Error: QtConversion::evaluate() no structure type compatible found" << std::endl; + delete convResult.destType; + convResult.destType=NULL; + delete convResult.dest; + convResult.dest=NULL; + throw r_Error(STRUCTTYPE_ELEMENT_UNKNOWN); + } + + free(typeStructure); + typeStructure = NULL; + + if(((r_Structure_Type*)currStruct)->compatibleWith((r_Structure_Type*)convResult.destType)) { + //we found a type + delete currStruct; + currStruct = NULL; + myType=structIter.get_element().ptr(); + break; + } + + delete currStruct; + currStruct = NULL; + structIter.advance(); + } + if(myType == NULL) { + RMInit::logOut << "Error: QtConversion::evaluate() no structure type compatible found" << std::endl; + delete convResult.destType; + convResult.destType=NULL; + delete convResult.dest; + convResult.dest=NULL; + throw r_Error(STRUCTTYPE_ELEMENT_UNKNOWN); + } + + if(strcasecmp(dataStreamType.getType()->getTypeName(), myType->getTypeName())) { + //FIXME here we have to change the dataStreamType.getType(), is not char for + //conversion from_DEF all the time, we don't know the result type until we parse the data + MDDBaseType* mddBaseType = new MDDBaseType( "tmp", TypeFactory::mapType(myType->getTypeName()) ); + TypeFactory::addTempType( mddBaseType ); + + dataStreamType.setType( mddBaseType ); + RMInit::logOut << " QtConversion::evaluate() for conversion " << conversionType << " real result is " << std::flush; + dataStreamType.printStatus(RMInit::logOut); + RMInit::logOut << std::endl; + } + } + + Tile* resultTile = new Tile( convResult.destInterv, + myType, + convResult.dest, + 0, + convFormat ); + + // delete destination type + if( convResult.destType ) { + delete convResult.destType; + convResult.destType=NULL; + } + + // create a transient MDD object for the query result + MDDBaseType* mddBaseType = (MDDBaseType*)dataStreamType.getType(); + MDDObj* resultMDD = new MDDObj( mddBaseType, convResult.destInterv ); + resultMDD->insertTile( resultTile ); + + // create a new QtMDD object as carrier object for the transient MDD object + returnValue = new QtMDD( (MDDObj*)resultMDD ); + + // delete base type schema + delete baseSchema; + baseSchema = NULL; + + // delete old operand + if( operand ) operand->deleteRef(); + } + else + RMInit::logOut << "Error: QtConversion::evaluate() - operand is not provided." << std::endl; + + return returnValue; +} + + +void +QtConversion::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtConversion Object: "; + + switch( conversionType ) + { + case QT_TOTIFF: s << "to TIFF"; break; + case QT_TOBMP: s << "to BMP"; break; + case QT_TOHDF: s << "to HDF"; break; + case QT_TOCSV: s << "to CSV"; break; + case QT_TOJPEG: s << "to JPEG"; break; + case QT_TOPNG: s << "to PNG"; break; + case QT_TOVFF: s << "to VFF"; break; + case QT_TOTOR: s << "to TOR"; break; + case QT_TODEM: s << "to DEM"; break; + case QT_FROMTIFF: s << "from TIFF"; break; + case QT_FROMBMP: s << "from BMP"; break; + case QT_FROMHDF: s << "from HDF"; break; + case QT_FROMCSV: s << "from CSV"; break; + case QT_FROMJPEG: s << "from JPEG"; break; + case QT_FROMPNG: s << "from PNG"; break; + case QT_FROMVFF: s << "from VFF"; break; + case QT_FROMTOR: s << "from TOR"; break; + case QT_FROMDEM: s << "from DEM"; break; + default: s << "unknown conversion"; break; + } + + s << std::endl; + + QtUnaryOperation::printTree( tab, s, mode ); +} + + + +void +QtConversion::printAlgebraicExpression( ostream& s ) +{ + s << conversionType << "("; + + if( input ) + input->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtTypeElement& +QtConversion::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtConversion", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input ) + { + + // get input type + const QtTypeElement& inputType = input->checkType( typeTuple ); + + if( inputType.getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtConversion::checkType() - operand is not of type MDD." << std::endl; + parseInfo.setErrorNo(380); + throw parseInfo; + } + + //FIXME we set for every kind of conversion the result type char + //for conversion from_DEF we don't know the result type until we parse the data + MDDBaseType* mddBaseType = new MDDBaseType( "Char", TypeFactory::mapType("Char") ); + TypeFactory::addTempType( mddBaseType ); + + dataStreamType.setType( mddBaseType ); + + if(conversionType>QT_TODEM) { + RMInit::logOut << std::endl << "QtConversion::checkType() for conversion " << conversionType << " assume the result " << std::flush; + dataStreamType.printStatus(RMInit::logOut); + RMInit::logOut << std::endl; + } + } + else + RMInit::logOut << "Error: QtConversion::checkType() - operand branch invalid." << std::endl; + + return dataStreamType; +} + +std::ostream& +operator<< (std::ostream& os, QtConversion::QtConversionType type) { + switch( type ) + { + case QtConversion::QT_TOTIFF: os << "tiff"; break; + case QtConversion::QT_TOBMP: os << "bmp"; break; + case QtConversion::QT_TOHDF: os << "hdf"; break; + case QtConversion::QT_TOCSV: os << "csv"; break; + case QtConversion::QT_TOJPEG: os << "jpeg"; break; + case QtConversion::QT_TOPNG: os << "png"; break; + case QtConversion::QT_TOVFF: os << "vff"; break; + case QtConversion::QT_TOTOR: os << "tor"; break; + case QtConversion::QT_TODEM: os << "dem"; break; + case QtConversion::QT_FROMTIFF: os << "inv_tiff"; break; + case QtConversion::QT_FROMBMP: os << "inv_bmp"; break; + case QtConversion::QT_FROMHDF: os << "inv_hdf"; break; + case QtConversion::QT_FROMCSV: os << "inv_csv"; break; + case QtConversion::QT_FROMJPEG: os << "inv_jpeg"; break; + case QtConversion::QT_FROMPNG: os << "inv_png"; break; + case QtConversion::QT_FROMVFF: os << "inv_vff"; break; + case QtConversion::QT_FROMTOR: os << "inv_tor"; break; + case QtConversion::QT_FROMDEM: os << "inv_dem"; break; + default: os << "unknown Conversion"; break; + } + + return os; +} + diff --git a/qlparser/qtconversion.hh b/qlparser/qtconversion.hh new file mode 100644 index 0000000..6bb44bc --- /dev/null +++ b/qlparser/qtconversion.hh @@ -0,0 +1,113 @@ +#ifndef _QTCONVERSION_HH__ +#define _QTCONVERSION_HH___ + +#include "qlparser/qtunaryoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents a format conversion. The conversion is described by + an enumerator. + +*/ + +class QtConversion : public QtUnaryOperation +{ + public: + enum QtConversionType + { + QT_UNKNOWN, + QT_TOTIFF, + QT_TOBMP, + QT_TOHDF, + QT_TOCSV, + QT_TOJPEG, + QT_TOPNG, + QT_TOVFF, + QT_TOTOR, + QT_TODEM, + QT_FROMTIFF, + QT_FROMBMP, + QT_FROMHDF, + QT_FROMCSV, + QT_FROMJPEG, + QT_FROMPNG, + QT_FROMVFF, + QT_FROMTOR, + QT_FROMDEM + }; + + /// constructor getting operand and format conversion type + QtConversion( QtOperation* newInput, QtConversionType newConversionType, const char* = NULL ); + + /// set the format conversion type by name + void setConversionTypeByName( std::string formatName ); + + /// look up the format conversion type by name + static bool lookupConversionTypeByName( std::string formatName ); + + /// test if the two nodes have an equal meaning in a subtree + virtual bool equalMeaning( QtNode* node ); + + /// evaluates the node + QtData* evaluate( QtDataList* inputList ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute storing conversion type + QtConversionType conversionType; + + /// attribute for identification of nodes + static const QtNodeType nodeType; + + const char* paramStr; +}; + +extern std::ostream& operator<<(std::ostream& os, QtConversion::QtConversionType t); + +#include "qlparser/qtconversion.icc" + +#endif + diff --git a/qlparser/qtconversion.icc b/qlparser/qtconversion.icc new file mode 100644 index 0000000..410e34e --- /dev/null +++ b/qlparser/qtconversion.icc @@ -0,0 +1,35 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline const QtNode::QtNodeType +QtConversion::getNodeType() const +{ + return nodeType; +} diff --git a/qlparser/qtdata.cc b/qlparser/qtdata.cc new file mode 100644 index 0000000..1ef0735 --- /dev/null +++ b/qlparser/qtdata.cc @@ -0,0 +1,127 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtData: $Id: qtdata.cc,v 1.17 2002/06/05 18:18:17 coman Exp $"; + +#include "raslib/rmdebug.hh" +#include "qlparser/qtdata.hh" + + +QtData::QtData() + : referenceCounter(1), + persistent( QT_TRANSIENT ), + parseInfo(NULL) +{ + RMDBGONCE( 10, RMDebug::module_qlparser, "QtData", "QtData::QtData() Obj: " << this ) +} + + + +QtData::QtData( const std::string name ) + : iteratorName( name ), + referenceCounter(1), + persistent( QT_TRANSIENT ), + parseInfo(NULL) +{ + RMDBGONCE( 10, RMDebug::module_qlparser, "QtData", "QtData::QtData( const std::string ) Obj: " << this ) +} + + + +QtData::QtData( const QtData &obj ) + : iteratorName( obj.iteratorName ), + persistent( obj.persistent ), + referenceCounter(1), + parseInfo(NULL) +{ + RMDBGONCE( 10, RMDebug::module_qlparser, "QtData", "QtData::QtData( QtData& ) Obj: " << this ) + + if( obj.parseInfo ) + parseInfo = new ParseInfo( *(obj.parseInfo) ); +} + + + +QtData::~QtData() +{ + RMDBGONCE( 10, RMDebug::module_qlparser, "QtData", "QtData::~QtData() Obj: " << this ) + + if( parseInfo ) + { + delete parseInfo; + parseInfo=NULL; + } +} + + + +bool +QtData::isScalarData() const +{ + // default implementation returns false + return false; +} + + + +const QtData& +QtData::operator=( const QtData& obj ) +{ + RMDBGONCE( 10, RMDebug::module_qlparser, "QtData", "QtData::operator=" ) + + if( this != &obj ) + { + iteratorName = obj.iteratorName; + persistent = obj.persistent; + referenceCounter = 1; + + if( parseInfo ) + { + delete parseInfo; + parseInfo = NULL; + } + + if( obj.parseInfo ) + parseInfo = new ParseInfo( *(obj.parseInfo) ); + } + + return *this; +} + + + +void +QtData::printStatus( std::ostream& stream ) const +{ + if( iteratorName.size() ) + stream << ", iter name: " << iteratorName.c_str() << std::flush; + + stream << ", ref#: " << referenceCounter + << ( persistent == QT_TRANSIENT ? " trans " : " pers " ) << std::flush; +} diff --git a/qlparser/qtdata.hh b/qlparser/qtdata.hh new file mode 100644 index 0000000..ee2e285 --- /dev/null +++ b/qlparser/qtdata.hh @@ -0,0 +1,200 @@ +#ifndef _QTDATA_ +#define _QTDATA_ + +#include <iostream> + +#include "qlparser/parseinfo.hh" +#include "raslib/rminit.hh" + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@Man: TypeEnum +//@Type: typedef +//@Memo: Module: {\bf qlparser}. + +enum QtDataType +{ + QT_TYPE_UNKNOWN, + QT_BOOL, + QT_CHAR, + QT_OCTET, + QT_USHORT, + QT_SHORT, + QT_ULONG, + QT_LONG, + QT_FLOAT, + QT_DOUBLE, + QT_COMPLEXTYPE1, // with float members + QT_COMPLEXTYPE2, // with double + QT_MDD, + QT_COMPLEX, + QT_STRING, + QT_INTERVAL, + QT_MINTERVAL, + QT_POINT +}; + + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +This class is superclass for the classes representing a +specific data type handled by the query tree. + +*/ + +class QtData +{ + public: + // construktor + QtData(); + + // constructor + QtData( const std::string name ); + + /// copy constructor + QtData( const QtData &obj ); + + /// destructor + virtual ~QtData(); + + /// assignement operator + const QtData& operator=( const QtData& obj ); + + enum QtLifetime + { + QT_PERSISTENT, + QT_TRANSIENT + }; + + /// returns type of data represented by the QtData object + virtual QtDataType getDataType() const = 0; + /** + \begin{tabular}{lll} + QtMDD&&QT_MDD\\ + QtAtomicData&&QT_BOOL\\ + &&QT_CHAR\\ + &&QT_OCTET\\ + &&QT_USHORT\\ + &&QT_SHORT\\ + &&QT_ULONG\\ + &&QT_FLOAT\\ + &&QT_DOUBLE\\ + QtComplexData&&QT_COMPLEX\\ + QtString&&QT_STRING\\ + QtInterval&&QT_INTERVAL\\ + QtMinterval&&QT_MINTERVAL\\ + QtPoint&&QT_POINT\\ + \end{tabular} + */ + + /// returns a null-terminated string describing the type structure + virtual char* getTypeStructure() const = 0; + /** + The string pointer has to be free using free() by the caller. + */ + + /// determines, if the data is of type scalar + virtual bool isScalarData() const; + + /// compares data content + virtual bool equal( const QtData* obj ) const = 0; + + /// returns content dependent string representation + virtual std::string getSpelling() const = 0; + + //@Man: Read/Write methods: + //@{ + /// + + /// get the iterator name + inline std::string const getIteratorName() const; + /// + inline void setIteratorName( const std::string & iteratorNameNew ); + /// + inline QtLifetime const getLifetime() const; + /// + inline void setLifetime( QtLifetime flag ); + /// return number of references to the self object + inline unsigned int getRefNo() const; + /// increases the reference counter by one + inline void incRef(); + /// deletes one reference and the object if it was the last one + inline int deleteRef(); + /** + In case the object is deleted, 1 is returned, 0 otherwise. + */ + + /// + inline ParseInfo getParseInfo(); + /// + inline void setParseInfo( const ParseInfo &info ); + + /// + //@} + + /// print status of the object to the specified stream + virtual void printStatus( std::ostream& stream = std::cout ) const; + + protected: + /// pointer to an optional parser info + ParseInfo* parseInfo; + + private: + /// decreases the reference counter by one and returns the new value + inline unsigned int decRef(); + + /// attribute storing the iterator name + std::string iteratorName; + + /// attribute storing the lifetime (persistent, transient) + QtLifetime persistent; + /** + Objects of subclasses of QtScalarData (QtAtomicData and QtComplexdata) are always transient. + Objects of subclass QtMDD are persistent or transient. + */ + + /// counts the number of references to the data object + unsigned int referenceCounter; +}; + +#include "qlparser/qtdata.icc" + +#endif + diff --git a/qlparser/qtdata.icc b/qlparser/qtdata.icc new file mode 100644 index 0000000..677559e --- /dev/null +++ b/qlparser/qtdata.icc @@ -0,0 +1,137 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline void +QtData::setIteratorName( const std::string &iteratorNameNew ) +{ + iteratorName = iteratorNameNew; +} + + +inline const std::string +QtData::getIteratorName() const +{ + return iteratorName; +} + + +inline const QtData::QtLifetime +QtData::getLifetime() const +{ + return persistent; +} + + +inline void +QtData::setLifetime( QtLifetime flag) +{ + persistent = flag; +} + + + +inline unsigned int +QtData::getRefNo() const +{ + return referenceCounter; +} + + + +inline ParseInfo +QtData::getParseInfo() +{ + if( parseInfo ) + return *parseInfo; + else + return ParseInfo(); +} + + +inline void +QtData::setParseInfo( const ParseInfo &info ) +{ + if( parseInfo ) + *parseInfo = info; + else + parseInfo = new ParseInfo( info ); +} + + + +inline +int +QtData::deleteRef() +{ + int objDeleted = 0; + +#if 0 + if (parseInfo==NULL) + { + // RMInit::logOut << "QtData::deleteRef() - error: null parseinfo, resetting before doing delete." << endl; + parseInfo = new ParseInfo(); + } +#endif + + if( !decRef() ) + { + objDeleted = 1; + delete this; + } + + return objDeleted; +} + + + +inline +unsigned int +QtData::decRef() +{ + if( referenceCounter > 0 ) + referenceCounter--; + else + RMInit::logOut << "Internal Error: QtData::decRef() - decrease of a zero reference counter" << endl; + + return referenceCounter; +} + + + +inline +void +QtData::incRef() +{ + referenceCounter++; +} + + + + + diff --git a/qlparser/qtdelete.cc b/qlparser/qtdelete.cc new file mode 100644 index 0000000..0b09179 --- /dev/null +++ b/qlparser/qtdelete.cc @@ -0,0 +1,268 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtDelete: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtdelete.cc,v 1.14 2003/12/27 20:51:28 rasdev Exp $"; + +#include "qlparser/qtdelete.hh" +#include "qlparser/qtdata.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtmddaccess.hh" +#include "mddmgr/mddobj.hh" +#include "mddmgr/mddcoll.hh" + +#include <iostream> + + + +const QtNode::QtNodeType QtDelete::nodeType = QtNode::QT_DELETE; + + + +QtDelete::QtDelete() + : QtExecute(), input(NULL) +{ +} + + + +QtDelete::~QtDelete() +{ + if( input ) + { + delete input; + input=NULL; + } +} + + + +int +QtDelete::evaluate() +{ + RMDBCLASS( "QtDelete", "evaluate()", "qlparser", __FILE__, __LINE__ ) + + QtNode::QtDataList* nextTupel=NULL; + + // open input stream + try + { + input->open(); + } + catch( ... ) + { + input->close(); + throw; + } + + try + { + while( (nextTupel = input->next()) ) + { + QtData* target = (*nextTupel)[0]; + + // check delete target + if( target->getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtDelete::evaluate() - delete target must be an expression resulting in an r_Marray<>" << std::endl; + + // delete tupel vector received by next() + vector<QtData*>::iterator dataIter; + for( dataIter=nextTupel->begin(); dataIter!=nextTupel->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete nextTupel; + nextTupel=NULL; + + parseInfo.setErrorNo(951); + throw parseInfo; + } + + QtMDD* targetMDD = (QtMDD*) target; + MDDObj* targetObj = targetMDD->getMDDObject(); + + // get leaf of ONC input + QtNodeList* leafList = input->getChilds( QtNode::QT_LEAF_NODES ); + QtMDDAccess* inputLeaf = NULL; + // take the last QtMDDAccess object from the list assuming that it is the right one + for( std::list<QtNode*>::iterator iter=leafList->begin(); iter!=leafList->end(); iter++ ) + if( (*iter)->getNodeType() == QT_MDD_ACCESS ) + inputLeaf = (QtMDDAccess*)*iter; + delete leafList; + leafList=NULL; + + // delete the MDD object + if( inputLeaf ) + { + inputLeaf->getMDDColl()->remove( targetObj ); + RMInit::logOut << "deleted..." << std::flush; + } + + if(targetMDD && targetObj && !targetObj->isPersistent()); + targetMDD->setLifetime( QtData::QT_TRANSIENT ); + + // delete tupel vector received by next() + vector<QtData*>::iterator dataIter; + for( dataIter=nextTupel->begin(); dataIter!=nextTupel->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete nextTupel; + nextTupel=NULL; + } // while + + } + catch( ... ) + { + input->close(); + throw; + } + + input->close(); + + return 0; +} + + + +QtNode::QtNodeList* +QtDelete::getChilds( QtChildType flag ) +{ + QtNodeList* resultList=NULL; + + if( input ) + { + // allocate resultList + if( flag == QT_DIRECT_CHILDS ); + resultList = new QtNodeList(); + + if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) + resultList = input->getChilds( flag ); + + // add the nodes of the current level + if( flag == QT_DIRECT_CHILDS || flag == QT_ALL_NODES ) + resultList->push_back( input ); + } + else + resultList = new QtNodeList(); + + return resultList; +} + + + +void +QtDelete::printTree( int tab, std::ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtDelete Object" << std::endl; + + if( mode != QtNode::QT_DIRECT_CHILDS ) + { + if( input ) + { + s << SPACE_STR(tab).c_str() << "input: " << std::endl; + input->printTree( tab+2, s, mode ); + } + else + s << SPACE_STR(tab).c_str() << "no input" << std::endl; + + s << std::endl; + } +} + + + +void +QtDelete::printAlgebraicExpression( std::ostream& s ) +{ + s << "delete"; + + if( input ) + { + s << "( "; + input->printAlgebraicExpression( s ); + s << " )"; + } + else + s << "(<no input>)"; +} + + + +void +QtDelete::setStreamInput( QtONCStream* newInput ) +{ + input = newInput; + input->setParent( this ); +}; + +QtONCStream::QtONCStream* +QtDelete::getStreamInput() +{ + return input; +} + + +/* +void +QtDelete::preOptimize() +{ + if( input ) + input->preOptimize(); +} +*/ + + +void +QtDelete::checkType() +{ + RMDBCLASS( "QtDelete", "checkType()", "qlparser", __FILE__, __LINE__ ) + + // check operand branches + if( input ) + { + + // get input type + QtTypeTuple inputType = input->checkType(); + + if( inputType.tuple[0].getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtDelete::checkType() - delete target must be an expression resulting in an r_Marray<>" << std::endl; + parseInfo.setErrorNo(951); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtDelete::checkType() - operand branch invalid." << std::endl; + +} + + + + + + + + diff --git a/qlparser/qtdelete.hh b/qlparser/qtdelete.hh new file mode 100644 index 0000000..c16f243 --- /dev/null +++ b/qlparser/qtdelete.hh @@ -0,0 +1,100 @@ +#ifndef __QTDELETE_HH__ +#define __QTDELETE_HH___ + +#include "qlparser/qtexecute.hh" +#include "qlparser/qtoncstream.hh" + +#include <iostream> + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtDelete : public QtExecute +{ + public: + /// default constructor + QtDelete(); + + /// virtual destructor + virtual ~QtDelete(); + + /// method for evaluating the node + virtual int evaluate(); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + //@Man: Read/Write methods: + //@{ + /// + /// + void setStreamInput( QtONCStream* newInput ); + /// + /// returns input + QtONCStream* getStreamInput(); + //@} + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// pre optimization +// virtual void preOptimize(); + /** + Pre-Optimization step is passed to the input streams. + */ + + /// type checking + virtual void checkType(); + + private: + /// one input stream + QtONCStream* input; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtdelete.icc" + +#endif + + + diff --git a/qlparser/qtdelete.icc b/qlparser/qtdelete.icc new file mode 100644 index 0000000..db18e76 --- /dev/null +++ b/qlparser/qtdelete.icc @@ -0,0 +1,35 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtDelete::getNodeType() const +{ + return nodeType; +} + diff --git a/qlparser/qtdomainoperation.cc b/qlparser/qtdomainoperation.cc new file mode 100644 index 0000000..950c49d --- /dev/null +++ b/qlparser/qtdomainoperation.cc @@ -0,0 +1,950 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtTrim: $Id: qtdomainoperation.cc,v 1.35 2002/06/15 20:16:42 coman Exp $"; + +#include <vector> +#include <string> +using namespace std; + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtmdd.hh" +#include "qlparser/qtunaryoperation.hh" +#include "qlparser/qtdomainoperation.hh" +#include "qlparser/qtnode.hh" +#include "qlparser/qtconst.hh" +#include "qlparser/qtmintervaldata.hh" +#include "qlparser/qtintervaldata.hh" +#include "qlparser/qtpointdata.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtcomplexdata.hh" + +#include "mddmgr/mddobj.hh" +#include "tilemgr/tile.hh" + +#include "catalogmgr/ops.hh" +#include "relcatalogif/mddbasetype.hh" +#include "relcatalogif/ulongtype.hh" + +#include <iostream> + + +const QtNode::QtNodeType QtDomainOperation::nodeType = QtNode::QT_DOMAIN_OPERATION; + + +QtDomainOperation::QtDomainOperation( QtOperation* mintOp ) + : mintervalOp( mintOp ), + dynamicMintervalExpression( true ) +{ + RMDBCLASS( "QtDomainOperation", "QtDomainOperation( QtOperation* )", "qlparser", __FILE__, __LINE__ ) + + if( mintervalOp ) mintervalOp->setParent( this ); +} + + + +QtDomainOperation::QtDomainOperation( r_Minterval domainNew, const vector<bool>* newTrimFlags ) + : mintervalOp(0), + dynamicMintervalExpression( false ) +{ + RMDBCLASS( "QtDomainOperation", "QtDomainOperation( r_Minterval, const vector<bool>* )", "qlparser", __FILE__, __LINE__ ) + + // make a copy + vector<bool>* trimFlags = new vector<bool>( *newTrimFlags ); + mintervalOp = new QtConst( new QtMintervalData( domainNew, trimFlags ) ); + mintervalOp->setParent( this ); +} + + + +QtDomainOperation::~QtDomainOperation() +{ + RMDBCLASS( "QtDomainOperation", "~QtDomainOperation()", "qlparser", __FILE__, __LINE__ ) + + if( mintervalOp ) + { + delete mintervalOp; + mintervalOp=NULL; + } +} + + + +QtNode::QtNodeList* +QtDomainOperation::getChilds( QtChildType flag ) +{ + RMDBCLASS( "QtDomainOperation", "getChilds( QtChildType )", "qlparser", __FILE__, __LINE__ ) + + QtNodeList* resultList=NULL; + + resultList = QtUnaryOperation::getChilds( flag ); + + if( mintervalOp ) + { + if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) + { + QtNodeList* subList; + + subList = mintervalOp->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( mintervalOp ); + } + + return resultList; +} + + + +bool +QtDomainOperation::equalMeaning( QtNode* node ) +{ + RMDBCLASS( "QtDomainOperation", "equalMeaning( QtNode* )", "qlparser", __FILE__, __LINE__ ) + + bool result = false; + + if( nodeType == node->getNodeType() ) + { + QtDomainOperation* domainNode; + domainNode = (QtDomainOperation*) node; // by force + + result = input->equalMeaning( domainNode->getInput() ) && + mintervalOp->equalMeaning( domainNode->getMintervalOp() ); + }; + + return ( result ); +} + + +string +QtDomainOperation::getSpelling() +{ + char tempStr[20]; + sprintf(tempStr, "%ud", (unsigned long)getNodeType()); + string result = string(tempStr); + result.append( mintervalOp->getSpelling() ); + result.append( "(" ); + result.append( input->getSpelling() ); + result.append( ")" ); + + return result; +} + + +void +QtDomainOperation::setInput( QtOperation* inputOld, QtOperation* inputNew ) +{ + QtUnaryOperation::setInput( inputOld, inputNew ); + + if( mintervalOp == inputOld ) + { + mintervalOp = inputNew; + + if( inputNew ) + inputNew->setParent( this ); + } +}; + + + +void +QtDomainOperation::optimizeLoad( QtTrimList* trimList ) +{ + RMDBCLASS( "QtDomainOperation", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) + + // test, if there is already a specification for that dimension + bool trimming = false; + + if( mintervalOp ) + { + // pass optimization to minterval tree + mintervalOp->optimizeLoad( new QtNode::QtTrimList ); + + // evaluate minterval tree + QtData* operand = mintervalOp->evaluate(NULL); + + // if spatial operation could be determined, it is static + dynamicMintervalExpression = !operand; + + if( operand ) + { + if( operand->getDataType() == QT_MINTERVAL ) + { + r_Minterval domain = ((QtMintervalData*)operand)->getMintervalData(); + vector<bool>* trimFlags = new vector<bool>( *(((QtMintervalData*)operand)->getTrimFlags()) ); + + if( trimList && trimList->empty() ) + { + // no previous specification for that dimension + trimming = true; + for( int i=0; i!=domain.dimension(); i++ ) + { + // create a new element + QtTrimElement* elem = new QtTrimElement; + + elem->interval = domain[i]; + elem->intervalFlag = (*trimFlags)[i]; + elem->dimension = i; + + // and add it to the list + trimList->push_back( elem ); + + trimming &= (*trimFlags)[i]; + } + } + else + { + // previous specification exists, test for compatibility + } + + if( trimFlags ) + { + delete trimFlags; + trimFlags = NULL; + } + } + + // else if( operand->getDataType() == QtData::QT_POINT ) + + // delete the operand + operand->deleteRef(); + } + } + + // pass optimization process to the input tree + if( input ) input->optimizeLoad( trimList ); + + // Eliminate node QtDomainOperation if only trimming occurs. + if( trimming ) + { + RMDBGMIDDLE(2, RMDebug::module_qlparser, "QtDomainOperation", "all trimming") + + getParent()->setInput( this, input ); + + // Delete the node itself after resetting its input because + // otherwise the input is delete either. + setInput( input, NULL ); + delete this; + } +} + + + +QtData* +QtDomainOperation::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtDomainOperation", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + + switch( input->getDataStreamType().getDataType() ) + { + case QT_MDD: + { + if( mintervalOp->getDataStreamType().getDataType() == QT_POINT || + mintervalOp->getDataStreamType().isInteger() ) + { + // + // Projection to one cell. + // + + QtData* indexData = mintervalOp->evaluate( inputList ); + + if( !indexData ) + return 0; + +#ifdef QT_RUNTIME_TYPE_CHECK + if( indexData->getDataType() != QT_POINT && + !indexData->getDataType().isInteger() ) + { + RMInit::logOut << "Internal error in QtDomainOperation::evaluate() - " + << "runtime type checking failed (QT_POINT, INTEGER)." << endl; + + // delete index data + indexData->deleteRef(); + + return 0; + } +#endif + + // get projection point + r_Point projPoint; + + if( indexData->getDataType() == QT_POINT ) + { + projPoint = ((QtPointData*)indexData)->getPointData(); + } + else + { + projPoint = r_Point(1); + + if( indexData->getDataType() == QT_SHORT || + indexData->getDataType() == QT_OCTET || + indexData->getDataType() == QT_LONG ) + projPoint[0] = ((QtAtomicData*)indexData)->getSignedValue(); + else + projPoint[0] = ((QtAtomicData*)indexData)->getUnsignedValue(); + + } + + // + // In case of dynamic index expressions, load optimization has to + // be performed for the current input expression. + // + /* + if( dynamicMintervalExpression ) + { + QtNode::QtTrimList* trimList = new QtNode::QtTrimList; + + for( int i=0; i!=domain.dimension(); i++ ) + { + // create a new element + QtTrimElement* elem = new QtTrimElement; + + elem->interval = domain[i]; + elem->intervalFlag = (*trimFlags)[i]; + elem->dimension = i; + + // and add it to the list + trimList->push_back( elem ); + } + + // pass optimization process to the input tree + input->optimizeLoad( trimList ); + } + */ + + // get operand data + QtData* operand = input->evaluate( inputList ); + + if( !operand ) + { + // delete indexData + indexData->deleteRef(); + + return 0; + } + +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() != QT_MDD ) + { + RMInit::logOut << "Internal error in QtDomainOperation::evaluate() - runtime type checking failed (QT_MDD)." << endl; + + // delete index and operand data + indexData->deleteRef(); + operand ->deleteRef(); + + return 0; + } +#endif + + QtMDD* qtMDD = (QtMDD*) operand; + MDDObj* currentMDDObj = qtMDD->getMDDObject(); + + if( currentMDDObj ) + { + RMDBGMIDDLE(2, RMDebug::module_qlparser, "QtDomainOperation", " mdd domain: " << currentMDDObj->getCurrentDomain() ) + RMDBGMIDDLE(2, RMDebug::module_qlparser, "QtDomainOperation", " mdd load domain: " << qtMDD->getLoadDomain() ) + + // reset loadDomain to intersection of domain and loadDomain + // if( domain.intersection_with( qtMDD->getLoadDomain() ) != qtMDD->getLoadDomain() ) + // qtMDD->setLoadDomain( domain.intersection_with( qtMDD->getLoadDomain() ) ); + + // get type of cell + const BaseType* cellType = ((MDDBaseType*)(currentMDDObj->getMDDBaseType()))->getBaseType(); + + RMDBGMIDDLE(2, RMDebug::module_qlparser, "QtDomainOperation", " point access: " << projPoint ) + const char* resultCell = NULL; + if (projPoint.dimension() == currentMDDObj->getDimension()) + resultCell = currentMDDObj->pointQuery( projPoint ); + if (resultCell == NULL) + { + RMInit::logOut << "Error: QtDomainOperation::evaluate() - projected cell is not defined." << endl; + parseInfo.setErrorNo(356); + + // delete index and operand data + indexData->deleteRef(); + operand ->deleteRef(); + + throw parseInfo; + } + + // allocate cell buffer + char* resultBuffer = new char[ cellType->getSize() ]; + + // copy cell content + memcpy( (void*)resultBuffer, (void*)resultCell, cellType->getSize() ); + + // 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 indexData + indexData->deleteRef(); + + // delete old operand + operand->deleteRef(); + + } + else // mintervalOp->getDataStreamType() == QT_MINTERVAL + { + // + // Trimming/Projection to an MDD object + // + QtData* indexData = mintervalOp->evaluate( inputList ); + + if( !indexData ) + return 0; + +#ifdef QT_RUNTIME_TYPE_CHECK + if( indexData->getDataType() != QT_MINTERVAL ) + { + RMInit::logOut << "Internal error in QtDomainOperation::evaluate() - " + << "runtime type checking failed (QT_MINTERVAL)." << endl; + + // delete index data + indexData->deleteRef(); + + return 0; + } +#endif + + // get minterval data + vector<bool>* trimFlags = new vector<bool>( *(((QtMintervalData*)indexData)->getTrimFlags()) ); + r_Minterval domain = ((QtMintervalData*)indexData)->getMintervalData(); + + // + // In case of dynamic index expressions, load optimization has to + // be performed for the current input expression. + // + + if( dynamicMintervalExpression ) + { + QtNode::QtTrimList* trimList = new QtNode::QtTrimList; + + for( int i=0; i!=domain.dimension(); i++ ) + { + // create a new element + QtTrimElement* elem = new QtTrimElement; + + elem->interval = domain[i]; + elem->intervalFlag = (*trimFlags)[i]; + elem->dimension = i; + + // and add it to the list + trimList->push_back( elem ); + } + + // pass optimization process to the input tree + input->optimizeLoad( trimList ); + } + + // get operand data + QtData* operand = input->evaluate( inputList ); + + if( !operand ) + { + // delete index data + indexData->deleteRef(); + return 0; + } + +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() != QT_MDD ) + { + RMInit::logOut << "Internal error in QtDomainOperation::evaluate() - runtime type checking failed (QT_MDD)." << endl; + + // delete index and operand data + indexData->deleteRef(); + operand ->deleteRef(); + + return 0; + } +#endif + + QtMDD* qtMDD = (QtMDD*) operand; + MDDObj* currentMDDObj = qtMDD->getMDDObject(); + + if( currentMDDObj ) + { + bool trimming = false; + bool projection = false; + + // reset loadDomain to intersection of domain and loadDomain + if( domain.intersection_with( qtMDD->getLoadDomain() ) != qtMDD->getLoadDomain() ) + qtMDD->setLoadDomain( domain.intersection_with( qtMDD->getLoadDomain() ) ); + + // Test, if trimming has to be done; trimming = 1 if !(load domain is subset of spatial operation) + trimming = ( domain.intersection_with( qtMDD->getLoadDomain() ) == qtMDD->getLoadDomain() ); + + // Test, if a projection has to be made and build the projSet in projection case + set< r_Dimension, less<r_Dimension> > projSet; + + for( int i=0; i<trimFlags->size(); i++ ) + if( !(*trimFlags)[i] ) + { + projection = true; + projSet.insert( i ); + } + + r_Minterval projectedDom( domain.dimension() - projSet.size() ); + + // build the projected domain + for( int i = 0; i < domain.dimension(); i++ ) + // do not include dimensions projected away + if(projSet.find(i) == projSet.end()) + projectedDom << domain[i]; + + if( trimFlags ) + { + delete trimFlags; + trimFlags = NULL; + } + + RMDBGMIDDLE(2, RMDebug::module_qlparser, "QtDomainOperation", " operation domain..: " << domain << " with projection " << projectedDom ) + RMDBGMIDDLE(2, RMDebug::module_qlparser, "QtDomainOperation", " mdd load domain: " << qtMDD->getLoadDomain() ) + RMDBGMIDDLE(2, RMDebug::module_qlparser, "QtDomainOperation", " mdd current domain: " << currentMDDObj->getCurrentDomain() ) + + if( trimming || projection ) + { + // get relevant tiles + vector<Tile* >* relevantTiles = currentMDDObj->intersect( domain ); + + if( relevantTiles->size() > 0 ) + { + // iterator for tiles + vector<Tile*>::iterator tileIt; + + // create a transient MDD object for the query result + MDDObj* resultMDD = new MDDObj( currentMDDObj->getMDDBaseType(), projectedDom ); + + // and iterate over them + for( tileIt = relevantTiles->begin(); tileIt != relevantTiles->end(); tileIt++ ) + { + // domain of the actual tile + r_Minterval tileDom = (*tileIt)->getDomain(); + + // domain of the relevant area of the actual tile + r_Minterval intersectDom = tileDom.create_intersection( domain ); + + RMDBGMIDDLE(2, RMDebug::module_qlparser, "QtDomainOperation", " trimming/projecting tile with domain " << tileDom << " to domain " << intersectDom ) + + // create projected tile + Tile* resTile = new Tile( (*tileIt), intersectDom, &projSet ); + + // insert Tile in result mddObj + resultMDD->insertTile( resTile ); + } + + // create a new QtMDD object as carrier object for the transient MDD object + returnValue = new QtMDD( (MDDObj*)resultMDD ); + + // delete the tile vector + delete relevantTiles; + relevantTiles=NULL; + } + else + { + RMInit::logOut << "Error: QtDomainOperation::evaluate() - the load domain does not intersect with tiles in the current MDD." << endl; + parseInfo.setErrorNo(356); + + // delete index and operand data + indexData->deleteRef(); + operand ->deleteRef(); + + throw parseInfo; + } + + } // trimming || projection + else + // operand is passed through + returnValue = operand; + + } // if( currentMDDObj ) + + // delete index and operand data + if( indexData ) indexData->deleteRef(); + if( operand ) operand ->deleteRef(); + + } + break; + } + case QT_MINTERVAL: + { + QtData* operandData = NULL; + QtData* indexData = NULL; + + operandData = input->evaluate( inputList ); + + if( operandData ) + { +#ifdef QT_RUNTIME_TYPE_CHECK + if( operandData->getDataType() != QT_MINTERVAL ) + { + RMInit::logOut << "Internal error in QtDomainOperation::evaluate() - runtime type checking failed (QT_MINTERVAL)." << endl; + return 0; + } +#endif + // get point + const r_Minterval& minterval = ((QtMintervalData*)operandData)->getMintervalData(); + + // get index + indexData = mintervalOp->evaluate( inputList ); + +#ifdef QT_RUNTIME_TYPE_CHECK + if( indexData->getDataType() != QT_POINT && indexData->getDataType() != QT_CHAR && + indexData->getDataType() != QT_USHORT && indexData->getDataType() != QT_ULONG ) + { + RMInit::logOut << "Internal error in QtDomainOperation::evaluate() - runtime type checking failed." << endl; + return 0; + } +#endif + r_Dimension indexValue = 0; + + switch( indexData->getDataType() ) + { + case QT_POINT: + { + // get first element as index + const r_Point& indexPoint = ((QtPointData*)indexData)->getPointData(); + + if( indexPoint.dimension() != 1 ) + { + RMInit::logOut << "Error: QtDomainOperation::evaluate() - Operand of minterval selection must be of type unsigned integer." << endl; + parseInfo.setErrorNo(397); + + // delete ressources + if( operandData ) operandData->deleteRef(); + if( indexData ) indexData ->deleteRef(); + + throw parseInfo; + } + + indexValue = indexPoint[0]; + } + break; + + case QT_CHAR: + case QT_USHORT: + case QT_ULONG: + indexValue = ((QtAtomicData*)indexData)->getUnsignedValue(); + break; + + case QT_OCTET: + case QT_SHORT: + case QT_LONG: + indexValue = ((QtAtomicData*)indexData)->getSignedValue(); + break; + default: + RMDBGONCE(0, RMDebug::module_qlparser, "r_QtDomainOperation", "evaluate() bad type " << indexData->getDataType()); + break; + } +//indexValue is a unsigned type -> there will never be a indexVAlue < 0 + if( /*indexValue < 0 ||*/ indexValue >= minterval.dimension() ) + { + RMInit::logOut << "Error: QtDomainOperation::evaluate() - index for minterval selection is out of range." << endl; + parseInfo.setErrorNo(398); + + // delete ressources + if( operandData ) operandData->deleteRef(); + if( indexData ) indexData ->deleteRef(); + + throw parseInfo; + } + + returnValue = new QtIntervalData( minterval[indexValue] ); + } + + // delete ressources + if( operandData ) operandData->deleteRef(); + if( indexData ) indexData ->deleteRef(); + break; + } + + case QT_POINT: + { + QtData* operandData = NULL; + QtData* indexData = NULL; + + operandData = input->evaluate( inputList ); + + if( operandData ) + { +#ifdef QT_RUNTIME_TYPE_CHECK + if( operandData->getDataType() != QT_POINT ) + { + RMInit::logOut << "Internal error in QtDomainOperation::evaluate() - runtime type checking failed (QT_POINT)." << endl; + return 0; + } +#endif + // get point + const r_Point& pt = ((QtPointData*)operandData)->getPointData(); + + // get index + indexData = mintervalOp->evaluate( inputList ); + +#ifdef QT_RUNTIME_TYPE_CHECK + if( indexData->getDataType() != QT_POINT && indexData->getDataType() != QT_CHAR && + indexData->getDataType() != QT_USHORT && indexData->getDataType() != QT_ULONG ) + { + RMInit::logOut << "Internal error in QtDomainOperation::evaluate() - runtime type checking failed." << endl; + return 0; + } +#endif + r_Dimension indexValue = 0; + + switch( indexData->getDataType() ) + { + case QT_POINT: + { + // get first element as index + const r_Point& indexPoint = ((QtPointData*)indexData)->getPointData(); + + if( indexPoint.dimension() != 1 ) + { + RMInit::logOut << "Error: QtDomainOperation::evaluate() - Operand of point selection must be of type unsigned integer." << endl; + parseInfo.setErrorNo(399); + + // delete ressources + if( operandData ) operandData->deleteRef(); + if( indexData ) indexData ->deleteRef(); + + throw parseInfo; + } + + indexValue = indexPoint[0]; + } + break; + + case QT_CHAR: + case QT_USHORT: + case QT_ULONG: + indexValue = ((QtAtomicData*)indexData)->getUnsignedValue(); + break; + + case QT_OCTET: + case QT_SHORT: + case QT_LONG: + indexValue = ((QtAtomicData*)indexData)->getSignedValue(); + break; + default: + RMDBGONCE(0, RMDebug::module_qlparser, "r_QtDomainOperation", "evaluate() 2 - bad type " << indexData->getDataType()); + break; + } + + //indexValue is a unsigned type -> there will never be a indexValue < 0 + if( /*indexValue < 0 ||*/ indexValue >= pt.dimension() ) + { + RMInit::logOut << "Error: QtDomainOperation::evaluate() - index for point selection is out of range." << endl; + parseInfo.setErrorNo(411); + + // delete ressources + if( operandData ) operandData->deleteRef(); + if( indexData ) indexData ->deleteRef(); + + throw parseInfo; + } + + returnValue = new QtAtomicData( (r_Long)pt[indexValue], 4 ); + } + + // delete ressources + if( operandData ) operandData->deleteRef(); + if( indexData ) indexData ->deleteRef(); + break; + } + + default: + { + RMInit::logOut << "Error: QtDomainOperation::evaluate() - selection operation is not supported on this data type." << endl; + parseInfo.setErrorNo(396); + throw parseInfo; + } + } + + return returnValue; +} + + +void +QtDomainOperation::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtDomainOperation Object: type " << flush; + dataStreamType.printStatus( s ); + s << endl; + + if( mintervalOp ) + { + s << SPACE_STR(tab).c_str() << "spatial operation: " << endl; + mintervalOp->printTree( tab + 2, s ); + } + else + s << SPACE_STR(tab).c_str() << "no spatial operation" << endl; + + QtUnaryOperation::printTree( tab, s, mode ); +} + + + +void +QtDomainOperation::printAlgebraicExpression( ostream& s ) +{ + s << "geo("; + + if( mintervalOp ) + mintervalOp->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ","; + + if( input ) + input->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtTypeElement& +QtDomainOperation::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtDomainOperation", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // + // operation signatures + // + // MDD<T,D> x Minterval -> MDD<T,D> + // // MDD<T,D> x Interval -> MDD<T,D> + // MDD<T,D> x Point -> T + // MDD<T,D> x Integer -> T + // Minterval x Integer -> Interval + // Minterval x Point(1) -> Interval + // Point x Integer -> Integer + // Point x Point(1) -> Integer + // + + // check operand branches + if( input && mintervalOp ) + { + + // 1. check input expression type + const QtTypeElement& inputType = input->checkType( typeTuple ); + + // 2. check index expression type + const QtTypeElement& indexType = mintervalOp->checkType( typeTuple ); + + // 3. determine result type + if( inputType.getDataType() == QT_MDD ) + { + // check index type + if( indexType.getDataType() != QT_MINTERVAL + // && indexType.getDataType() != QT_INTERVAL + && indexType.getDataType() != QT_POINT + && !indexType.isInteger() + ) + { + RMInit::logOut << "Error: QtDomainOperation::checkType() - spatial domain expressions must be either of type minterval, point, or integer." << endl; + parseInfo.setErrorNo(391); + throw parseInfo; + } + + // MDD + if( indexType.getDataType() == QT_MINTERVAL /* || indexType.getDataType() == QT_INTERVAL */ ) + // pass MDD type + dataStreamType = inputType; + else + // use MDD cell type + dataStreamType.setType( ((MDDBaseType*)inputType.getType())->getBaseType() ); + } + else if( inputType.getDataType() == QT_MINTERVAL ) + { + // check index type + if( !indexType.isInteger() && indexType.getDataType() != QT_POINT ) + { + RMInit::logOut << "Error: QtDomainOperation::checkType() - Operand of minterval selection must be of type integer." << endl; + parseInfo.setErrorNo(397); + throw parseInfo; + } + + dataStreamType.setDataType( QT_INTERVAL ); + } + else if( inputType.getDataType() == QT_POINT ) + { + // check index type + if( !indexType.isInteger() && indexType.getDataType() != QT_POINT ) + { + RMInit::logOut << "Error: QtDomainOperation::checkType() - Operand of point selection must be of type integer." << endl; + parseInfo.setErrorNo(399); + throw parseInfo; + } + + dataStreamType.setDataType( QT_ULONG ); + } + else + { + RMInit::logOut << "Error: QtDomainOperation::checkType() - selection operation is not supported on this data type." << endl; + parseInfo.setErrorNo(396); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtDomainOperation::checkType() - input or index branch invalid." << endl; + + return dataStreamType; +} + + diff --git a/qlparser/qtdomainoperation.hh b/qlparser/qtdomainoperation.hh new file mode 100644 index 0000000..0806ca8 --- /dev/null +++ b/qlparser/qtdomainoperation.hh @@ -0,0 +1,124 @@ +#ifndef _QTDOMAINOPERATION_ +#define _QTDOMAINOPERATION_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtunaryoperation.hh" +#include "qlparser/qtmintervaldata.hh" +#include "raslib/sinterval.hh" +#include "raslib/minterval.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +The class represents a spatial domain operation, e.g. trimming or projections. + +*/ + +class QtDomainOperation : public QtUnaryOperation +{ + public: + + /// constructor getting an minterval expression + QtDomainOperation( QtOperation* mintOp ); + + /// constructor + QtDomainOperation( r_Minterval domainNew, const vector<bool>* newTrimFlags ); + + /// destructor + virtual ~QtDomainOperation(); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// test if the two nodes have an equal meaning in a subtree + virtual bool equalMeaning( QtNode* node ); + + /// creates a unique name for a common subexpression + virtual std::string getSpelling(); + + /// method for query rewrite + virtual void setInput( QtOperation* inputOld, QtOperation* inputNew ); + + /// optimizing load access + void optimizeLoad( QtTrimList* trimList ); + + /// evaluates the node + QtData* evaluate( QtDataList* inputList ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + //@Man: Read/Write methods: + //@{ + /// + + /// + inline virtual void setInput( QtOperation* newInput ); + /// + inline virtual void setMintervalOp(QtOperation* miop); + /// + inline QtOperation* getMintervalOp(); + + /// + //@} + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// pointer to an minterval expression + QtOperation* mintervalOp; + + /// the flag determines if the minterval expression has to be calculated at runtime or not + bool dynamicMintervalExpression; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtdomainoperation.icc" + +#endif + diff --git a/qlparser/qtdomainoperation.icc b/qlparser/qtdomainoperation.icc new file mode 100644 index 0000000..2541c7c --- /dev/null +++ b/qlparser/qtdomainoperation.icc @@ -0,0 +1,66 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline void +QtDomainOperation::setMintervalOp(QtOperation* miop) +{ + mintervalOp = miop; +} + +inline QtOperation* +QtDomainOperation::getMintervalOp() +{ + return mintervalOp; +} + + +inline const QtNode::QtNodeType +QtDomainOperation::getNodeType() const +{ + return nodeType; +} + + +inline void +QtDomainOperation::setInput( QtOperation* newInput ) +{ + QtUnaryOperation::setInput( newInput ); +} + + + + + + + + + + + diff --git a/qlparser/qtexecute.hh b/qlparser/qtexecute.hh new file mode 100644 index 0000000..94352ec --- /dev/null +++ b/qlparser/qtexecute.hh @@ -0,0 +1,66 @@ +#ifndef __QTEXECUTE_HH__ +#define __QTEXECUTE_HH__ + +#include "qlparser/qtnode.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtExecute : public QtNode +{ + public: + /// method for evaluating the execute node node + virtual int evaluate() = 0; + + /// type checking + virtual void checkType() = 0; + /** + The method triggers type checking of the node's subtree. If an error occurs, an exception + is raised. + */ +}; + +#endif + + + + + + + + + + + diff --git a/qlparser/qtinsert.cc b/qlparser/qtinsert.cc new file mode 100644 index 0000000..bfcfbc5 --- /dev/null +++ b/qlparser/qtinsert.cc @@ -0,0 +1,361 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * 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 <iostream> + +#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<Tile*>* 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<Tile*>::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 << "<no source>"; + + 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<T>" << std::endl; + parseInfo.setErrorNo(960); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtInsert::checkType() - operand branch invalid." << std::endl; +} diff --git a/qlparser/qtinsert.hh b/qlparser/qtinsert.hh new file mode 100644 index 0000000..5c928b9 --- /dev/null +++ b/qlparser/qtinsert.hh @@ -0,0 +1,104 @@ +#ifndef __QTINSERT_HH__ +#define __QTINSERT_HH___ + +#include "qlparser/qtexecute.hh" +#include "qlparser/qtoperation.hh" + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif +#include <iostream> + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/** + +*/ + +class QtInsert : public QtExecute +{ + public: + /// constructor getting name of collection and insert expression + QtInsert( const std::string& initCollectionName, QtOperation* initSource ); + + /// virtual destructor + virtual ~QtInsert(); + + /// method for evaluating the node + virtual int evaluate(); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method for query rewrite + inline virtual void setInput( QtOperation* child, QtOperation* input); + + /// returns source + QtOperation* getSource(); + + /// pre optimization +// virtual void preOptimize(); + /** + Pre-Optimization step is passed to the input streams. + */ + + /// type checking + virtual void checkType(); + + private: + /// insert expression + QtOperation* source; + + /// collection name + std::string collectionName; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtinsert.icc" + +#endif + + + diff --git a/qlparser/qtinsert.icc b/qlparser/qtinsert.icc new file mode 100644 index 0000000..eb98e55 --- /dev/null +++ b/qlparser/qtinsert.icc @@ -0,0 +1,49 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtInsert::getNodeType() const +{ + return nodeType; +} + + +inline void +QtInsert::setInput( QtOperation* inputOld, QtOperation* inputNew ) +{ + if( inputOld == source ) + { + source = inputNew; + + if( inputNew ) + inputNew->setParent( this ); + } +}; + + diff --git a/qlparser/qtintervaldata.cc b/qlparser/qtintervaldata.cc new file mode 100644 index 0000000..0d80cc2 --- /dev/null +++ b/qlparser/qtintervaldata.cc @@ -0,0 +1,128 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtIntervalData: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtintervaldata.cc,v 1.10 2005/09/03 20:17:55 rasdev Exp $"; + +using namespace std; + +using namespace std; + +#include "qlparser/qtintervaldata.hh" + +#include <iostream> +#include <cstring> + + +QtIntervalData::QtIntervalData( const r_Sinterval& interval ) + : intervalData(interval), QtData() +{ +} + + + +QtDataType +QtIntervalData::getDataType() const +{ + return QT_INTERVAL; +} + + + +bool +QtIntervalData::equal( const QtData* obj ) const +{ + int returnValue = false; // not equal by initialization + + if( obj->getDataType() == QT_INTERVAL ) + returnValue = (intervalData == ((QtIntervalData*)obj)->getIntervalData()); + + return returnValue; +} + + + +std::string +QtIntervalData::getSpelling() const +{ + std::string result; + + // buffer + int bufferLen = 256; // on the save side for two integers plus colon + char* buffer = new char[ bufferLen ]; + // replaced deprecated ostrstream -- PB 2005-jan-14 + // ostrstream bufferStream( buffer, bufferLen ); + ostringstream bufferStream( buffer ); + + bufferStream << intervalData << std::ends; + + result.append( std::string( buffer ) ); + + delete[] buffer; + buffer = NULL; + + return result; +} + + + +char* QtIntervalData::getTypeStructure() const +{ + return strdup("interval"); +} + + + +void +QtIntervalData::printStatus( std::ostream& stream ) const +{ + stream << "interval, value: " << intervalData << std::flush; + QtData::printStatus( stream ); +} + + + + + + + + + + + + + + + + + + + diff --git a/qlparser/qtintervaldata.hh b/qlparser/qtintervaldata.hh new file mode 100644 index 0000000..af4f421 --- /dev/null +++ b/qlparser/qtintervaldata.hh @@ -0,0 +1,102 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +#ifndef _QTINTERVALDATA_ +#define _QTINTERVALDATA_ + +#include "qlparser/qtdata.hh" + +#include "raslib/sinterval.hh" + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include <iostream> +// removed deprecated ostrstream -- PB 2005-jan-14 +// #include <strstream.h> + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + The class encapsulates an interval. +*/ + +class QtIntervalData : public QtData +{ + public: + /// constructor getting the interval + QtIntervalData( const r_Sinterval& interval ); + + //@Man: Read/Write methods: + //@{ + /// + /// + inline const r_Sinterval& getIntervalData() const; + /// + inline void setIntervalData( const r_Sinterval& interval ); + + /// returns a null-terminated string describing the type structure + virtual char* getTypeStructure() const; + /** + The string pointer has to be free using free() by the caller. + */ + + /// + //@} + + /// returns {\tt QT_INTERVAL} + virtual QtDataType getDataType() const; + + /// compares data content + virtual bool equal( const QtData* obj ) const; + + /// returns content dependent string representation + virtual std::string getSpelling() const; + + /// print status of the object to the specified stream + virtual void printStatus( std::ostream& stream = std::cout ) const; + + private: + /// prevents from using the default constructor + QtIntervalData(){}; + + /// + r_Sinterval intervalData; +}; + +#include "qlparser/qtintervaldata.icc" + +#endif + + + + diff --git a/qlparser/qtintervaldata.icc b/qlparser/qtintervaldata.icc new file mode 100644 index 0000000..46e32a1 --- /dev/null +++ b/qlparser/qtintervaldata.icc @@ -0,0 +1,42 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline const r_Sinterval& +QtIntervalData::getIntervalData() const +{ + return intervalData; +} + + +inline void +QtIntervalData::setIntervalData( const r_Sinterval& interval ) +{ + intervalData = interval; +} diff --git a/qlparser/qtintervalop.cc b/qlparser/qtintervalop.cc new file mode 100644 index 0000000..d5884cc --- /dev/null +++ b/qlparser/qtintervalop.cc @@ -0,0 +1,311 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtIntervalOp: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtintervalop.cc,v 1.13 2003/12/27 20:51:28 rasdev Exp $"; + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtintervalop.hh" +#include "qlparser/qtdata.hh" +#include "qlparser/qtintervaldata.hh" +#include "qlparser/qtstringdata.hh" +#include "qlparser/qtatomicdata.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + + +const QtNode::QtNodeType QtIntervalOp::nodeType = QT_INTERVALOP; + +QtIntervalOp::QtIntervalOp( QtOperation* initInput1, QtOperation* initInput2 ) + : QtBinaryOperation( initInput1, initInput2 ) +{ +} + + + +bool +QtIntervalOp::isCommutative() const +{ + return false; // NOT commutative +} + + + +QtData* +QtIntervalOp::evaluate( QtDataList* inputList ) +{ + QtData* returnValue = NULL; + QtData* operand1 = NULL; + QtData* operand2 = NULL; + + if( getOperands( inputList, operand1, operand2 ) ) + { + r_Sinterval sinterval; + + switch( operand1->getDataType() ) + { + case QT_LONG: + case QT_SHORT: + case QT_OCTET: + try{ + sinterval.set_low( (r_Range)(((QtAtomicData*)operand1)->getSignedValue()) ); + } + catch(...) + { + RMInit::logOut << "Error: QtIntervalOp::evaluate() - interval bound must be of type integer or '*'." << endl; + parseInfo.setErrorNo(389); + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + throw parseInfo; + } + break; + + case QT_ULONG: + case QT_USHORT: + case QT_CHAR: + try{ + sinterval.set_low( (r_Range)((QtAtomicData*)operand1)->getUnsignedValue() ); + } + catch(...) + { + RMInit::logOut << "Error: QtIntervalOp::evaluate() - interval bound must be of type integer or '*'." << endl; + parseInfo.setErrorNo(389); + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + throw parseInfo; + } + break; + + case QT_STRING: + QtStringData *p; + p = dynamic_cast<QtStringData *>(operand1); + + if (p && (p->getStringData() == string("*")) ) + sinterval.set_low('*'); + else + { + RMInit::logOut << "Error: QtIntervalOp::evaluate() - interval bound must be '*'." << endl; + parseInfo.setErrorNo(389); + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + throw parseInfo; + } + break; + + default: + RMInit::logOut << "Error: QtIntervalOp::evaluate() - interval bound must be of type integer or '*'." << endl; + parseInfo.setErrorNo(388); + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + throw parseInfo; + } + + + switch( operand2->getDataType() ) + { + case QT_LONG: + case QT_SHORT: + case QT_OCTET: + try{ + sinterval.set_high( (r_Range)(((QtAtomicData*)operand2)->getSignedValue()) ); + } + catch(...) + { + RMInit::logOut << "Error: QtIntervalOp::evaluate() - interval bound must be of type integer or '*'." << endl; + parseInfo.setErrorNo(389); + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + throw parseInfo; + } + break; + + case QT_ULONG: + case QT_USHORT: + case QT_CHAR: + try{ + sinterval.set_high( (r_Range)((QtAtomicData*)operand2)->getUnsignedValue() ); + } + catch(...) + { + RMInit::logOut << "Error: QtIntervalOp::evaluate() - interval bound must be of type integer or '*'." << endl; + parseInfo.setErrorNo(389); + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + throw parseInfo; + } + break; + + case QT_STRING: + QtStringData *p; + p = dynamic_cast<QtStringData *>(operand2); + + if (p && (p->getStringData() == string("*")) ) + sinterval.set_high('*'); + else + { + RMInit::logOut << "Error: QtIntervalOp::evaluate() - interval bound must be '*'." << endl; + parseInfo.setErrorNo(389); + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + throw parseInfo; + } + break; + + default: + RMInit::logOut << "Error: QtIntervalOp::evaluate() - interval bound must be of type integer or '*'." << endl; + parseInfo.setErrorNo(388); + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + + throw parseInfo; + } + + returnValue = new QtIntervalData( sinterval ); + + // delete the old operands + if( operand1 ) operand1->deleteRef(); + if( operand2 ) operand2->deleteRef(); + } + + return returnValue; +} + + + +void +QtIntervalOp::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtIntervalOp Object " << getNodeType() << endl; + + QtBinaryOperation::printTree( tab, s, mode ); +} + + + +void +QtIntervalOp::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input1 ) + input1->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ":"; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtTypeElement& +QtIntervalOp::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtIintervalOp", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input1 && input2 ) + { + + const QtTypeElement& input1Type = input1->checkType( typeTuple ); + const QtTypeElement& input2Type = input2->checkType( typeTuple ); + + bool opTypesValid = true; + + // check operand1 + opTypesValid &= input1Type.getDataType() == QT_STRING || + input1Type.getDataType() == QT_LONG || + input1Type.getDataType() == QT_SHORT || + input1Type.getDataType() == QT_OCTET || + input1Type.getDataType() == QT_ULONG || + input1Type.getDataType() == QT_USHORT || + input1Type.getDataType() == QT_CHAR; + + // check operand2 + opTypesValid &= input2Type.getDataType() == QT_STRING || + input2Type.getDataType() == QT_LONG || + input2Type.getDataType() == QT_SHORT || + input2Type.getDataType() == QT_OCTET || + input2Type.getDataType() == QT_ULONG || + input2Type.getDataType() == QT_USHORT || + input2Type.getDataType() == QT_CHAR; + + if( !opTypesValid ) + { + RMInit::logOut << "Error: QtIntervalOp::evaluate() - interval bound must be of type integer or '*'." << endl; + parseInfo.setErrorNo(389); + throw parseInfo; + } + + dataStreamType.setDataType( QT_INTERVAL ); + } + else + RMInit::logOut << "Error: QtIntervalOp::checkType() - input branch invalid." << endl; + + return dataStreamType; +} diff --git a/qlparser/qtintervalop.hh b/qlparser/qtintervalop.hh new file mode 100644 index 0000000..de43b78 --- /dev/null +++ b/qlparser/qtintervalop.hh @@ -0,0 +1,84 @@ +#ifndef _QTINTERVALOP_ +#define _QTINTERVALOP_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtbinaryoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the root of an interval expression. + +*/ + +class QtIntervalOp : public QtBinaryOperation +{ + public: + /// constructor getting the two operands + QtIntervalOp( QtOperation* input1, QtOperation* input2 ); + + /// returns FALSE saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + /** + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +#include "qlparser/qtintervalop.icc" + +#endif + diff --git a/qlparser/qtintervalop.icc b/qlparser/qtintervalop.icc new file mode 100644 index 0000000..331e0f0 --- /dev/null +++ b/qlparser/qtintervalop.icc @@ -0,0 +1,34 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtIntervalOp::getNodeType() const +{ + return nodeType; +} diff --git a/qlparser/qtiterator.cc b/qlparser/qtiterator.cc new file mode 100644 index 0000000..ef0615f --- /dev/null +++ b/qlparser/qtiterator.cc @@ -0,0 +1,260 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtIterator: $Id: qtiterator.cc,v 1.20 2001/08/14 10:48:17 rastest Exp $"; + +#include "qlparser/qtiterator.hh" +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +const QtNode::QtNodeType QtIterator::nodeType = QtNode::QT_ITERATOR; + +QtIterator::QtIterator() + : QtONCStream(), + inputs(NULL) +{ +} + + +QtIterator::QtIterator( QtNode* node ) + : QtONCStream( node ), + inputs(NULL) +{ +} + + +QtIterator::~QtIterator() +{ + if( inputs ) + { + // delete the inputs + for( int i=0; i<inputs->size(); i++ ) + { + delete (*inputs)[i]; + (*inputs)[i] = NULL; + } + + // delete the list + delete inputs; + inputs=NULL; + } +} + + +QtNode::QtNodeList* +QtIterator::getChilds( QtChildType flag ) +{ + QtNodeList* resultList=NULL; + list<QtNode*>::iterator it; //default + QtNode::QtNodeList::iterator iter; + + RMDBCLASS( "QtIterator", "getChilds( QtChildType )", "qlparser", __FILE__, __LINE__ ) + + // allocate resultList + resultList = new QtNodeList(); + + if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) + { + for(int i=0; i<inputs->size(); i++ ) + { + QtNodeList* subList=NULL; + subList = (*inputs)[i]->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 ) + for(int i=0; i<inputs->size(); i++ ) + resultList->push_back( (*inputs)[i] ); + + return resultList; +} + + +void +QtIterator::open() +{ + RMDBCLASS( "QtIterator", "open()", "qlparser", __FILE__, __LINE__ ) + + if( inputs ) + { + QtONCStreamList::iterator i; + + for( i=inputs->begin(); i!=inputs->end(); i++ ) + (*i)->open(); + } +} + + +void +QtIterator::close() +{ + RMDBCLASS( "QtIterator", "close()", "qlparser", __FILE__, __LINE__ ) + + if( inputs ) + { + QtONCStreamList::iterator i; + + for( i=inputs->begin(); i!=inputs->end(); i++ ) + (*i)->close(); + } +} + + +void +QtIterator::reset() +{ + if( inputs ) + { + QtONCStreamList::iterator i; + + for( i=inputs->begin(); i!=inputs->end(); i++ ) + (*i)->reset(); + } +} + + +void +QtIterator::printTree( int tab, ostream& s, QtChildType mode ) +{ + if( mode != QtNode::QT_DIRECT_CHILDS ) + { + if( inputs ) + for( int i=0; i<inputs->size(); i++ ) + { + s << SPACE_STR(tab).c_str() << "input " << i+1 << ": " << endl; + (*inputs)[i]->printTree( tab+2, s, mode ); + } + else + s << SPACE_STR(tab).c_str() << "no inputs" << endl; + + s << endl; + } +} + + + +void +QtIterator::printAlgebraicExpression( ostream& s ) +{ + if( inputs ) + { + s << "( "; + + for( int i=0; i<inputs->size(); i++ ) + { + (*inputs)[i]->printAlgebraicExpression( s ); + + if( i < inputs->size()-1 ) + s << ", "; + } + + s << " )"; + } + else + s << "(<no input>)"; +} + + + +void +QtIterator::setStreamInput( QtONCStream* oldInput, QtONCStream* newInput ) +{ + QtONCStreamList::iterator iter; + bool notDone=true; + + for( iter=inputs->begin(); iter!=inputs->end() && notDone; iter++ ) + if( *iter && (*iter) == oldInput ) + { + *iter = newInput; + if( newInput ) + newInput->setParent( this ); + + notDone = false; + } + + if( notDone ) + RMInit::logOut << "QtIterator::setStreamInput() - Error: Old input stream not found." << endl; +} + +QtIterator::QtONCStreamList* +QtIterator::getStreamInputs() +{ + return inputs; +} + +/* +void +QtIterator::preOptimize() +{ + if( inputs ) + { + QtONCStreamList::iterator i; + + for( i=inputs->begin(); i!=inputs->end(); i++ ) + (*i)->preOptimize(); + } +} +*/ + + +void +QtIterator::getInputTypeTuple( QtTypeTuple& typeTuple ) +{ + typeTuple = QtTypeTuple(0); + + if( inputs ) + { + QtONCStreamList::iterator inputIter; + + for( inputIter=inputs->begin(); inputIter!=inputs->end(); inputIter++ ) + { + if( *inputIter ) + typeTuple.concat( (*inputIter)->checkType() ); + else + RMInit::logOut << "Error: QtIterator::getInputTypeTuple() - input branch is invalid." << endl; + } + } + else + RMInit::logOut << "Error: QtIterator::getInputTypeTuple() - inputs branch is invalid." << endl; +} + diff --git a/qlparser/qtiterator.hh b/qlparser/qtiterator.hh new file mode 100644 index 0000000..d2fad41 --- /dev/null +++ b/qlparser/qtiterator.hh @@ -0,0 +1,118 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _QTITERATOR_ +#define _QTITERATOR_ + +#include "qlparser/qtoncstream.hh" + +#include <vector> + +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +It is super class for every class capable of iterating over collections of MDD. +It has a list of inputs of type QtONCStream, so every instance of type +QtONCStream or of a subtype of it can serve as an input stream for a QtIterator +object. The input streams can be combined differently, as cross product of the +inputs in class QtSelectionIterator or as simple tupels in the order they occure +in the input streams in class QtOperationIterator. + +*/ + +class QtIterator : public QtONCStream +{ + public: + /// list of QtONCStream objects + typedef std::vector<QtONCStream*> QtONCStreamList; + + /// default constructor + QtIterator(); + + /// constructor getting a pointer to the parent + QtIterator( QtNode* node ); + + /// destructor + virtual ~QtIterator(); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + //@Man: Operations of the ONC protocol + //@{ + /// + virtual void open(); + /// + virtual void close(); + /// + virtual void reset(); + //@} + + //@Man: Read/Write methods: + //@{ + /// + inline void setStreamInputs( QtONCStreamList* inputs ); + + /// Returns inputs + QtONCStreamList* getStreamInputs(); + /// exchange the stream input {\tt oldInput} with {\tt newInput} + void setStreamInput( QtONCStream* oldInput, QtONCStream* newInput ); + /// + //inline virtual void setParents(); + //@} + + /// pre optimization + //virtual void preOptimize(); + /** + Pre-Optimization step is passed to the input streams. + */ + + /// get input type tuple + void getInputTypeTuple( QtTypeTuple& typeTuple ); + + protected: + /// list of input streams + QtONCStreamList* inputs; + + private: + /// atribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtiterator.icc" + +#endif + diff --git a/qlparser/qtiterator.icc b/qlparser/qtiterator.icc new file mode 100644 index 0000000..ede86ed --- /dev/null +++ b/qlparser/qtiterator.icc @@ -0,0 +1,36 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline void +QtIterator::setStreamInputs( QtONCStreamList* inputsNew ) +{ + inputs = inputsNew; + for( int i=0; i<inputs->size(); i++ ) + (*inputs)[i]->setParent( this ); +}; diff --git a/qlparser/qtjoiniterator.cc b/qlparser/qtjoiniterator.cc new file mode 100644 index 0000000..12277ab --- /dev/null +++ b/qlparser/qtjoiniterator.cc @@ -0,0 +1,338 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtjoiniterator.hh" +#include "qlparser/qtmdd.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +const QtNode::QtNodeType QtJoinIterator::nodeType = QtNode::QT_JOIN_ITERATOR; + + +QtJoinIterator::QtJoinIterator() + : QtIterator(), + actualTupel(NULL), + outputStreamIsEmpty(false) +{ +} + + +QtJoinIterator::QtJoinIterator( QtNode* node ) + : QtIterator( node ), + actualTupel(NULL), + outputStreamIsEmpty(false) +{ +} + + +QtJoinIterator::~QtJoinIterator() +{ + vector<QtData*>::iterator i; //default + + if( actualTupel ) + { + // first delete still existing data carriers + for( QtDataList::iterator iter=actualTupel->begin(); iter!=actualTupel->end(); iter++ ) + if( *iter ) (*iter)->deleteRef(); + + delete actualTupel; + actualTupel=NULL; + } +} + + +void +QtJoinIterator::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtJoinIterator Object: type " << flush; + dataStreamType.printStatus( s ); + s << endl; + + QtIterator::printTree( tab, s, mode ); +} + + + +void +QtJoinIterator::printAlgebraicExpression( ostream& s ) +{ + s << "join"; + + QtIterator::printAlgebraicExpression( s ); +} + + +void +QtJoinIterator::open() +{ + RMDBCLASS( "QtJoinIterator", "open()", "qlparser", __FILE__, __LINE__ ) + + QtIterator::open(); + + outputStreamIsEmpty = false; // initialization + + if( inputs ) + { + // The idea of actualTupel initialization: + // + // tupel[0] tupel[1] tupel[2] ... | + // ----------------------------------------------------- + // 0 0 0 | initial phase + // 0 b1 c1 | open + // a1 b1 c1 | next invocation + // a2 b1 c1 | " + // a1 b2 c1 | " + // : : : | " + + // allocate an empty tupel, right now each input stream provides one data element + actualTupel = new QtDataList( inputs->size() ); + + // set the first element of the tupel to NULL + (*actualTupel)[0] = NULL; + + // fill the tupel, except of the first element, with the first elements of the input streams + //the first element is filled in the ::next() method + for( int tupelPos=1; tupelPos<actualTupel->size(); tupelPos++ ) + { + QtDataList* resultList = (*inputs)[tupelPos]->next(); + + if( resultList ) + { + // take the first data element of the input stream result + (*actualTupel)[tupelPos] = (*resultList)[0]; + + // delete the result vector (only the first data carriers is taken, the others are never deleted) + delete resultList; + resultList = NULL; + } + else + { + // In that case, one of the input streams is empty. Therefore, the output stream of + // the self object is empty either. + (*actualTupel)[tupelPos] = NULL; + outputStreamIsEmpty = true; + } + } + + // Reset the first stream again, because the first tupel element is catched when next() is + // called for the first time. + // (*inputs)[0]->reset(); + } +} + + +QtNode::QtDataList* +QtJoinIterator::next() +{ + RMDBCLASS( "QtJoinIterator", "next()", "qlparser", __FILE__, __LINE__ ) + + + QtDataList* returnValue = NULL; + + if( inputs && actualTupel && !outputStreamIsEmpty ) + { + bool nextTupelAvailable = true; + bool nextTupelValid = false; + int tupelPos; + QtDataList* resultList = NULL; + QtONCStreamList::iterator iter; + + while( !nextTupelValid && nextTupelAvailable && !outputStreamIsEmpty ) + { + // switch to the next tupel which means + + nextTupelAvailable = false; + tupelPos = 0; + iter = inputs->begin(); + + while( !nextTupelAvailable && iter!=inputs->end() ) + { + resultList = (*iter)->next(); + + // Test, if the first input stream is empty, because this is not tested in open() + if( resultList == NULL && tupelPos==0 && (*actualTupel)[0] == 0 ) + outputStreamIsEmpty = true; + + if( resultList == NULL ) + { + (*iter)->reset(); // reset the stream ... + //this causes the first element of the list to be deleted - not the others + resultList = (*iter)->next(); // ... and read the first element again + // this was commented out because it will cause problems when the stream is closed + // if it is commented out it will break join queries + } + else + nextTupelAvailable = true; + + // + // exchange the actual element in the tupel + // + + // delete the data carrier + if( (*actualTupel)[tupelPos] ) + { + (*actualTupel)[tupelPos]->deleteRef(); + (*actualTupel)[tupelPos] = NULL; + } + + if( resultList ) + { + // take the first data element of the input stream result - copy the data carrier pointer + (*actualTupel)[tupelPos] = (*resultList)[0]; + + // delete the result vector (only the first data carrier is taken, the others are never deleted) + delete resultList; + resultList = NULL; + } + + iter++; + tupelPos++; + } + + if( nextTupelAvailable ) + nextTupelValid = true; + } + + if( nextTupelAvailable ) + { + // Copy the actual tupel in order to pass it as the next stream element + // which means increase references to data elements. + returnValue = new QtDataList( actualTupel->size() ); + + for( tupelPos=0; tupelPos < actualTupel->size(); tupelPos++ ) + if( (*actualTupel)[tupelPos] ) + { + (*returnValue)[tupelPos] = (*actualTupel)[tupelPos]; + (*actualTupel)[tupelPos]->incRef(); + } + else + { + // should not come here, because now the next tupel isn't valid + + // delete return value again + for( tupelPos=0; tupelPos < returnValue->size(); tupelPos++ ) + if( (*returnValue)[tupelPos] ) + (*returnValue)[tupelPos]->deleteRef(); + + delete returnValue; + returnValue = NULL; + + RMInit::logOut << "Internal Error in QtJoinIterator::next()" << endl; + } + } + } + + return returnValue; +} + + + +void +QtJoinIterator::close() +{ + RMDBCLASS( "QtJoinIterator", "close()", "qlparser", __FILE__, __LINE__ ) + + if( actualTupel ) + { + // first delete still existing data carriers + for( QtDataList::iterator iter=actualTupel->begin(); iter!=actualTupel->end(); iter++ ) + if( *iter ) (*iter)->deleteRef(); + + delete actualTupel; + actualTupel = NULL; + } + + QtIterator::close(); +} + + +void +QtJoinIterator::reset() +{ + RMDBCLASS( "QtJoinIterator", "reset()", "qlparser", __FILE__, __LINE__ ) + + // reset the input streams + QtIterator::reset(); + + if( inputs ) + { + // first delete still existing data carriers + for( QtDataList::iterator iter=actualTupel->begin(); iter!=actualTupel->end(); iter++ ) + if( *iter ) + { + (*iter)->deleteRef(); + (*iter) = NULL; + } + + // fill the tupel with the first elements of the input streams except of the first element + for( int tupelPos=1; tupelPos<actualTupel->size(); tupelPos++ ) + { + QtDataList* resultList = (*inputs)[tupelPos]->next(); + + if( resultList ) + { + // take the first data element of the input stream result + (*actualTupel)[tupelPos] = (*resultList)[0]; + + // delete the result vector (only the first data carriers is taken, the others are never deleted) + delete resultList; + resultList = NULL; + } + else + (*actualTupel)[tupelPos] = NULL; + + } + + (*actualTupel)[0] = NULL; // fist tupel element is catched when next() is called for the first time + } +} + + + +const QtTypeTuple& +QtJoinIterator::checkType() +{ + RMDBCLASS( "QtJoinIterator", "checkType()", "qlparser", __FILE__, __LINE__ ) + + getInputTypeTuple( dataStreamType ); + + return dataStreamType; +} diff --git a/qlparser/qtjoiniterator.hh b/qlparser/qtjoiniterator.hh new file mode 100644 index 0000000..ca1403f --- /dev/null +++ b/qlparser/qtjoiniterator.hh @@ -0,0 +1,120 @@ +#ifndef _QTJOINITERATOR_ +#define _QTJOINITERATOR_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtiterator.hh" +#include "qlparser/qtoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +An object of this class takes its inputs and computes a tupel for every element +of the cross product. The result is passed to the output stream. +The class represents the FROM part of a query. + +*/ + +class QtJoinIterator : public QtIterator +{ + public: + /// default constructor + QtJoinIterator(); + + /// constructor getting a pointer to the parent + QtJoinIterator( QtNode* node ); + + /// virtual destructor + virtual ~QtJoinIterator(); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + //@Man: Operations of the ONC protocol: + //@{ + /// + void open(); + /// + QtDataList* next(); + /** + According to the producer/consumer protocol of ONC streams, the {/tt next()} + method has to store the last tupel of the crossproduct and update it with a new + element everytime it is invoked. Than it makes a copy of the tupel and pass + it to the caller. + */ + /// + void close(); + /// + void reset(); + /// + //@} + + //@Man: Read/Write methods: + //@{ + /// + //inline virtual void setParents(); + //@} + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking + virtual const QtTypeTuple& checkType(); + + private: + /// inidicates if the output stream is empty or not + bool outputStreamIsEmpty; + /** The output stream is empty if at least one of the input streams is empty. + In that case, the cross product has no elements. This is indicated + by the variable {\tt outputStreamIsEmpty} which is set in the method + {\tt open()}. + */ + + /// pointer to a copy of the last passed tupel + QtDataList* actualTupel; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtjoiniterator.icc" + +#endif + diff --git a/qlparser/qtjoiniterator.icc b/qlparser/qtjoiniterator.icc new file mode 100644 index 0000000..741c048 --- /dev/null +++ b/qlparser/qtjoiniterator.icc @@ -0,0 +1,35 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtJoinIterator::getNodeType() const +{ + return nodeType; +} + diff --git a/qlparser/qtmarrayop.cc b/qlparser/qtmarrayop.cc new file mode 100644 index 0000000..dbcbc84 --- /dev/null +++ b/qlparser/qtmarrayop.cc @@ -0,0 +1,314 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * 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 <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +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 << "<nn>"; + + s << ","; + + if( input2 ) + input2->printAlgebraicExpression( s ); + else + s << "<nn>"; + + 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; +} diff --git a/qlparser/qtmarrayop.hh b/qlparser/qtmarrayop.hh new file mode 100644 index 0000000..98b651c --- /dev/null +++ b/qlparser/qtmarrayop.hh @@ -0,0 +1,90 @@ +#ifndef _QTMARRAYOP_ +#define _QTMARRAYOP_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtbinaryoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the root of an marray expression. + +*/ + +class QtMarrayOp : public QtBinaryOperation +{ + public: + /// constructor getting iterator, minterval expression, and cell expression + QtMarrayOp( const std::string& initIteratorName, QtOperation* mintervalExp, QtOperation* cellExp ); + + /// returns FALSE saying that the operation IS NOT commutative + virtual bool isCommutative() const; + + /// optimizing load access + void optimizeLoad( QtTrimList* trimList ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + /** + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; + + /// attribute storing the iterator name + std::string iteratorName; +}; + + +#include "qlparser/qtmarrayop.icc" + +#endif + diff --git a/qlparser/qtmarrayop.icc b/qlparser/qtmarrayop.icc new file mode 100644 index 0000000..5acc69e --- /dev/null +++ b/qlparser/qtmarrayop.icc @@ -0,0 +1,34 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtMarrayOp::getNodeType() const +{ + return nodeType; +} diff --git a/qlparser/qtmarrayop2.cc b/qlparser/qtmarrayop2.cc new file mode 100644 index 0000000..4393486 --- /dev/null +++ b/qlparser/qtmarrayop2.cc @@ -0,0 +1,369 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtMarrayOp2: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtmarrayop2.cc,v 1.17 2003/12/27 20:51:28 rasdev Exp $"; + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtmarrayop2.hh" +#include "qlparser/qtdata.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtpointdata.hh" +#include "qlparser/qtmintervaldata.hh" +#include "qlparser/qtmintervalop.hh" + +#include "mddmgr/mddobj.hh" +#include "qlparser/querytree.hh" + +#include "catalogmgr/typefactory.hh" +#include "relcatalogif/basetype.hh" +#include "relcatalogif/longtype.hh" + +#include "catalogmgr/algebraops.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +extern QueryTree* parseQueryTree; + +QtMarrayOp2::QtMarrayOp2( mddIntervalListType* & aList, QtOperation* & cellExp ) +: iterators( *aList ), qtOperation( cellExp ) { +} + +QtMarrayOp2::~QtMarrayOp2(){ +} + +bool QtMarrayOp2::concatenateIntervals() { + QtData* data=NULL; + RMDBGENTER( 2, RMDebug::module_qlparser, "QtMarrayOp2", "Validity Check: " ) + + // check for validity + bool eflag=true; + mddIntervalListType::const_iterator ii; + QtNode::QtOperationList::const_iterator j; + QtNode::QtOperationList *ddd=NULL; + QtOperation *op1=NULL; + QtOperation *op2=NULL; + + for (ii = iterators.begin(); ii != iterators.end() ; ii++) { + ddd = ((QtMintervalOp *)(ii->tree))->getInputs(); + for (j = ddd->begin(); j != ddd->end(); j++) { + if((QtNode *)*j) { + if ((((QtNode *)*j)->getNodeType() == QtNode::QT_INTERVALOP)) + { + op1 = ((QtBinaryOperation *)*j)->getInput1(); + if (((QtNode *)op1)->getNodeType() != QtNode::QT_CONST) eflag=false; + op2 = ((QtBinaryOperation *)*j)->getInput2(); + if (((QtNode *)op2)->getNodeType() != QtNode::QT_CONST) eflag=false; + } else + if (((QtNode *)*j)->getNodeType() != QtNode::QT_CONST) + eflag=false; + } + } + } + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", "Validity check completed." ) + if (eflag) { + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", "eflag is true!" << endl ) + // compute total dimension + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", endl << "QtMarrayOp2: Dimensions: " ) + greatDimension=0; + mddIntervalListType::const_iterator i; + for (i = iterators.begin(); i != iterators.end() ; i++) { + // evaluate intervals + data = (i->tree)->evaluate(0); + r_Dimension dimension = ((QtMintervalData*)data)->getMintervalData().dimension(); + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", dimension << " | " ); + greatDimension += dimension; + } + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", " Total " << greatDimension << endl ) + + // concatenate the data of the intervals into one big interval + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", "QtMarray2: Domains: " ) + greatDomain = r_Minterval( greatDimension ); + for (i = iterators.begin(); i != iterators.end() ; i++) { + // evaluate intervals + data = i->tree->evaluate(0); + r_Minterval domain = ((QtMintervalData*)data)->getMintervalData(); + r_Dimension dimension = domain.dimension(); + r_Dimension jj; + for (jj=0; jj != dimension; jj++) { + r_Sinterval part = domain[jj]; + greatDomain << part; + } + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", domain << " | " ) + } + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", " Total: " << greatDomain << endl ) + + // concatenate the identifier names to one big identifier name + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", "QtMarray2: Iterators: " ) + greatIterator = string(""); + string iname(""); + for (i = iterators.begin(); i != iterators.end() ; i++) { + // get iterator name + iname = string(i->variable); + greatIterator = greatIterator + string(" ") + string(i->variable); + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", i->variable << " | " ) + } + RMDBGEXIT( 2, RMDebug::module_qlparser, "QtMarrayOp2", " Total: " << greatIterator << endl ) + } else + RMDBGEXIT( 2, RMDebug::module_qlparser, "QtMarrayOp2", " eflag is false! " << greatIterator << endl ) + return eflag; +} + + + +void QtMarrayOp2::rewriteVars( ) { + if (!oldMarray) { + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", "concatenateIteratorNames: " ) + mddIntervalListType::const_iterator i; + // concatenate the identifier names to one big identifier name + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", "QtMarray2: Iterators: " ) + greatIterator = string(""); + string iname(""); + for (i = iterators.begin(); i != iterators.end() ; i++) { + // get iterator name + iname = string(i->variable); + greatIterator = greatIterator + string(" ") + string(i->variable); + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", i->variable << " | " ) + } + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", " Total: " << greatIterator << endl ) + } + traverse(qtOperation); +} + +void QtMarrayOp2::traverse(QtOperation *&node) { + + if (node != 0) + { + QtOperation* temp = NULL; + + + if (((QtNode *)node)->getNodeType() == QtNode::QT_DOMAIN_OPERATION) + { + // syntax: dinput [ dmiop ] + + // traverse dmiop + QtOperation *dmiop = ((QtDomainOperation *)node)->getMintervalOp(); + temp = (QtOperation*)dmiop; + traverse(temp); + dmiop = temp; + ((QtDomainOperation *)node)->setMintervalOp(dmiop); + + // if dinput == QtVariable then rewrite it + QtOperation *dinput = ((QtDomainOperation *)node)->getInput(); + + // if not a variable, then recurse + if (((QtNode *)dinput)->getNodeType() != QtNode::QT_MDD_VAR) + { + // traverse dinput + temp = (QtOperation *)dinput; + traverse(temp); + dinput = temp; + ((QtDomainOperation *)node)->setInput(dinput); + + // get childs and traverse them + QtNode::QtNodeList* childList = node->getChilds(QtNode::QT_DIRECT_CHILDS); + for( QtNode::QtNodeList::iterator iter = childList->begin(); iter != childList->end(); iter++ ) + { + temp = (QtOperation*)*iter; + traverse(temp); + *iter = temp; + }; + delete childList; + childList=NULL; + }; + } else + { + + if (node->getNodeType() == QtNode::QT_MDD_VAR) { + if (QueryTree::symtab.lookupSymbol(((QtVariable *)node)->getIteratorName())) + { + if (!oldMarray) + { + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtMarrayOp2", endl << "marray2 var identifier:" << ((QtVariable *)node)->getIteratorName() << " replacing with " << greatIterator << endl ) + ((QtVariable *)node)->setIteratorName(greatIterator); + }; + // replace with var[0] + QtDomainOperation *dop = new QtDomainOperation( new QtConst (new QtAtomicData((r_Long)0, sizeof(r_Long))) /*new QtPointOp( lop )*/ ); + dop->setInput( (QtVariable *)node ); + node = dop; + parseQueryTree->addDomainObject( dop ); + }; + } else + { + + // traverse inputs + switch (((QtNode *)node)->getNodeType()) { +/* + // with no input + case QtNode::QT_UNDEFINED_NODE: + case QtNode::QT_MDD_ACCESS: + case QtNode::QT_OPERATION_ITERATOR: + case QtNode::QT_SELECTION_ITERATOR: + case QtNode::QT_JOIN_ITERATOR: + case QtNode::QT_UPDATE: + case QtNode::QT_INSERT: + case QtNode::QT_DELETE: + case QtNode::QT_COMMAND: + case QtNode::QT_PYRAMID: + case QtNode::QT_MDD_VAR: + case QtNode::QT_UDFCALLOP: + case QtNode::QT_CONST: + case QtNode::QT_MDD_STREAM: +*/ + // from Unary + case QtNode::QT_TANH: + case QtNode::QT_TAN: + case QtNode::QT_SQRT: + case QtNode::QT_SINH: + case QtNode::QT_SIN: + case QtNode::QT_NOT: + case QtNode::QT_LOG: + case QtNode::QT_LN: + case QtNode::QT_EXP: + case QtNode::QT_DOT: + case QtNode::QT_COSH: + case QtNode::QT_COS: + case QtNode::QT_ARCTAN: + case QtNode::QT_ARCSIN: + case QtNode::QT_ARCCOS: + case QtNode::QT_ABS: + case QtNode::QT_REALPART: + case QtNode::QT_IMAGINARPART: + case QtNode::QT_CAST: + case QtNode::QT_SDOM: + case QtNode::QT_OID: + case QtNode::QT_LO: + case QtNode::QT_HI: +// case QtNode::QT_DOMAIN_OPERATION: + case QtNode::QT_CONVERSION: + case QtNode::QT_SOME: + case QtNode::QT_MINCELLS: + case QtNode::QT_MAXCELLS: + case QtNode::QT_COUNTCELLS: + case QtNode::QT_AVGCELLS: + case QtNode::QT_ALL: + case QtNode::QT_ADDCELLS: + case QtNode::QT_CSE_ROOT: + { + QtOperation *uinput = ((QtUnaryOperation *)node)->getInput(); + + temp = (QtOperation *)uinput; + traverse(temp); + uinput = temp; + + ((QtUnaryOperation *)node)->setInput(uinput); + }; + break; + + // from Binary + case QtNode::QT_SHIFT: + case QtNode::QT_SCALE: + case QtNode::QT_MARRAYOP: + case QtNode::QT_INTERVALOP: + case QtNode::QT_CONDENSEOP: + case QtNode::QT_XOR: + case QtNode::QT_PLUS: + case QtNode::QT_OR: + case QtNode::QT_NOT_EQUAL: + case QtNode::QT_MULT: + case QtNode::QT_MINUS: + case QtNode::QT_LESS_EQUAL: + case QtNode::QT_LESS: + case QtNode::QT_IS: + case QtNode::QT_EQUAL: + case QtNode::QT_DIV: + case QtNode::QT_AND: + case QtNode::QT_OVERLAY: + case QtNode::QT_BIT: + { + QtOperation *binput1 = ((QtBinaryOperation *)node)->getInput1(); + QtOperation *binput2 = ((QtBinaryOperation *)node)->getInput2(); + + QtOperation* temp1 = 0; + QtOperation* temp2 = 0; + temp1 = (QtOperation *)binput1; + temp2 = (QtOperation *)binput2; + traverse(temp1); + traverse(temp2); + binput1 = temp1; + binput2 = temp2; + + ((QtBinaryOperation *)node)->setInput1(binput1); + ((QtBinaryOperation *)node)->setInput2(binput2); + }; + break; + + // from Nary + case QtNode::QT_POINTOP: + case QtNode::QT_MINTERVALOP: + { + QtNode::QtOperationList *ninput = ((QtNaryOperation *)node)->getInputs(); + + for( QtNode::QtOperationList::iterator iter = ninput->begin(); iter != ninput->end(); iter++ ) + { + temp = (QtOperation *)*iter; + traverse(temp); + *iter = temp; + }; + + ((QtNaryOperation *)node)->setInputs(ninput); + }; + break; + default: { + // do nothing + }; break; + }; + + // get childs and traverse them + QtNode::QtNodeList* childList = node->getChilds(QtNode::QT_DIRECT_CHILDS); + for( QtNode::QtNodeList::iterator iter = childList->begin(); iter != childList->end(); iter++ ) + { + temp = (QtOperation*)*iter; + traverse(temp); + *iter = temp; + }; + delete childList; + childList=NULL; + }; + }; + }; +} + + + + diff --git a/qlparser/qtmarrayop2.hh b/qlparser/qtmarrayop2.hh new file mode 100644 index 0000000..94e67e6 --- /dev/null +++ b/qlparser/qtmarrayop2.hh @@ -0,0 +1,113 @@ +#ifndef _QTMARRAYOP2_ +#define _QTMARRAYOP2_ + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the root of a fake marray expression. + +*/ + +#include "raslib/minterval.hh" + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include <vector> +#include "qlparser/qtoperation.hh" +#include "qlparser/qtdomainoperation.hh" +#include "qlparser/qtvariable.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtpointop.hh" +#include "qlparser/qtconst.hh" + +class QtMarrayOp2 { + public: + /// variables to pass to old marray + r_Dimension greatDimension; + r_Minterval greatDomain; + std::string greatIterator; + + /// pair (Identifier, Interval) + typedef struct { + std::string variable; + QtOperation* tree; + ParseInfo parseInfo; + } mddIntervalType; + + /// list storing pairs (Identifier, Interval) + typedef vector<mddIntervalType> mddIntervalListType; + + /// constructor getting iterator, minterval expression, and cell expression + QtMarrayOp2( mddIntervalListType* & aList, QtOperation* & cellExp ); + + /// destructor + virtual ~QtMarrayOp2(); + + /// optimizing load access + virtual bool concatenateIntervals(); + virtual void rewriteVars(); + inline QtOperation *getInput() const; + /// + inline const ParseInfo& getParseInfo(); + /// + inline void setParseInfo( const ParseInfo &info ); + /// + inline void setOldMarray( bool value ); + + protected: + /// attribute for parser info + ParseInfo parseInfo; + + private: + /// attribute storing the iterators + mddIntervalListType iterators; + + /// attribute storing the cellExp + QtOperation *qtOperation; + + /// tree traversal + virtual void traverse(QtOperation *&node); + + /// replace Iterator name if this is false + bool oldMarray; + +}; + +#include "qlparser/qtmarrayop2.icc" + +#endif + diff --git a/qlparser/qtmarrayop2.icc b/qlparser/qtmarrayop2.icc new file mode 100644 index 0000000..8155712 --- /dev/null +++ b/qlparser/qtmarrayop2.icc @@ -0,0 +1,54 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +inline QtOperation *QtMarrayOp2::getInput() const +{ + return qtOperation; +} + +inline const ParseInfo& +QtMarrayOp2::getParseInfo() +{ + return parseInfo; +} + +inline void +QtMarrayOp2::setParseInfo( const ParseInfo &info ) +{ + parseInfo = info; +} + +inline void +QtMarrayOp2::setOldMarray( bool value ) +{ + oldMarray = value; +}; diff --git a/qlparser/qtmdd.cc b/qlparser/qtmdd.cc new file mode 100644 index 0000000..b3e994f --- /dev/null +++ b/qlparser/qtmdd.cc @@ -0,0 +1,329 @@ +#include "mymalloc/mymalloc.h" +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtMDD: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtmdd.cc,v 1.44 2003/12/27 20:51:28 rasdev Exp $"; + +#include "qlparser/qtmdd.hh" +#include "qlparser/qtscalardata.hh" +#include "qlparser/qtmintervaldata.hh" +#include "qlparser/qtoperation.hh" + +#include "mddmgr/mddobj.hh" +#include "tilemgr/tile.hh" +#include "mddmgr/mddcoll.hh" +#include "catalogmgr/typefactory.hh" + +#include "raslib/rmdebug.hh" + +#include "relcatalogif/mdddimensiontype.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif +#include <iostream> + +extern MDDColl* mddConstants; + +QtMDD::QtMDD( MDDObj* ptr ) + : QtData(), + mddObject( ptr ) +{ + if( ptr && ptr->isPersistent() ) + setLifetime( QtData::QT_PERSISTENT ); + else + setLifetime( QtData::QT_TRANSIENT ); + + if( ptr ) + loadDomain = ptr->getDefinitionDomain(); +} + + +QtMDD::QtMDD( MDDObj* ptr, string name ) + : QtData( name ), + mddObject( ptr ) +{ + if( ptr && ptr->isPersistent() ) + setLifetime( QtData::QT_PERSISTENT ); + else + setLifetime( QtData::QT_TRANSIENT ); + + if( ptr ) + loadDomain = ptr->getCurrentDomain(); +} + + +QtMDD::QtMDD( QtOperation* mintervalOp, list<QtScalarData*>* literalList ) + : QtData(), mddObject(0) +{ + list< QtScalarData* >::iterator elemIter; + QtScalarData* scalarElem=NULL; + + // + // evaluate domain + // + + if( mintervalOp ) + { + + QtData* operand = mintervalOp->evaluate(NULL); + + if( operand->getDataType() != QT_MINTERVAL ) + { + RMInit::logOut << "Error: QtMDD( QtOperation*, list<QtScalarData*>* ) - Can not evaluate domain expression to an minterval." << endl; + ParseInfo errorInfo = getParseInfo(); + errorInfo.setErrorNo(401); + throw errorInfo; + } + + r_Minterval domain = ((QtMintervalData*)operand)->getMintervalData(); + + // delete old operand + if( operand ) operand->deleteRef(); + + // + // determine base type + // + + if( literalList->size()!=0 ) + { + scalarElem = *(literalList->begin()); + const BaseType* baseType = scalarElem->getValueType(); + + // + // allocate memory and fill it with cell values of the list + // + unsigned long cellCount = 0; + unsigned long cellSize = baseType->getSize(); + char* cellBuffer = (char*)mymalloc( domain.cell_count()*cellSize ); + char* bufferOffset = cellBuffer; + + for( elemIter = literalList->begin(); elemIter != literalList->end(); elemIter++ ) + { + scalarElem = *elemIter; + cellCount++; + + // do not write beyond array boundary + if( cellCount <= domain.cell_count() ) + { + if( scalarElem->getValueType() != baseType ) + { + RMDBGONCE(2, RMDebug::module_qlparser, "QtMDD", "Error: QtMDD() - All cell values of an MDD must be of the same type." ) + free( cellBuffer ); + cellBuffer=NULL; + ParseInfo errorInfo = getParseInfo(); + errorInfo.setErrorNo(301); + throw errorInfo; + } + memcpy( (void*)bufferOffset, (void*)(scalarElem->getValueBuffer()), (unsigned int)cellSize ); + bufferOffset += cellSize; + } + } + + // delete literal list - done by caller + // delete literalList; + + if( cellCount != domain.cell_count() ) + { + RMDBGONCE(2, RMDebug::module_qlparser, "QtMDD", "Error: QtMDD() - Number of cells specified does not match the number of cells of the given spatial domain." ) + free( cellBuffer ); + cellBuffer=NULL; + ParseInfo errorInfo = getParseInfo(); + errorInfo.setErrorNo(302); + throw errorInfo; + } + + // + // create transient tile + // + Tile* tile = new Tile( domain, baseType, cellBuffer, 0 ); + + // + // create transiend mddObject and attach created tile + // + MDDDimensionType* mddDimensionType = new MDDDimensionType( "tmp", baseType, domain.dimension() ); + TypeFactory::addTempType( mddDimensionType ); + mddObject = new MDDObj( mddDimensionType, domain ); + mddObject->insertTile( tile ); + loadDomain = domain; + } + else + RMInit::logOut << "Internal Error: QtMDD( domain, literalList ) - list of literal lists is empty" << endl; + } + else + { + RMInit::logOut << "Error: QtMDD( QtOperation*, list<QtScalarData*>* ) - Domain of MDD constructor has to be defined." << endl; + ParseInfo errorInfo = getParseInfo(); + errorInfo.setErrorNo(400); + throw errorInfo; + } + +} + + + +QtMDD::QtMDD( int constantNo ) + : QtData(), + mddObject( NULL ) +{ + RMDBGONCE(2, RMDebug::module_qlparser, "QtMDD", "QtMDD() - constant no " << constantNo ) + + if( mddConstants ) + { + + MDDCollIter* mddIter = mddConstants->createIterator(); + //for( mddIter->reset(); mddIter->notDone(); mddIter->advance() ) + mddIter->reset(); + + // take the MDD object + mddObject = mddIter->getElement(); + + // remove it from the constant list + mddConstants->remove( mddObject ); + + delete mddIter; + mddIter = NULL; + + if( mddObject ) + loadDomain = mddObject->getCurrentDomain(); + } + else + { + RMInit::logOut << "Error: QtMDD() - Unsatisfied MDD constant parameter." << endl; + ParseInfo errorInfo = getParseInfo(); + errorInfo.setErrorNo(373); + throw errorInfo; + } + +} + + + +QtMDD::QtMDD( const QtMDD& obj ) + : QtData( obj ), + mddObject( obj.mddObject ) +{ +} + + +QtMDD::~QtMDD() +{ + //this causes problems when passing more than one trans mddobj + if( mddObject && getLifetime() == QtData::QT_TRANSIENT ) + { + RMDBGONCE( 2, RMDebug::module_qlparser, "QtMDD", "~QtMDD() - transient MDD object " << mddObject << " deleted" ) + delete mddObject; + mddObject = NULL; + } +} + + +BaseType* +QtMDD::getCellType() const +{ + return (BaseType*)mddObject->getCellType(); +} + + + +unsigned long +QtMDD::getCellSize() const +{ + return mddObject->getCellType()->getSize(); +} + + + +QtDataType +QtMDD::getDataType() const +{ + return QT_MDD; +} + + + +bool +QtMDD::equal( const QtData* /*obj*/ ) const +{ + int returnValue = false; // not equal by initialization + + // Later on, MDD constants can be compared. + + return returnValue; +} + + + +string +QtMDD::getSpelling() const +{ + string result; + + // no spelling right now + + return result; +} + + + +char* QtMDD::getTypeStructure() const +{ + if( mddObject ) + return mddObject->getMDDBaseType()->getTypeStructure(); + else + return NULL; +} + + + +void +QtMDD::printStatus( ostream& stream ) const +{ + if( mddObject ) + stream << "MDD object: load domain: " << loadDomain << endl; + else + stream << "<no object>" << endl; + + QtData::printStatus( stream ); + +RMDBGIF(3, RMDebug::module_qlparser, "QtMDD", mddObject->printStatus(0, stream); ) + +RMDBGIF(30, RMDebug::module_qlparser, "QtMDD", \ + vector<Tile*>* vec = mddObject->getTiles(); \ + for( int i = 0; i<vec->size(); i++ ) \ + ((*vec)[i])->printStatus(); \ + delete vec; vec=NULL; ) +} diff --git a/qlparser/qtmdd.hh b/qlparser/qtmdd.hh new file mode 100644 index 0000000..bbbe195 --- /dev/null +++ b/qlparser/qtmdd.hh @@ -0,0 +1,138 @@ +#ifndef _QTMDD_ +#define _QTMDD_ + +#include "qlparser/qtdata.hh" +#include "qlparser/qtscalardata.hh" +#include "catalogmgr/typefactory.hh" +#include "raslib/minterval.hh" + +#include <string> +#include <list> + +// forward declarations +class MDDObj; +class QtOperation; + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class encapsulates a pointer to an object of type {\tt MDDObj}. + Its purpose is to have the {\tt MDDObj} object available as a descendant + of class {\tt QtData}. The class does not care of the memory management + of the {\tt MDDObj} object. + + Note: The attribute lifetime of the superclass QtData ist set implicit + in the constructor functions! +*/ + +class QtMDD : public QtData +{ + public: + // list of lists of \Ref{QtScalarData} objects + // typedef list< list<QtScalarData*>* > QtDimensionList; + + /// constructor getting the pointer to the MDDObj object + QtMDD( MDDObj* ptr ); + + /// constructor getting the pointer to the MDDObj object and an iterator name + QtMDD( MDDObj* ptr, std::string name ); + + /// constructor getting a domain expression and a literal list for initializing a transient constant object + QtMDD( QtOperation* mintervalOp, std::list<QtScalarData*>* literalList ); + /** + The list of literal objects is not deleted. + */ + + /// constructor getting the number of an mdd constant + QtMDD( int constantNo ); + + /// copy constructor + QtMDD( const QtMDD& obj ); + + /// destructor + virtual ~QtMDD(); + + //@Man: Read/Write methods: + //@{ + /// + /// gets the pointer to the MDDObj object + inline MDDObj* getMDDObject() const; + /// sets the pointer to the MDDObj object and it does not care about the old pointer + inline void setMDDObject( MDDObj* ptr ); + /// read method for loadDomain + inline const r_Minterval& getLoadDomain() const; + /// write method for loadDomain + inline void setLoadDomain( r_Minterval& newLoadDomain ); + + /// returns a null-terminated string describing the type structure + virtual char* getTypeStructure() const; + /** + The string pointer has to be free using free() by the caller. + */ + /// + /// + //@} + + /// returns a pointer to the cell type + BaseType* getCellType() const; + + /// returns size of one cell in bytes + unsigned long getCellSize() const; + + /// returns {\tt QT_MDD} + virtual QtDataType getDataType() const; + + /// compares data content + virtual bool equal( const QtData* obj ) const; + + /// returns content dependent string representation + virtual std::string getSpelling() const; + + /// print status of the object to the specified stream + virtual void printStatus( std::ostream& stream = std::cout ) const; + + private: + /// prevents from using the default constructor + QtMDD(){}; + + /// pointer to the MDDObj object + MDDObj* mddObject; + + /// load domain + r_Minterval loadDomain; +}; + +#include "qlparser/qtmdd.icc" + +#endif + diff --git a/qlparser/qtmdd.icc b/qlparser/qtmdd.icc new file mode 100644 index 0000000..8fee948 --- /dev/null +++ b/qlparser/qtmdd.icc @@ -0,0 +1,59 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline MDDObj* +QtMDD::getMDDObject() const +{ + return mddObject; +} + + +inline void +QtMDD::setMDDObject( MDDObj* ptr ) +{ + mddObject = ptr; +} + + + +inline const r_Minterval& +QtMDD::getLoadDomain() const +{ + return loadDomain; +} + + +inline void +QtMDD::setLoadDomain( r_Minterval& newLoadDomain ) +{ + loadDomain = newLoadDomain; +} + + diff --git a/qlparser/qtmddaccess.cc b/qlparser/qtmddaccess.cc new file mode 100644 index 0000000..db009e3 --- /dev/null +++ b/qlparser/qtmddaccess.cc @@ -0,0 +1,250 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtMDDAccess: $Id: qtmddaccess.cc,v 1.30 2002/04/23 16:22:41 purify Exp $"; + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtmddaccess.hh" +#include "qlparser/qtmdd.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +#include "mddmgr/mddcoll.hh" +#include "mddmgr/mddcolliter.hh" + +#include "servercomm/servercomm.hh" + +extern ServerComm::ClientTblElt* currentClientTblElt; + +const QtNode::QtNodeType QtMDDAccess::nodeType = QT_MDD_ACCESS; + +QtMDDAccess::QtMDDAccess( const string& collectionNameNew ) + : QtONCStream(), + collectionName( collectionNameNew ), + mddColl(NULL), + mddIter(NULL) +{ +} + + +QtMDDAccess::QtMDDAccess( const string& collectionNameNew, const string& initName ) + : QtONCStream(), + collectionName( collectionNameNew ), + iteratorName( initName ), + mddColl(NULL), + mddIter(NULL) +{ +} + + +QtMDDAccess::~QtMDDAccess() +{ + //just to be on the safe side + close(); +} + + +void +QtMDDAccess::open() +{ + RMDBCLASS( "QtMDDAccess", "open()", "qlparser", __FILE__, __LINE__ ) + + // delete an existing iterator + if( mddIter ) + { + delete mddIter; + mddIter=NULL; + } + + // create the iterator + mddIter = mddColl->createIterator(); + + //for( mddIter->reset(); mddIter->notDone(); mddIter->advance() ) + // mddIter->getElement()->printStatus(); + + mddIter->reset(); +} + + +QtNode::QtDataList* +QtMDDAccess::next() +{ + RMDBCLASS( "QtMDDAccess", "next()", "qlparser", __FILE__, __LINE__ ) + + QtDataList* returnValue = NULL; + MDDObj* ptr = NULL; + + if( mddColl && mddIter && mddIter->notDone() ) + { + // + // create a list with a pointer to the next element of the mdd collection + // + + // encapsulate the next MDDObj in an QtMDD object + ptr = mddIter->getElement(); + QtMDD* elem = new QtMDD( ptr, iteratorName ); + + + + // create the list + QtNode::QtDataList* dataList = new QtNode::QtDataList(1); // create container to contain one element + + // insert the element into the list + (*dataList)[0] = elem; + + // if mddColl is not persistent delete thist from + // collection to avoid multiple destruction + if(!mddColl->isPersistent()) { + mddColl->remove(ptr); + mddIter->reset(); + } + else { + // increment the iterator + mddIter->advance(); + } + + returnValue = dataList; + } + + return returnValue; +} + + +void +QtMDDAccess::close() +{ + RMDBCLASS( "QtMDDAccess", "close()", "qlparser", __FILE__, __LINE__ ) + + // delete the mdd iterator + if( mddIter ) + { + delete mddIter; + mddIter=NULL; + } + + // This is now done in ServerComm::ClientTblElt::releaseTransferStructures(). + // + // delete the mdd objects and the mdd collection + // if( mddColl ) + // { + // mddColl->releaseAll(); + // delete mddColl; + // } +} + + +void +QtMDDAccess::reset() +{ + if( mddIter ) mddIter->reset(); +} + + +void +QtMDDAccess::printTree( int tab, ostream& s, QtChildType /*mode*/ ) +{ + s << SPACE_STR(tab).c_str() << "QtMDDAccess Object: type " << flush; + dataStreamType.printStatus( s ); + s << endl; + + s << SPACE_STR(tab).c_str() << collectionName.c_str() + << " <- " << iteratorName.c_str() << endl; +} + + + +void +QtMDDAccess::printAlgebraicExpression( ostream& s ) +{ + s << collectionName.c_str() << " as " << iteratorName.c_str() << flush; +} + + + +const QtTypeTuple& +QtMDDAccess::checkType() +{ + RMDBCLASS( "QtMDDAccess", "checkType()", "qlparser", __FILE__, __LINE__ ) + + dataStreamType = QtTypeTuple(0); + + // + // create the collection and add it to the list in the client table entry + // + + try + { + mddColl = MDDColl::getMDDCollection( collectionName.c_str() ); + + if( currentClientTblElt ) + { + if (mddColl->isPersistent()) + { + if( !(currentClientTblElt->persMDDCollections) ) + currentClientTblElt->persMDDCollections = new vector<MDDColl*>(); + + currentClientTblElt->persMDDCollections->push_back( (MDDColl*)mddColl ); + } + else { + currentClientTblElt->transferColl = mddColl; + } + } + else { + RMInit::logOut << "Internal Error in QtMDDAccess::open(): No client context available" << endl; + } + } + catch(...) + { + RMInit::logOut << "Error: QtMDDAccess::open() collection: " << collectionName.c_str() << " is unknown" << endl; + parseInfo.setErrorNo(355); + throw parseInfo; + } + + CollectionType* collType = (CollectionType*) mddColl->getCollectionType(); + + if( !collType ) + RMInit::logOut << "Internal error in QtMDDAccess::checkType() - no collection type available" << endl; + + dataStreamType = QtTypeTuple( 1 ); + + dataStreamType.tuple[0].setType( collType->getMDDType() ); + dataStreamType.tuple[0].setName( iteratorName.c_str() ); + + return dataStreamType; +} diff --git a/qlparser/qtmddaccess.hh b/qlparser/qtmddaccess.hh new file mode 100644 index 0000000..433f805 --- /dev/null +++ b/qlparser/qtmddaccess.hh @@ -0,0 +1,114 @@ +#ifndef _QTMDDACCESS_ +#define _QTMDDACCESS_ + +#include "qlparser/qtoncstream.hh" + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +// forward declarations +class MDDColl; +class MDDCollIter; + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +This class encapsulates a MDDCollection. It gives access to the elements +through the ONC protocol. The list returned by next() consists of just one +element. + +*/ + +class QtMDDAccess : public QtONCStream +{ + public: + /// constructor getting the collection name if no iterator name is specified + QtMDDAccess( const std::string& collectionName ); + + /// constructor getting collection and iterator name + QtMDDAccess( const std::string& collectionName, const std::string& iteratorName ); + + /// destructor + virtual ~QtMDDAccess(); + + //@Man: Operations of the ONC protocol + //@{ + /// + void open(); + /// + QtDataList* next(); + /// + void close(); + /// + void reset(); + //@} + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method for retrieving the current MDD collection + inline MDDColl* getMDDColl(); + + /// type checking + virtual const QtTypeTuple& checkType(); + + private: + /// name of the MDD collection + std::string collectionName; + + /// name of the iterator + std::string iteratorName; + + /// pointer to the MDD collection + MDDColl* mddColl; + + /// pointer to the curent iterator + MDDCollIter* mddIter; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtmddaccess.icc" + +#endif + diff --git a/qlparser/qtmddaccess.icc b/qlparser/qtmddaccess.icc new file mode 100644 index 0000000..37a8e3b --- /dev/null +++ b/qlparser/qtmddaccess.icc @@ -0,0 +1,42 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtMDDAccess::getNodeType() const +{ + return nodeType; +} + + + +inline MDDColl* +QtMDDAccess:: getMDDColl() +{ + return mddColl; +} diff --git a/qlparser/qtmintervaldata.cc b/qlparser/qtmintervaldata.cc new file mode 100644 index 0000000..da5343d --- /dev/null +++ b/qlparser/qtmintervaldata.cc @@ -0,0 +1,188 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtMintervalData: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtmintervaldata.cc,v 1.10 2005/09/03 20:17:55 rasdev Exp $"; + +using namespace std; + +using namespace std; + +#include "qlparser/qtmintervaldata.hh" + +#include <iostream> +#include <cstring> + +QtMintervalData::QtMintervalData( const r_Minterval& minterval, vector<bool>* initTrimFlags ) + : mintervalData(minterval), QtData(), trimFlags( initTrimFlags ) +{ + if( !trimFlags ) + { + trimFlags = new vector<bool>( minterval.dimension() ); + + for( int i=0; i<trimFlags->size(); i++ ) + (*trimFlags)[i] = true; + } +} + + + +QtMintervalData::~QtMintervalData() +{ + if( trimFlags ) {delete trimFlags; trimFlags=NULL; } +} + + + +QtDataType +QtMintervalData::getDataType() const +{ + return QT_MINTERVAL; +} + + + +bool +QtMintervalData::equal( const QtData* obj ) const +{ + bool returnValue = false; // not equal by initialization + + if( obj->getDataType() == QT_MINTERVAL ) + { + QtMintervalData* mint = (QtMintervalData*)obj; + + // 1. check domains + returnValue = (mintervalData == mint->getMintervalData()); + + // 2. check projection flags !!! + if( returnValue && trimFlags && mint->getTrimFlags() ) + for( int i=0; i<mintervalData.dimension(); i++ ) + if (!((*trimFlags)[i] == (*(mint->getTrimFlags()))[i])) + { + returnValue = false; + break; + } + } + + return returnValue; +} + + + +std::string +QtMintervalData::getSpelling() const +{ + std::string result; + + // buffer + int bufferLen = mintervalData.dimension() * 50; // on the save side for two integers per dimension plus colon and brackets + char* buffer = new char[ bufferLen ]; + // replaced deprecated ostrstream -- PB 2005-jan-14 + // ostrstream bufferStream( buffer, bufferLen ); + ostringstream bufferStream( buffer ); + + if( trimFlags ) + { + bufferStream << "[" << std::flush; + for( int i=0; i<mintervalData.dimension(); i++ ) + { + if( i > 0 ) bufferStream << "'" << std::flush; + + if( (*trimFlags)[i] ) + bufferStream << mintervalData[i] << std::flush; + else + bufferStream << mintervalData[i].low() << std::flush; + } + bufferStream << "]" << std::ends; + } + else + bufferStream << mintervalData << std::ends; + + result.append( std::string( buffer ) ); + + delete[] buffer; + buffer = NULL; + + return result; +} + + + +char* QtMintervalData::getTypeStructure() const +{ + return strdup("minterval"); +} + + + +void +QtMintervalData::printStatus( std::ostream& stream ) const +{ + stream << "minterval, value: " << std::flush; + + if( trimFlags ) + { + stream << "[" << std::flush; + for( int i=0; i<mintervalData.dimension(); i++ ) + { + if( i > 0 ) stream << "," << std::flush; + + if( (*trimFlags)[i] ) + stream << mintervalData[i] << std::flush; + else + stream << mintervalData[i].low() << std::flush; + } + stream << "]" << std::flush; + } + else + stream << mintervalData << std::flush; + + QtData::printStatus( stream ); +} + + + + + + + + + + + + + + + + + + + diff --git a/qlparser/qtmintervaldata.hh b/qlparser/qtmintervaldata.hh new file mode 100644 index 0000000..9fcd705 --- /dev/null +++ b/qlparser/qtmintervaldata.hh @@ -0,0 +1,108 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +#ifndef _QTMINTERVALDATA_ +#define _QTMINTERVALDATA_ + +#include "qlparser/qtdata.hh" + +#include "raslib/minterval.hh" +#include "raslib/point.hh" + +#include <string> +#include <vector> +#include <iostream> + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + The class encapsulates an minterval. +*/ + +class QtMintervalData : public QtData +{ + public: + /// constructor getting the minterval + QtMintervalData( const r_Minterval& minterval, vector<bool>* initTrimFlags = NULL ); + + /// virtual destructor + virtual ~QtMintervalData(); + + //@Man: Read/Write methods: + //@{ + /// + + /// + inline const r_Minterval& getMintervalData() const; + /// + inline void setMintervalData( const r_Minterval& interval ); + // + // inline void setMintervalData( const r_Point& point ); + /// + inline const vector<bool>* getTrimFlags() const; + + /// returns a null-terminated string describing the type structure + virtual char* getTypeStructure() const; + /** + The string pointer has to be free using free() by the caller. + */ + + /// + //@} + + /// returns {\tt QT_INTERVAL} + virtual QtDataType getDataType() const; + + /// compares data content + virtual bool equal( const QtData* obj ) const; + + /// returns content dependent string representation + virtual std::string getSpelling() const; + + /// print status of the object to the specified stream + virtual void printStatus( std::ostream& stream = std::cout ) const; + + private: + /// prevents from using the default constructor + QtMintervalData(){}; + + /// attribute storing the minterval + r_Minterval mintervalData; + + /// bitvector indicating real projections + vector<bool>* trimFlags; +}; + +#include "qlparser/qtmintervaldata.icc" + +#endif + + + + diff --git a/qlparser/qtmintervaldata.icc b/qlparser/qtmintervaldata.icc new file mode 100644 index 0000000..b5a003f --- /dev/null +++ b/qlparser/qtmintervaldata.icc @@ -0,0 +1,59 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline const r_Minterval& +QtMintervalData::getMintervalData() const +{ + return mintervalData; +} + + +inline void +QtMintervalData::setMintervalData( const r_Minterval& minterval ) +{ + mintervalData = minterval; + + // reset trim flags + + if( trimFlags ) delete trimFlags; + trimFlags = new vector<bool>( minterval.dimension() ); + + for( int i=0; i<trimFlags->size(); i++ ) + (*trimFlags)[i] = true; +} + + +inline const vector<bool>* +QtMintervalData::getTrimFlags() const +{ + return trimFlags; +} + + diff --git a/qlparser/qtmintervalop.cc b/qlparser/qtmintervalop.cc new file mode 100644 index 0000000..e112f18 --- /dev/null +++ b/qlparser/qtmintervalop.cc @@ -0,0 +1,222 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtMintervalOp: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtmintervalop.cc,v 1.12 2003/12/27 20:51:28 rasdev Exp $"; + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtmintervalop.hh" +#include "qlparser/qtdata.hh" +#include "qlparser/qtmintervaldata.hh" +#include "qlparser/qtintervaldata.hh" +#include "qlparser/qtatomicdata.hh" + +#include "catalogmgr/ops.hh" +#include "relcatalogif/type.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + + +const QtNode::QtNodeType QtMintervalOp::nodeType = QT_MINTERVALOP; + +QtMintervalOp::QtMintervalOp( QtOperationList* opList ) + : QtNaryOperation( opList ) +{ +} + + + +QtData* +QtMintervalOp::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtMintervalOp", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtDataList* operandList = NULL; + + if( getOperands( inputList, operandList ) ) + { + vector<QtData*>::iterator dataIter; + bool goOn=true; + + // check for point operand + if( operandList->size() == 1 && ((*operandList)[0])->getDataType() == QT_MINTERVAL ) + { + // pass point as minterval projection + returnValue = (*operandList)[0]; + + delete operandList; + operandList=NULL; + } + else + { + // first check operand types + for( dataIter=operandList->begin(); dataIter!=operandList->end() && goOn; dataIter++ ) + if (!( (*dataIter)->getDataType() == QT_SHORT || (*dataIter)->getDataType() == QT_USHORT || + (*dataIter)->getDataType() == QT_LONG || (*dataIter)->getDataType() == QT_ULONG || + (*dataIter)->getDataType() == QT_OCTET || (*dataIter)->getDataType() == QT_CHAR || + (*dataIter)->getDataType() == QT_INTERVAL)) + { + goOn=false; + break; + } + + if( !goOn ) + { + RMInit::logOut << "Error: QtMintervalOp::evaluate() - expressions for minterval dimensions must be either of type integer or interval." << endl; + parseInfo.setErrorNo(390); + + // delete the old operands + if( operandList ) + { + for( dataIter=operandList->begin(); dataIter!=operandList->end(); dataIter++ ) + if( (*dataIter) ) (*dataIter)->deleteRef(); + + delete operandList; + operandList=NULL; + } + + throw parseInfo; + } + + // + // create a QtMintervalData object and fill it + // + r_Minterval domainData( operandList->size() ); + vector<bool>* trimFlags = new vector<bool>( operandList->size() ); + int pos; + + for( dataIter=operandList->begin(), pos=0; dataIter!=operandList->end(); dataIter++,pos++ ) + { + if( (*dataIter)->getDataType() == QT_INTERVAL ) + { + domainData << ((QtIntervalData*)(*dataIter))->getIntervalData(); + (*trimFlags)[pos] = true; + }else + { + if( (*dataIter)->getDataType() == QT_SHORT || + (*dataIter)->getDataType() == QT_LONG || + (*dataIter)->getDataType() == QT_OCTET ) + domainData << ((QtAtomicData*)(*dataIter))->getSignedValue(); + else + domainData << ((QtAtomicData*)(*dataIter))->getUnsignedValue(); + + (*trimFlags)[pos] = false; + } + } + + returnValue = new QtMintervalData( domainData, trimFlags ); + + // delete the old operands + if( operandList ) + { + for( dataIter=operandList->begin(); dataIter!=operandList->end(); dataIter++ ) + if( (*dataIter) ) (*dataIter)->deleteRef(); + + delete operandList; + operandList=NULL; + } + } + } + + return returnValue; +} + + + +void +QtMintervalOp::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtMintervalOp Object " << getNodeType() << endl; + + QtNaryOperation::printTree( tab, s, mode ); +} + + + +void +QtMintervalOp::printAlgebraicExpression( ostream& s ) +{ + s << "["; + + QtNaryOperation::printAlgebraicExpression( s ); + + s << "]"; +} + + + +const QtTypeElement& +QtMintervalOp::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtMintervalOp", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + QtOperationList::iterator iter; + bool opTypesValid = true; + + for( iter=operationList->begin(); iter!=operationList->end() && opTypesValid; iter++ ) + { + const QtTypeElement& type = (*iter)->checkType( typeTuple ); + + // valid types: interval, integers + if (!( type.getDataType() == QT_INTERVAL || + type.getDataType() == QT_SHORT || + type.getDataType() == QT_LONG || + type.getDataType() == QT_OCTET || + type.getDataType() == QT_USHORT || + type.getDataType() == QT_ULONG || + type.getDataType() == QT_CHAR)) + { + opTypesValid=false; + break; + } + } + + if( !opTypesValid ) + { + RMInit::logOut << "Error: QtMintervalOp::checkType() - expressions for minterval dimensions must be either of type integer or interval." << endl; + parseInfo.setErrorNo(390); + throw parseInfo; + } + + dataStreamType.setDataType( QT_MINTERVAL ); + + return dataStreamType; +} diff --git a/qlparser/qtmintervalop.hh b/qlparser/qtmintervalop.hh new file mode 100644 index 0000000..9d3316e --- /dev/null +++ b/qlparser/qtmintervalop.hh @@ -0,0 +1,81 @@ +#ifndef _QTMINTERVALOP_ +#define _QTMINTERVALOP_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtnaryoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the root of an minterval expression. + +*/ + +class QtMintervalOp : public QtNaryOperation +{ + public: + /// constructor getting the two operands + QtMintervalOp( QtOperationList* opList ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + /** + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +#include "qlparser/qtmintervalop.icc" + +#endif + diff --git a/qlparser/qtmintervalop.icc b/qlparser/qtmintervalop.icc new file mode 100644 index 0000000..3cadc8f --- /dev/null +++ b/qlparser/qtmintervalop.icc @@ -0,0 +1,34 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtMintervalOp::getNodeType() const +{ + return nodeType; +} diff --git a/qlparser/qtnaryoperation.cc b/qlparser/qtnaryoperation.cc new file mode 100644 index 0000000..4923004 --- /dev/null +++ b/qlparser/qtnaryoperation.cc @@ -0,0 +1,414 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtNaryOperation: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtnaryoperation.cc,v 1.13 2003/12/27 20:51:28 rasdev Exp $"; + +#include "qlparser/qtnaryoperation.hh" +#include "qlparser/qtconst.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +const QtNode::QtNodeType QtNaryOperation::nodeType = QtNode::QT_NARY_OPERATION; + +QtNaryOperation::QtNaryOperation() + : QtOperation(), + operationList(NULL) +{ +} + + +QtNaryOperation::QtNaryOperation( QtNode* node ) + : QtOperation( node ), + operationList(NULL) +{ +} + + +QtNaryOperation::QtNaryOperation( QtOperationList* opList ) + : QtOperation(), + operationList( opList ) +{ + if( operationList ) + { + QtOperationList::iterator iter; + + for( iter=operationList->begin(); iter!=operationList->end(); iter++) + (*iter)->setParent( this ); + } +} + + +QtNaryOperation::~QtNaryOperation() +{ + if( operationList ) + { + QtOperationList::iterator iter; + + for( iter=operationList->begin(); iter!=operationList->end(); iter++) + { + delete *iter; + *iter=NULL; + } + + delete operationList; + operationList=NULL; + } +} + + +void +QtNaryOperation::simplify() +{ + RMDBCLASS( "QtNaryOperation", "simplify()", "qlparser", __FILE__, __LINE__ ) + + // In order to work bottom up, first inspect the descendants + QtNode::simplify(); + + // Test, if all operands are available. + bool success = (operationList != NULL); + QtOperationList::iterator iter; + + if( success ) + for( iter=operationList->begin(); iter!=operationList->end(); iter++) + if ((*iter) == NULL) + { + success = false; + break; + } + + if( success ) + { + // Test, if all operands are of const type. + for( iter=operationList->begin(); iter!=operationList->end(); iter++) + if ((*iter)->getNodeType() != QT_CONST) + { + success = false; + break; + } + + if( success ) + { + // evaluate the self node with no input list + QtData* newConst = this->evaluate( NULL ); + + if( newConst ) + { + // create a new constant node and fill it with newConst + QtConst* newNode = new QtConst( newConst ); + + // set its data stream type + newNode->checkType( NULL ); + + // link it to the parent + getParent()->setInput( this, newNode ); + + // delete the self node and its descendants + delete this; + } + } + } +} + + + +bool +QtNaryOperation::equalMeaning( QtNode* node ) +{ + RMDBCLASS( "QtNaryOperation", "equalMeaning( QtNode* )", "qlparser", __FILE__, __LINE__ ) + + bool result; + result=false; + + if( getNodeType() == node->getNodeType() ) + { + QtNaryOperation* naryNode; + naryNode = (QtNaryOperation* ) node; // by force + + // get 2nd operation list + QtOperationList* operationList2 = naryNode->getInputs(); + + // create iterators + QtOperationList::iterator iter, iter2; + + result = true; + for( iter =operationList->begin(), iter2 =operationList2->begin(); + iter!=operationList->end() && iter2!=operationList2->end(); + iter++, iter2++ ) + if (!( (*iter)->equalMeaning( *iter2 ) )) + { + result=false; + break; + } + + // input lists must have the same length + result &= ( iter==operationList->end() && iter2==operationList2->end() ); + }; + + return result; +} + + + +QtNode::QtNodeList* +QtNaryOperation::getChilds( QtChildType flag ) +{ + RMDBCLASS( "QtNaryOperation", "getChilds( QtChildType )", "qlparser", __FILE__, __LINE__ ) + + QtNodeList* resultList=NULL; + QtNodeList* subList=NULL; + + QtOperationList::iterator iter; + + resultList = new QtNodeList(); + + for( iter=operationList->begin(); iter!=operationList->end(); iter++ ) + { + if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) + { + subList = (*iter)->getChilds( flag ); + resultList->splice(resultList->begin(), *subList); + delete subList; + subList=NULL; + }; + + if( flag == QT_DIRECT_CHILDS || flag == QT_ALL_NODES ) + resultList->push_back( *iter ); + }; + + return resultList; +} + + +bool +QtNaryOperation::getOperands( QtDataList* inputList, QtDataList* &operandList ) +{ + RMDBCLASS( "QtNaryOperation", "getOperands( QtDataList*, QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + bool success = (operationList != 0); + + // Test, if all operands are available. + QtOperationList::iterator iter; + + if( success ) + for( iter=operationList->begin(); iter!=operationList->end(); iter++) + if ((*iter) == NULL) + { + success=false; + break; + } + + if( success ) + { + // get the operands + operandList = new QtDataList( operationList->size() ); + + int pos=0; + + for( iter=operationList->begin(); iter!=operationList->end(); iter++) + { + if( *iter ) + (*operandList)[pos] = (*iter)->evaluate( inputList ); + + pos++; + } + + // Test, if all operands are valid. + for( pos=0; pos<operandList->size(); pos++ ) + if ((*operandList)[pos] == NULL) + { + success=false; + break; + } + + if( !success ) + { + // if not all operands are valid, delete the old ones + QtDataList::iterator dataIter; + + for( dataIter=operandList->begin(); dataIter!=operandList->end(); dataIter++ ) + if( (*dataIter) ) (*dataIter)->deleteRef(); + + delete operandList; + operandList = NULL; + + RMDBGONCE(2, RMDebug::module_qlparser, "QtNaryOperation", "Information: QtNaryOperation::getOperands() - at least one operand is not provided." ) + } + } + else + RMInit::logOut << endl << "Error: QtNaryOperation::getOperands() - at least one operand branch is invalid." << endl; + + return success; +} + + + +string +QtNaryOperation::getSpelling() +{ + QtOperationList::iterator iter; + + char tempStr[20]; + sprintf(tempStr, "%ud", (unsigned long)getNodeType()); + string result = string(tempStr); + + result.append( "(" ); + + for( iter=operationList->begin(); iter!=operationList->end(); iter++ ) + { + if( iter!=operationList->begin() ) result.append( "," ); + + result.append( (*iter)->getSpelling() ); + } + + result.append( ")" ); + + RMDBGONCE(2, RMDebug::module_qlparser, "QtNaryOperation", "Result:" << result.c_str() ) + + return result; +} + + + +void +QtNaryOperation::setInput( QtOperation* inputOld, QtOperation* inputNew ) +{ + QtOperationList::iterator iter; + + for( iter=operationList->begin(); iter!=operationList->end(); iter++) + { + if( *iter == inputOld ) + { + (*iter) = inputNew; + + if( inputNew ) + inputNew->setParent( this ); + }; + }; +}; + + + +QtNode::QtAreaType +QtNaryOperation::getAreaType() +{ + return QT_AREA_SCALAR; +} + +/* +void +QtNaryOperation::checkIdempotency() +{ + // default method: do nothing +} +*/ + +void +QtNaryOperation::optimizeLoad( QtTrimList* trimList ) +{ + RMDBCLASS( "QtNaryOperation", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) + + // delete trimList + // release( trimList->begin(), trimList->end() ); + for( QtNode::QtTrimList::iterator iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + + if( operationList ) + { + QtOperationList::iterator iter; + + for( iter=operationList->begin(); iter!=operationList->end(); iter++) + if( *iter ) + (*iter)->optimizeLoad( new QtNode::QtTrimList ); + } +} + + +void +QtNaryOperation::printTree( int tab, ostream& s, QtChildType mode ) +{ + if( mode != QT_DIRECT_CHILDS ) + { + if( operationList ) + { + QtOperationList::iterator iter; + int no; + + for( no=1, iter=operationList->begin(); iter!=operationList->end(); iter++, no++ ) + if( *iter ) + { + s << SPACE_STR(tab).c_str() << "input" << no << ": " << endl; + (*iter)->printTree( tab+2, s, mode ); + } + } + } +} + + + +void +QtNaryOperation::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( operationList ) + { + QtOperationList::iterator iter; + + for( iter=operationList->begin(); iter!=operationList->end(); iter++ ) + { + if( iter!=operationList->begin() ) s << ","; + + if( *iter ) + (*iter)->printAlgebraicExpression( s ); + else + s << "<nn>"; + } + } + else + s << "<nn>"; + + s << ")"; +} + + + diff --git a/qlparser/qtnaryoperation.hh b/qlparser/qtnaryoperation.hh new file mode 100644 index 0000000..142ea40 --- /dev/null +++ b/qlparser/qtnaryoperation.hh @@ -0,0 +1,137 @@ +#ifndef _QTNARYOPERATION_ +#define _QTNARYOPERATION_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include <stdio.h> + +#include "qlparser/qtoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************** + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class serves as superclass for all operation classes taking n + (more than two) arguments. + +*/ + +class QtNaryOperation : public QtOperation +{ + public: + /// default constructor + QtNaryOperation(); + + /// constructor getting the node to the parent + QtNaryOperation( QtNode* node ); + + /// constructor getting a list of operands + QtNaryOperation( QtOperationList* opList ); + + /// virtual destructor + virtual ~QtNaryOperation(); + + /// simplifies the tree + virtual void simplify(); + + /// test if the two nodes have an equal meaning in the query tree + virtual bool equalMeaning( QtNode* node ); + /** + The meaning of a binary operation is equal, iff all operands have + the same meaning. + */ + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// creates a unique name for a subexpression + virtual std::string getSpelling(); + + /// method for query rewrite + virtual void setInput( QtOperation*, QtOperation* inputNew ); + + /// tests if the edge to the parent node is of type mdd or atomic + virtual QtAreaType getAreaType(); + + /// method for checking idempotency rules +// virtual void checkIdempotency(); + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + /** + The method deletes the given {\tt trimList} and passes the {\tt optimizeLoad} + message with empty triming lists to its input trees. + */ + + /// debugging method + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + //@Man: read/write methods for the operands + //@{ + /// + /// + inline void setInputs( QtOperationList* opList ); + /// + inline QtNode::QtOperationList* getInputs(); + /// + //@} + + protected: + /// method for testing and evaluating the input branches + bool getOperands( QtDataList* inputList, QtDataList* &operandList ); + /** + The method checks if the input branches are valid. Then it passes the evaluate message to its two + operands with the {\tt inputList} as argument. The returned results are provided through the arguments + {\tt operand1} and {\tt operand2} called by reference. The method returns {\tt true} if the operands are + valid, otherwise {\tt false}. + */ + + /// operation trees + QtOperationList* operationList; + + private: + /// atribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtnaryoperation.icc" + +#endif + + diff --git a/qlparser/qtnaryoperation.icc b/qlparser/qtnaryoperation.icc new file mode 100644 index 0000000..18f104c --- /dev/null +++ b/qlparser/qtnaryoperation.icc @@ -0,0 +1,50 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline void +QtNaryOperation::setInputs( QtOperationList* opList ) +{ + operationList = opList; + + if( operationList ) + { + QtOperationList::iterator iter; + + for( iter=operationList->begin(); iter!=operationList->end(); iter++ ) + if( *iter ) + (*iter)->setParent( this ); + } +}; + + +inline QtNode::QtOperationList* +QtNaryOperation::getInputs() +{ + return operationList; +}; diff --git a/qlparser/qtnode.cc b/qlparser/qtnode.cc new file mode 100644 index 0000000..77313db --- /dev/null +++ b/qlparser/qtnode.cc @@ -0,0 +1,645 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * 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 <iostream> +#include <algorithm> + + +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<QtNodes; i++) + if ( QtInheritance[i][1] == node ) return QtInheritance[i][0]; + throw r_Error(QTNODETYPEPARENTDOESNOTEXIST); +} + + +bool +operator<(const QtNode::QtNodePair a, const QtNode::QtNodePair b){ + return (a.base < b.base); +} + +void +QtNode::num_node (const QtNodePair *arr, const enum QtNodeType x) { + int i; + static int ID = 0 ; + enum QtNodeType child; + minim[x] = ID++; + for (i = child_range[x]; i < child_range[x+1]; i++) + num_node(arr, arr[i].deriv); + maxim[x] = ID++; +} + +void +QtNode::set_child_range(const QtNodePair *arr) { + int i; + child_range[QtNodes] = QtNodes-1; + for (i=QtNodes-3; 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 << "<unknown type>" << 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<QtTypeElement>::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<QtTypeElement>::const_iterator iter = tuple.begin(); + iter != tuple.end(); + iter++ ) + { + if( iter != tuple.begin() ) + s << ", " << std::flush; + + (*iter).printStatus( s ); + } + + s << ">" << std::flush; +} + + + + diff --git a/qlparser/qtnode.hh b/qlparser/qtnode.hh new file mode 100644 index 0000000..53a038e --- /dev/null +++ b/qlparser/qtnode.hh @@ -0,0 +1,503 @@ +#ifndef _QTNODE_ +#define _QTNODE_ + +#ifndef CPPSTDLIB +#include <vector.h> // STL<ToolKit> +#include <list.h> // STL<ToolKit> +#include <ospace/string.h> // STL<ToolKit> +#else +#include <vector> +#include <list> +#include <string> +#endif + +#include "raslib/rmdebug.hh" +#include "raslib/sinterval.hh" +#include "qlparser/parseinfo.hh" +#include "qlparser/qtdata.hh" + +// define used in lots of qlparser files to indent output +#ifdef CPPSTDLIB +#define SPACE_STR(numSpace) std::string(numSpace,' ') +#else +#define SPACE_STR(numSpace) std::string(' ',numSpace) +#endif + +class QtOperation; // forward declarations of subclasses of QtNode +class Type; +class QtTypeElement; + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/** + + The class QtNode is the common super class of all node + classes of the query tree. It provides a reference to its + parent node in the tree. The parent of root is null. + +*/ + + +class QtNode +{ + public: + /// list of QtData pointers + typedef std::vector<QtData*> QtDataList; + + /// struct containing dimension and triming information + struct QtTrimElement + { + r_Dimension dimension; + r_Sinterval interval; + bool intervalFlag; + }; + + /// list of QtTrimData structures + typedef std::vector<QtTrimElement*> QtTrimList; + + /// list of QtNode pointers + typedef std::list<QtNode*> QtNodeList; + + enum QtNodeType + { + QT_UNDEFINED_NODE, + QT_MDD_ACCESS, + QT_OPERATION_ITERATOR, + QT_SELECTION_ITERATOR, + QT_JOIN_ITERATOR, + QT_UPDATE, + QT_INSERT, + QT_DELETE, + QT_COMMAND, + QT_PLUS, + QT_MINUS, + QT_MULT, + QT_DIV, + QT_OR, + QT_AND, + QT_XOR, + QT_IS, + QT_EQUAL, + QT_NOT_EQUAL, + QT_LESS, + QT_LESS_EQUAL, + QT_NOT, + QT_SQRT, +// added by CStancuMara + QT_EXECUTE, + QT_ONC_STREAM, + QT_ITERATOR, + QT_OPERATION, + QT_BINARY_OPERATION, + QT_BINARY_INDUCE, + QT_GROUP_ITERATOR, + QT_IDENT, + QT_NARY_OPERATION, + QT_UNARY_OPERATION, + QT_CONDENSE, + QT_UNARY_INDUCE, + +//************** + QT_ABS, QT_EXP, QT_LOG, QT_LN, QT_SIN, QT_COS, + QT_TAN, QT_SINH, QT_COSH, QT_TANH, QT_ARCSIN, + QT_ARCCOS, QT_ARCTAN, + QT_REALPART, + QT_IMAGINARPART, + QT_CAST, +//************** + + QT_CSE_ROOT, + QT_DOMAIN_OPERATION, + QT_ALL, + QT_SOME, + QT_COUNTCELLS, + QT_ADDCELLS, + QT_AVGCELLS, + QT_MINCELLS, + QT_MAXCELLS, + QT_MDD_VAR, + QT_MDD_STREAM, + QT_CONST, + QT_DOT, + QT_CONVERSION, + QT_OID, + QT_INTERVALOP, + QT_MINTERVALOP, + QT_POINTOP, + QT_LO, + QT_HI, + QT_SDOM, + QT_SHIFT, + QT_EXTEND, + //QT_MINTERVAL_SELECT, + QT_MARRAYOP, + QT_CONDENSEOP, + QT_SCALE, + QT_OVERLAY, + QT_BIT, + QT_PYRAMID, + QT_LAST_NODE_TYPE + }; + + + + enum QtAreaType + { + QT_AREA_MDD, + QT_AREA_SCALAR + }; + + enum QtChildType + { + QT_DIRECT_CHILDS, + QT_LEAF_NODES, + QT_ALL_NODES + }; + + /// list of QtOperation pointers + typedef std::vector<QtOperation*> QtOperationList; + + /// default constructor + QtNode(); + + /// constructor getting a pointer to the parent + QtNode( QtNode* node ); + + /// destructor + virtual ~QtNode(); + + /// returns weather class b is a subtype of class a + bool subtype( enum QtNodeType a, enum QtNodeType b ); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + /** + The method allows different retrieval of the subtree nodes. Dependent on the content of {\tt flag} + one of the following semantics is used: + {\tt DIRECT_CHILDS} - A list of all direct child nodes of the current node is returned. + {\tt LEAF_NODES } - A list of all leaf nodes of the subtree with the current node as root is returned. + {\tt ALL_NODES } - A list of all nodes of the subtree with the current node as root is returned. + The nodes in the result list have a special order. Every node comes before its parent node in + the result list. + */ + + /// return childs of a certain class + QtNodeList* getChild( const QtNodeType node, QtChildType flag = QT_DIRECT_CHILDS ); + /** + The method allows to specify the class of childs to be considered according to method {\tt getChilds}. + By default, just direct childs are considered + */ + + /// test if the two nodes have an equal meaning in a subtree + virtual bool equalMeaning( QtNode* node ); + + /** + The method checks, if the two nodes have an equal meaning in a subtree. + {\tt equalMeaning()} depends on the type of the node and the information in the node. + For unary and binary operators the method {\tt equalMeaning()} is invoked on the input nodes. + */ + + /// creates a unique name for a common subexpression + virtual std::string getSpelling(); + + /** + The method creates a unique name for common subexpressions by concatenating operators + and variables in the subtree of the common subexpression. + */ + + /// test if the edge to the parent node is of type mdd or atomic + virtual QtAreaType getAreaType(); + /** + The method tests if the edge to the parent node belongs to a multidimensional or + atomic area. + */ + + /// simplifies the tree + virtual void simplify(); + /** + The method evaluates constant expressions. + */ + + /// optimizes the tree +// virtual void rewriteOps(); + /** + The method applies some algebraic rules: + + \begin{verbatim} + some( x or y ) -> some( x ) or some( y ) + all ( x and y ) -> all ( x ) and all ( y ) + all() or some() -> some() or all() + some() and all() -> all() and some() + \end{verbatim} + + Further, a left deep tree is produced (for +,*):: + + \begin{verbatim} + (T1 o T2) + (T3 o T4) -> ((T1 o T2) o T3) o T4 + \end{verbatim} + + The method has to be supplied top-down in the query tree. + */ + + /// optimizes the tree +// virtual void sortAssociativeOps(); + /** + Operators of commutative binary operations are ordered in a + unique sequence. + */ + + /// check idempetency rules +// virtual void checkIdempotency(); + /** + The method applies idempotency rules on binary operations. + The method is supplied bottom-up in the query tree. + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES )=0; + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout )=0; + + //@Man: Read/Write methods + //@{ + /// + + /// + inline virtual void setInput( QtOperation* inputOld, QtOperation* inputNew); + /// + inline QtNode* getParent() const; + /// + inline void setParent( QtNode* node ); + /// + inline const ParseInfo& getParseInfo(); + /// + inline void setParseInfo( const ParseInfo &info ); + + /// + //@} + + /// methods for identification of nodes + inline virtual const QtNodeType getNodeType() const; + /** + The method allows you to differ between the different node types. + */ + + /// method for pre optimizations (basically load optimization) + //virtual void preOptimize(){}; + /** + {\em Load Optimization} + The method is invoked through the whole query tree. The information of + every triming and projection node is collected and stored in a {\tt QtTrimList} + structure which is passed down. While collecting the information consistency + of the data is checked. At the leafs, which are load operations, the structure + is converted to a minterval object and stored in the leaf node. + The list is dynamically created in the node which is on top of an operation subtree + and deleted where the information is stored or dropped. + + Defined empty to do nothing in case it is not defined for a subclass. + */ + + /// returns the QtNodeType parent of the argument (do not use for the root) + enum QtNodeType getQtNodeTypeParent(enum QtNodeType); + + /// number of QtNodeTypes + static const int QtNodes; + + /// the root of the inheritance tree + static const QtNodeType QtRoot; + + /// the inheritance relations list + static const QtNodeType QtInheritance[][2]; + + + protected: + /// attribute for parser info + ParseInfo parseInfo; + + private: + /// pointer to its parent + QtNode* parent; + + /// attribute for identification of nodes + static const QtNodeType nodeType; + + /// (base_class, derived_class) pair + struct QtNodePair { + enum QtNodeType base, deriv; + }; + + + ///operator overload for QtNodePair struct + friend bool operator<( const QtNodePair a, const QtNodePair b); + + /// starting point of elements having node as base class + static int child_range[]; + + /// sets up the child_range[] array + void set_child_range(const QtNodePair *arr); + + /// minim and maxim labels to determine subtypes + static int minim[], maxim[]; + + /// keeps track if SetMinMax was already called + static bool MinMaxDone; + + /// sets minim and maxim values for each QtNodeType + void SetMinMax(); + + /// sets min max values once child_range is set up, for subtree with x as root + void num_node (const QtNodePair *arr, enum QtNodeType x); + +}; + + + + +//@ManMemo: Module: {\bf qlparser} + +/** + + The class encapsulates type information. It additionally + can hold a name in order to be identifyable in a list. + + The type is specified by {\tt dataType} and {\tt type}. + This is necessary because not all types are supported by + subclasses of \Ref{Type}, e.g. not all types are persistent ones. + + In case of QT_MDD and QT_COMPLEX, further type information + can be optained from {\tt type}. + +*/ + +class QtTypeElement +{ + public: + /// + QtTypeElement(); + + /// + QtTypeElement( const QtDataType initDataType, const char* initName = NULL ); + + /// + QtTypeElement( const Type* initType, const char* initName = NULL ); + + /// + QtTypeElement( const QtTypeElement& typeElement ); + + /// + ~QtTypeElement(); + + /// assignment: cleanup + copy + const QtTypeElement& operator= ( const QtTypeElement& ); + + //@Man: Read/Write methods + //@{ + /// + /// + void setDataType( const QtDataType newDataType ); + /// + void setType( const Type* newType ); + /// + inline void setName( const char* newName ); + /// + inline const QtDataType getDataType() const; + /// + inline const Type* getType() const; + /// + inline const char* getName() const; + /// + inline bool isBaseType() const; + /// + inline bool isInteger() const; + /// + //@} + /// + + /// print type + void printStatus( std::ostream& s = std::cout ) const; + + private: + /// + QtDataType dataType; + + /// + const Type* type; + + /// + char* name; +}; + + + +//@ManMemo: Module: {\bf qlparser} + +/** + + The class encapsulates a tuple of \Ref{QtTypeElement} + objects. + +*/ + +class QtTypeTuple +{ + public: + /// + QtTypeTuple( unsigned int length = 0 ); + + /// concatenate type tuple + void concat( const QtTypeTuple& typeTuple ); + + /// concatenate type element + void concat( const QtTypeElement& typeElement ); + + /// + std::vector<QtTypeElement> tuple; + + /// print type + void printStatus( std::ostream& s = std::cout ) const; +}; + +#include "qlparser/qtnode.icc" + +#endif + + + + + + + + + + diff --git a/qlparser/qtnode.icc b/qlparser/qtnode.icc new file mode 100644 index 0000000..0bdddeb --- /dev/null +++ b/qlparser/qtnode.icc @@ -0,0 +1,130 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +#include <cstdlib> +#include <cstring> + +inline QtNode* +QtNode::getParent() const +{ + return parent; +}; + + +inline void +QtNode::setParent( QtNode* node ) +{ + parent = node; +}; + + +inline const QtNode::QtNodeType +QtNode::getNodeType() const +{ + return nodeType; +} + + + +inline void +QtNode::setInput( QtOperation* , QtOperation* ) +{ + RMInit::logOut << "Error: Method setInput(...) is undefined for node type " << getNodeType() << " in the query tree." << endl; +} + + +inline const ParseInfo& +QtNode::getParseInfo() +{ + return parseInfo; +} + + +inline void +QtNode::setParseInfo( const ParseInfo &info ) +{ + parseInfo = info; +} + + + +inline void +QtTypeElement::setName( const char* newName ) +{ + if( name ) free( name ); + name = strdup( newName ); +} + + + + +inline const QtDataType +QtTypeElement::getDataType() const +{ + return dataType; +} + + + +inline const Type* +QtTypeElement::getType() const +{ + return type; +} + + +inline const char* +QtTypeElement::getName() const +{ + return name; +} + + +inline bool +QtTypeElement::isBaseType() const +{ + return dataType == QT_BOOL || dataType == QT_COMPLEX || + dataType == QT_CHAR || dataType == QT_OCTET || + dataType == QT_USHORT || dataType == QT_SHORT || + dataType == QT_ULONG || dataType == QT_LONG || + dataType == QT_FLOAT || dataType == QT_DOUBLE || + dataType == QT_COMPLEXTYPE1 || dataType == QT_COMPLEXTYPE2; +} + + + +inline bool +QtTypeElement::isInteger() const +{ + return dataType == QT_CHAR || dataType == QT_OCTET || + dataType == QT_USHORT || dataType == QT_SHORT || + dataType == QT_ULONG || dataType == QT_LONG; +} + + diff --git a/qlparser/qtoid.cc b/qlparser/qtoid.cc new file mode 100644 index 0000000..6b6d01b --- /dev/null +++ b/qlparser/qtoid.cc @@ -0,0 +1,179 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtOId: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtoid.cc,v 1.13 2003/12/27 20:51:28 rasdev Exp $"; + +#include "qlparser/qtoid.hh" +#include "qlparser/qtvariable.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtmdd.hh" + +#include "mddmgr/mddobj.hh" + +#include "raslib/oid.hh" + +const QtNode::QtNodeType QtOId::nodeType = QtNode::QT_OID; + + +QtOId::QtOId( QtVariable* newInput ) + : QtUnaryOperation( newInput ) +{ + RMDBCLASS( "QtOId", "QtOId( QtVariable* )", "qlparser", __FILE__, __LINE__ ) +} + + + +QtData* +QtOId::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtOId", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtData* operand = NULL; + + operand = input->evaluate( inputList ); + + if( operand ) + { +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() == QT_MDD ) + { + RMInit::logOut << "Internal error in QtOId::evaluate() - " + << "runtime type checking failed (MDD)." << std::endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + return 0; + } +#endif + + QtMDD* qtMDD = (QtMDD*) operand; + MDDObj* mddObj = qtMDD->getMDDObject(); + + if( mddObj->isPersistent() ) + { + MDDObj* persMDD = (MDDObj*) mddObj; + + // get local oid and pass it as double + OId localOId; + if( !persMDD->getOId( &localOId ) ) + { + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtOid", " oid = " << (double)localOId ) + + returnValue = new QtAtomicData( (double)localOId, (unsigned short)8 ); + } + else + { + RMInit::logOut << "Error: QtOId::evaluate() - could not get oid." << std::endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + parseInfo.setErrorNo(384); + throw parseInfo; + } + } + else + { + RMInit::logOut << "Error: QtOId::evaluate() - operand is not a persistent MDD." << std::endl; + + // delete old operand + if( operand ) operand->deleteRef(); + parseInfo.setErrorNo(383); + throw parseInfo; + } + + // delete old operand + if( operand ) operand->deleteRef(); + } + else + RMInit::logOut << "Error: QtOId::evaluate() - operand is not provided." << std::endl; + + return returnValue; +} + + + +void +QtOId::printTree( int tab, std::ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtOId Object: " << std::endl; + + QtUnaryOperation::printTree( tab, s, mode ); +} + + + +void +QtOId::printAlgebraicExpression( std::ostream& s ) +{ + s << "oid(" << std::flush; + + if( input ) + input->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtTypeElement& +QtOId::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtOId", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input ) + { + + // get input type + const QtTypeElement& inputType = input->checkType( typeTuple ); + + if( inputType.getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtOId::checkType() - operand is not of type MDD." << std::endl; + parseInfo.setErrorNo(383); + throw parseInfo; + } + + dataStreamType.setDataType( QT_DOUBLE ); + } + else + RMInit::logOut << "Error: QtOId::checkType() - operand branch invalid." << std::endl; + + return dataStreamType; +} diff --git a/qlparser/qtoid.hh b/qlparser/qtoid.hh new file mode 100644 index 0000000..03dbbdb --- /dev/null +++ b/qlparser/qtoid.hh @@ -0,0 +1,78 @@ +#ifndef _QTOID_HH__ +#define _QTOID_HH___ + +#include "qlparser/qtunaryoperation.hh" + + +// forward declarations +class QtVariable; + + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents an oid node. + +*/ + +class QtOId : public QtUnaryOperation +{ + public: + /// constructor getting operand + QtOId( QtVariable* newInput ); + + /// evaluates the node + QtData* evaluate( QtDataList* inputList ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtoid.icc" + +#endif + diff --git a/qlparser/qtoid.icc b/qlparser/qtoid.icc new file mode 100644 index 0000000..8efdc80 --- /dev/null +++ b/qlparser/qtoid.icc @@ -0,0 +1,35 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline const QtNode::QtNodeType +QtOId::getNodeType() const +{ + return nodeType; +} diff --git a/qlparser/qtoncstream.cc b/qlparser/qtoncstream.cc new file mode 100644 index 0000000..53e72c2 --- /dev/null +++ b/qlparser/qtoncstream.cc @@ -0,0 +1,49 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtONCStream: $Id: qtoncstream.cc,v 1.10 1997/09/04 14:34:46 ritsch Exp $"; + +#include "qlparser/qtoncstream.hh" + +const QtNode::QtNodeType QtONCStream::nodeType = QtNode::QT_ONC_STREAM; + +QtONCStream::QtONCStream() + : QtNode() +{ +} + + +QtONCStream::QtONCStream( QtNode* node ) + : QtNode( node ) +{ +} + diff --git a/qlparser/qtoncstream.hh b/qlparser/qtoncstream.hh new file mode 100644 index 0000000..d267d7a --- /dev/null +++ b/qlparser/qtoncstream.hh @@ -0,0 +1,102 @@ +#ifndef _QTONCSTREAM_ +#define _QTONCSTREAM_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtnode.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************ + * + * + * COMMENTS: + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +This class is super class for every class supporting the ONC protocol +which means that, first, a stream has to be opened with open(), +then the elements are received through invoking next(), +and at the end, the stream is closed with the close() method. The +next() method returns a tupel of QtData or any subclass of QtData. + +*/ + +class QtONCStream : public QtNode +{ + public: + /// default constructor + QtONCStream(); + + /// constructor getting a pointer to the parent + QtONCStream( QtNode* node ); + + //@Man: Operations of the ONC protocol + //@{ + /// + virtual void open()=0; + /// + virtual QtDataList* next()=0; + /// + virtual void close()=0; + /// + virtual void reset()=0; + //@} + + /// type checking of the subtree + virtual const QtTypeTuple& checkType() = 0; + /** + The method triggers type checking of the node's subtree. If an error occurs, an exception + is raised. + */ + + //@Man: Read/Write methods + //@{ + /// + /// + inline void setDataStreamType( const QtTypeTuple& type ); + /// + inline const QtTypeTuple& getDataStreamType() const; + /// + //@} + + protected: + /// result type of the node + QtTypeTuple dataStreamType; + + private: + /// atribute for identification of nodes + static const QtNodeType nodeType; +}; + +#endif + diff --git a/qlparser/qtoncstream.icc b/qlparser/qtoncstream.icc new file mode 100644 index 0000000..e1d59df --- /dev/null +++ b/qlparser/qtoncstream.icc @@ -0,0 +1,42 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline void +QtONCStream::setDataStreamType( const QtTypeTuple &type ) +{ + dataStreamType = type; +} + + + +inline const QtTypeTuple& +QtONCStream::getDataStreamType() const +{ + return dataStreamType; +} diff --git a/qlparser/qtoperation.cc b/qlparser/qtoperation.cc new file mode 100644 index 0000000..23bf378 --- /dev/null +++ b/qlparser/qtoperation.cc @@ -0,0 +1,126 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtOperation: $Id: qtoperation.cc,v 1.17 2002/06/05 18:18:17 coman Exp $"; + + +#include "qlparser/qtoperation.hh" + +#include <iostream> + +const QtNode::QtNodeType QtOperation::nodeType = QtNode::QT_OPERATION; + +QtOperation::QtOperation() + : QtNode() +{ +} + + +QtOperation::QtOperation( QtNode* node ) + : QtNode( node ) +{ +} + + +QtOperation* +QtOperation::getUniqueOrder( const QtNode::QtNodeType ) +{ + // default method; + + return this; +} + + +QtData* +QtOperation::evaluate( QtDataList* /*inputList*/ ) +{ + RMInit::logOut << "Error: Method evaluate(...) is undefined for a node in the query tree." << std::endl; + return NULL; +} + + +void +QtOperation::optimizeLoad( QtTrimList* trimList ) +{ + if( trimList ) + { + std::vector<QtNode::QtTrimElement*>::iterator iter; + for( iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + } + + RMInit::logOut << "Error: Method optimizeLoad(...) is undefined for a QtOperation node in the query tree." << std::endl; +} + + + +const QtTypeElement& +QtOperation::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtOperation", "checkType( QtTypeElement, QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + return dataStreamType; +} + + +void +QtOperation::printTree( int tab, std::ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtOperation Object: type " << std::flush; + dataStreamType.printStatus( s ); + s << std::endl; + + if( mode != QtNode::QT_DIRECT_CHILDS ) + { + s << SPACE_STR(tab).c_str() << "no operation" << std::endl; + } + +} + + + +void +QtOperation::printAlgebraicExpression( std::ostream& s ) +{ + s << "op<"; + + s << "no ops"; + + s << ">"; +} diff --git a/qlparser/qtoperation.hh b/qlparser/qtoperation.hh new file mode 100644 index 0000000..eab3d7e --- /dev/null +++ b/qlparser/qtoperation.hh @@ -0,0 +1,120 @@ +#ifndef _QTOPERATION_ +#define _QTOPERATION_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtnode.hh" + +class QtData; // forward declaration of a subclass of QtOperation + +#include <iostream> + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +QtOperation defines a method {\tt evaluate()} getting a tupel of {\tt QtData} and returning +a {\tt QtData} element. Every subclass has to redefine this method to compute its specific +operation. Therefore, it takes its inputs which are also of type {\tt QtOperation}, and +invokes the {\tt evaluate()} method again. The results are used as operands and the +computed value is returned. + +*/ + +class QtOperation : public QtNode +{ + public: + /// default constructor + QtOperation(); + + /// constructor getting a pointer to the parent + QtOperation( QtNode* parent ); + + ///for associative law + virtual QtOperation* getUniqueOrder( const QtNode::QtNodeType ID ); + + /** + The method gives back a node that has the same QtNodeType and has the lowest + Spelling of all nodes in the subtree with the same QtNodeType. + */ + + /// method for evaluating the node + virtual QtData* evaluate( QtDataList* inputList ); + + /** + The method takes the {\tt inputList} to compute the result of the node which is returned in the end. + The semantics is that elements of the {\tt inputList} are not allowed to be used as a result because + the {\tt inputList} is freed by the caller. If this is needed, they have to be copied. + */ + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + /** + The method triggers type checking of the node's subtree. If an error occurs, an exception + is raised. + */ + + //@Man: Read/Write methods + //@{ + /// + /// + inline void setDataStreamType( const QtTypeElement& type ); + /// + inline const QtTypeElement& getDataStreamType() const; + /// + //@} + + void printTree( int tab, std::ostream& s, QtChildType mode=QT_ALL_NODES ); + + void printAlgebraicExpression( std::ostream& s ); + + protected: + /// result type of the node + QtTypeElement dataStreamType; + + private: + /// atribute for indetification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtoperation.icc" + +#endif + + diff --git a/qlparser/qtoperation.icc b/qlparser/qtoperation.icc new file mode 100644 index 0000000..c5703c1 --- /dev/null +++ b/qlparser/qtoperation.icc @@ -0,0 +1,43 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline void +QtOperation::setDataStreamType( const QtTypeElement &type ) +{ + dataStreamType = type; +} + + + +inline const QtTypeElement& +QtOperation::getDataStreamType() const +{ + return dataStreamType; +} diff --git a/qlparser/qtoperationiterator.cc b/qlparser/qtoperationiterator.cc new file mode 100644 index 0000000..6a1008a --- /dev/null +++ b/qlparser/qtoperationiterator.cc @@ -0,0 +1,303 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtOperationIterator: $Id: qtoperationiterator.cc,v 1.24 2001/08/07 12:36:49 barbat Exp $"; + + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtoperationiterator.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtdata.hh" + +#include <iostream> +#include <string> +#include <vector> +using namespace std; + +const QtNode::QtNodeType QtOperationIterator::nodeType = QT_OPERATION_ITERATOR; + + +QtOperationIterator::QtOperationIterator() + : QtIterator() +{ + operationTreeList = new QtOperationList(); +} + + +QtOperationIterator::QtOperationIterator( QtNode* node ) + : QtIterator( node ) +{ + operationTreeList = new QtOperationList(); +} + + +QtOperationIterator::~QtOperationIterator() +{ + // release( operationTreeList->begin(), operationTreeList->end() ); + QtOperationList::iterator iter; + for( iter = operationTreeList->begin(); iter!=operationTreeList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete operationTreeList; + operationTreeList=NULL; +} + + +QtNode::QtNodeList* +QtOperationIterator::getChilds( QtChildType flag ) +{ + RMDBCLASS( "QtOperationIterator", "getChilds( QtChildType )", "qlparser", __FILE__, __LINE__ ) + + QtNodeList* resultList=NULL; + QtNodeList* subList=NULL; + + QtOperationList::iterator iter; + + resultList = QtIterator::getChilds( flag ); + +RMDBGIF(3, RMDebug::module_qlparser, "QtOperationIterator", \ + RMInit::dbgOut << "1. childs from stream subtree " << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=resultList->begin(); debugIter!=resultList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); ) + + for( iter=operationTreeList->begin(); iter!=operationTreeList->end(); iter++ ) + { + if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) + { + subList = (*iter)->getChilds( flag ) ; + +RMDBGIF(3, RMDebug::module_qlparser, "QtOperationIterator", \ + RMInit::dbgOut << "2. childs from operation subtree (without direct childs) " << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=subList->begin(); debugIter!=subList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); ) + + // remove all elements in subList and insert them at the beginning of resultList + resultList->splice( resultList->begin(), *subList ); + +RMDBGIF(3, RMDebug::module_qlparser, "QtOperationIterator", \ + RMInit::dbgOut << "3. merge of the lists " << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=resultList->begin(); debugIter!=resultList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); ) + +RMDBGIF(3, RMDebug::module_qlparser, "QtOperationIterator", \ + RMInit::dbgOut << "4. old list (must be empty)" << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=subList->begin(); debugIter!=subList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); ) + + // delete temporary subList + delete subList; + subList=NULL; + }; + + // add nodes of next level + if( flag == QT_DIRECT_CHILDS || flag == QT_ALL_NODES ) + resultList->push_back( *iter ); + +RMDBGIF(3, RMDebug::module_qlparser, "QtOperationIterator", \ + RMInit::dbgOut << "4. current child list including direct childs " << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=resultList->begin(); debugIter!=resultList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); ) + + }; + + return resultList; +} + + +void +QtOperationIterator::printTree( int tab, ostream& s, QtChildType mode ) +{ + QtOperationList::iterator iter; + + s << SPACE_STR(tab).c_str() << "QtOperationIterator Object: type " << flush; + dataStreamType.printStatus( s ); + s << endl; + + if( mode != QtNode::QT_DIRECT_CHILDS ) + { + if( operationTreeList->empty() ) + s << SPACE_STR(tab).c_str() << "no operation" << endl; + else + for( iter=operationTreeList->begin(); iter!=operationTreeList->end(); iter++ ) + { + s << SPACE_STR(tab).c_str() << "operation: " << endl; + (*iter)->printTree( tab + 2, s, mode ); + } + } + + QtIterator::printTree( tab, s, mode ); +} + + + +void +QtOperationIterator::printAlgebraicExpression( ostream& s ) +{ + s << "op<"; + + if( operationTreeList ) + { + for( int i=0; i<operationTreeList->size(); i++ ) + { + (*operationTreeList)[i]->printAlgebraicExpression( s ); + + if( i < operationTreeList->size()-1 ) + s << ", "; + } + } + else + s << "no ops"; + + s << ">"; + + QtIterator::printAlgebraicExpression( s ); +} + + + +QtNode::QtDataList* +QtOperationIterator::next() +{ + RMDBCLASS( "QtOperationIterator", "next()", "qlparser", __FILE__, __LINE__ ) + + QtDataList* returnValue = NULL; + + if( inputs ) + { + QtDataList* nextTupel=NULL; + QtDataList* resultList=NULL; + + // create a composed tupel of type QtDataList of the next elements of the input streams + // right now, just take the QtDataList vector of the first input stream + nextTupel = (*inputs)[0]->next(); + + if( nextTupel ) + { + QtOperationList::iterator iter; + vector<QtData*>::iterator dataIter; + + resultList = new QtDataList( operationTreeList->size() ); + + int pos=0; + + for( iter=operationTreeList->begin(); iter!=operationTreeList->end(); iter++) + { + // send them through the operand tree + + try + { + if( *iter ) + (*resultList)[pos] = (*iter)->evaluate( nextTupel ); + } + catch(...) + { + // Delete the tupel vector received by next(). Just tupel elements which are not + // further referenced are deleted. + for( dataIter=nextTupel->begin(); dataIter!=nextTupel->end(); dataIter++ ) + if( (*dataIter) ) (*dataIter)->deleteRef(); + + for (QtDataList::iterator deleteIter = resultList->begin(); deleteIter != resultList->end(); deleteIter++) + { + delete *deleteIter; + *deleteIter = NULL; + } + delete resultList; + resultList = NULL; + delete nextTupel; + nextTupel = NULL; + + throw; + } + + pos++; + } + + // Delete the tupel vector received by next(). Just tupel elements which are not + // further referenced are deleted. + for( dataIter=nextTupel->begin(); dataIter!=nextTupel->end(); dataIter++ ) + if( (*dataIter) ) (*dataIter)->deleteRef(); + + // ... and now the vector itself + delete nextTupel; + nextTupel=NULL; + + returnValue = resultList; + } + } + return returnValue; +} + +/* +void +QtOperationIterator::preOptimize() +{ + QtOperationList::iterator iter; + + for( iter=operationTreeList->begin(); iter!=operationTreeList->end(); iter++ ) + (*iter)->optimizeLoad( new QtNode::QtTrimList ); + + // pass it to the input streams + QtIterator::preOptimize(); +}; +*/ + + +const QtTypeTuple& +QtOperationIterator::checkType() +{ + RMDBCLASS( "QtOperationIterator", "checkType()", "qlparser", __FILE__, __LINE__ ) + + dataStreamType = QtTypeTuple(); + + QtTypeTuple inputTypeTuple; + + getInputTypeTuple( inputTypeTuple ); + + // type check of operation trees + QtOperationList::iterator iter; + + for( iter=operationTreeList->begin(); iter!=operationTreeList->end(); iter++ ) + if( *iter ) + dataStreamType.concat( (*iter)->checkType( &inputTypeTuple ) ); + + return dataStreamType; +} + + diff --git a/qlparser/qtoperationiterator.hh b/qlparser/qtoperationiterator.hh new file mode 100644 index 0000000..78ab11e --- /dev/null +++ b/qlparser/qtoperationiterator.hh @@ -0,0 +1,120 @@ +#ifndef _QTOPERATIONITERATOR_ +#define _QTOPERATIONITERATOR_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtiterator.hh" +#include "qlparser/qtoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +A QtOperationIterator takes the next element of its input streams an creates +a tupel out of them. The operation specified through an operation tree of type +QtOperation is evaluated for this tupel and the result is passed to its output +stream. The class stands for the SELECT part of a query. The operations in the +SELECT clause are expressed through an operation tree which is attached to this +class. + +*/ + +class QtOperationIterator : public QtIterator +{ + public: + /// default constructor + QtOperationIterator(); + + /// constructor getting a pointer to the parent + QtOperationIterator( QtNode* node ); + + /// virtual destructor + virtual ~QtOperationIterator(); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// method for query rewrite + inline virtual void setInput( QtOperation* child, QtOperation* input); + + /// optimizing load access + //virtual void preOptimize(); + /** + Trigger load optimization in the operation tree and pass the optimization step to + the input streams. + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + //@Man: Read/Write methods: + //@{ + /// + //inline virtual void setParents(); + /// + inline void setOperationTree( QtOperation* operation ); + /// + inline QtNode::QtOperationList* getOperationTreeList(); + //@} + + //@Man: Operations of the ONC protocol: + //@{ + /// + QtDataList* next(); + //@} + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking + virtual const QtTypeTuple& checkType(); + + private: + /// operation trees + QtOperationList* operationTreeList; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtoperationiterator.icc" + +#endif + diff --git a/qlparser/qtoperationiterator.icc b/qlparser/qtoperationiterator.icc new file mode 100644 index 0000000..4abe3fc --- /dev/null +++ b/qlparser/qtoperationiterator.icc @@ -0,0 +1,74 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline void +QtOperationIterator::setOperationTree( QtOperation* operation ) +{ + if( operation ) + { + operationTreeList->push_back( operation ); + operation->setParent( this ); + }; +}; + + + +inline QtNode::QtOperationList* +QtOperationIterator::getOperationTreeList() +{ + return( operationTreeList ); +}; + + + +inline void +QtOperationIterator::setInput( QtOperation* inputOld, QtOperation* inputNew ) +{ + QtOperationList::iterator iter; + + for( iter=operationTreeList->begin(); iter!=operationTreeList->end(); iter++) + { + if( *iter == inputOld ) + { + (*iter) = inputNew; + + if( inputNew ) + inputNew->setParent( this ); + }; + }; +}; + + + +inline const QtNode::QtNodeType +QtOperationIterator::getNodeType() const +{ + return nodeType; +} + diff --git a/qlparser/qtpointdata.cc b/qlparser/qtpointdata.cc new file mode 100644 index 0000000..acc1a3d --- /dev/null +++ b/qlparser/qtpointdata.cc @@ -0,0 +1,114 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtPointData: $Id: qtpointdata.cc,v 1.7 2005/09/03 20:17:55 rasdev Exp $"; + +using namespace std; + +using namespace std; + +#include "qlparser/qtpointdata.hh" +#include <cstring> +// deprecated, not any longer available -- PB 2005-jan-14 +// #include <iostream> + + +QtPointData::QtPointData( const r_Point& point ) + : pointData(point), QtData() +{ +} + + +QtPointData::~QtPointData() +{ +} + + +QtDataType +QtPointData::getDataType() const +{ + return QT_POINT; +} + + +bool +QtPointData::equal( const QtData* obj ) const +{ + int returnValue = false; // not equal by initialization + + if( obj->getDataType() == QT_POINT ) + { + QtPointData* pt = (QtPointData*)obj; + + // check domains + returnValue = (pointData == pt->getPointData()); + } + + return returnValue; +} + + +std::string +QtPointData::getSpelling() const +{ + std::string result; + + // buffer + int bufferLen = pointData.dimension() * 50; // on the save side for one integers per dimension plus colon and brackets + char* buffer = new char[ bufferLen ]; + // replaced deprecated ostrstream -- PB 2005-jan-14 + // ostrstream bufferStream( buffer, bufferLen ); + ostringstream bufferStream( buffer ); + + bufferStream << pointData << std::ends; + + result.append( std::string( buffer ) ); + + delete[] buffer; + buffer=NULL; + return result; +} + + +char* QtPointData::getTypeStructure() const +{ + return strdup("point"); +} + + +void +QtPointData::printStatus( std::ostream& stream ) const +{ + stream << "point, value: " << std::flush; + stream << pointData << std::flush; + QtData::printStatus( stream ); +} diff --git a/qlparser/qtpointdata.hh b/qlparser/qtpointdata.hh new file mode 100644 index 0000000..11695f2 --- /dev/null +++ b/qlparser/qtpointdata.hh @@ -0,0 +1,101 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +#ifndef _QTPOINTDATA_ +#define _QTPOINTDATA_ + +#include "qlparser/qtdata.hh" + +#include "raslib/point.hh" + +#include <iostream> +#include <string> +#include <vector> + +// removed deprecated ostrsteam -- PB 2005-jan-14 +// #include <strstream.h> + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + The class encapsulates a point of type \Ref{r_Point}. +*/ + +class QtPointData : public QtData +{ + public: + /// constructor getting a point + QtPointData( const r_Point& point ); + + /// virtual destructor + virtual ~QtPointData(); + + //@Man: Read/Write methods: + //@{ + /// + + /// + inline const r_Point& getPointData() const; + /// + inline void setPointData( const r_Point& point ); + + /// returns a null-terminated string describing the type structure + virtual char* getTypeStructure() const; + /** + The string pointer has to be free using free() by the caller. + */ + + /// + //@} + + /// returns {\tt QT_POINT} + virtual QtDataType getDataType() const; + + /// compares data content + virtual bool equal( const QtData* obj ) const; + + /// returns content dependent string representation + virtual std::string getSpelling() const; + + /// print status of the object to the specified stream + virtual void printStatus( std::ostream& stream = std::cout ) const; + + private: + /// attribute storing the minterval + r_Point pointData; +}; + +#include "qlparser/qtpointdata.icc" + +#endif + + + + + diff --git a/qlparser/qtpointdata.icc b/qlparser/qtpointdata.icc new file mode 100644 index 0000000..d47ce57 --- /dev/null +++ b/qlparser/qtpointdata.icc @@ -0,0 +1,45 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline const r_Point& +QtPointData::getPointData() const +{ + return pointData; +} + + +inline void +QtPointData::setPointData( const r_Point& point ) +{ + pointData = point; +} + + + diff --git a/qlparser/qtpointop.cc b/qlparser/qtpointop.cc new file mode 100644 index 0000000..2f9f89b --- /dev/null +++ b/qlparser/qtpointop.cc @@ -0,0 +1,214 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtPointOp: $Id: qtpointop.cc,v 1.7 2002/06/05 18:18:17 coman Exp $"; + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtpointop.hh" +#include "qlparser/qtdata.hh" +#include "qlparser/qtpointdata.hh" +#include "qlparser/qtatomicdata.hh" + +#include "catalogmgr/ops.hh" +#include "relcatalogif/type.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + + +const QtNode::QtNodeType QtPointOp::nodeType = QT_POINTOP; + +QtPointOp::QtPointOp( QtOperationList* opList ) + : QtNaryOperation( opList ) +{ +} + + + +QtData* +QtPointOp::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtPointOp", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtDataList* operandList = NULL; + + if( getOperands( inputList, operandList ) ) + { + vector<QtData*>::iterator dataIter; + bool goOn=true; + + if( operandList ) + { + // first check operand types + for( dataIter=operandList->begin(); dataIter!=operandList->end() && goOn; dataIter++ ) + if (!( (*dataIter)->getDataType() == QT_SHORT || (*dataIter)->getDataType() == QT_USHORT || + (*dataIter)->getDataType() == QT_LONG || (*dataIter)->getDataType() == QT_ULONG || + (*dataIter)->getDataType() == QT_OCTET || (*dataIter)->getDataType() == QT_CHAR )) + { + goOn=false; + break; + } + + if( !goOn ) + { + RMInit::logOut << "Error: QtPointOp::evaluate() - operands of point expression must be of type integer." << std::endl; + + parseInfo.setErrorNo(410); + + // delete the old operands + if( operandList ) + { + for( dataIter=operandList->begin(); dataIter!=operandList->end(); dataIter++ ) + if( (*dataIter) ) (*dataIter)->deleteRef(); + + delete operandList; + operandList=NULL; + } + + throw parseInfo; + } + + // + // create a QtPointData object and fill it + // + r_Point pt( operandList->size() ); + + for( dataIter=operandList->begin(); dataIter!=operandList->end(); dataIter++ ) + if( (*dataIter)->getDataType() == QT_SHORT || + (*dataIter)->getDataType() == QT_LONG || + (*dataIter)->getDataType() == QT_OCTET ) + pt << ((QtAtomicData*)(*dataIter))->getSignedValue(); + else + pt << ((QtAtomicData*)(*dataIter))->getUnsignedValue(); + + returnValue = new QtPointData( pt ); + + // delete the old operands + if( operandList ) + { + for( dataIter=operandList->begin(); dataIter!=operandList->end(); dataIter++ ) + if( (*dataIter) ) (*dataIter)->deleteRef(); + + delete operandList; + operandList=NULL; + } + } + } + + return returnValue; +} + + + +void +QtPointOp::printTree( int tab, std::ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtPointOp Object " << getNodeType() << std::endl; + + QtNaryOperation::printTree( tab, s, mode ); +} + + + +void +QtPointOp::printAlgebraicExpression( std::ostream& s ) +{ + s << "["; + + QtNaryOperation::printAlgebraicExpression( s ); + + s << "]"; +} + + + +const QtTypeElement& +QtPointOp::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtPointOp", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + QtOperationList::iterator iter; + bool opTypesValid = true; + + for( iter=operationList->begin(); iter!=operationList->end() && opTypesValid; iter++ ) + { + const QtTypeElement& type = (*iter)->checkType( typeTuple ); + + // valid types: integers + if (!( type.getDataType() == QT_SHORT || + type.getDataType() == QT_LONG || + type.getDataType() == QT_OCTET || + type.getDataType() == QT_USHORT || + type.getDataType() == QT_ULONG || + type.getDataType() == QT_CHAR)) + { + opTypesValid = false; + break; + } + } + + if( !opTypesValid ) + { + RMInit::logOut << "Error: QtPointOp::checkType() - operand of point expression must be of type integer." << std::endl; + parseInfo.setErrorNo(410); + throw parseInfo; + } + + dataStreamType.setDataType( QT_POINT ); + + return dataStreamType; +} + + + + + + + + + + + + + + + + diff --git a/qlparser/qtpointop.hh b/qlparser/qtpointop.hh new file mode 100644 index 0000000..08f671a --- /dev/null +++ b/qlparser/qtpointop.hh @@ -0,0 +1,81 @@ +#ifndef _QTPOINTOP_ +#define _QTPOINTOP_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtnaryoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represents the root of a point expression. + +*/ + +class QtPointOp : public QtNaryOperation +{ + public: + /// constructor getting the two operands + QtPointOp( QtOperationList* opList ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + /** + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +#include "qlparser/qtpointop.icc" + +#endif + diff --git a/qlparser/qtpointop.icc b/qlparser/qtpointop.icc new file mode 100644 index 0000000..c9b8bf1 --- /dev/null +++ b/qlparser/qtpointop.icc @@ -0,0 +1,34 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtPointOp::getNodeType() const +{ + return nodeType; +} diff --git a/qlparser/qtscalardata.cc b/qlparser/qtscalardata.cc new file mode 100644 index 0000000..670204d --- /dev/null +++ b/qlparser/qtscalardata.cc @@ -0,0 +1,204 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtScalarData: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtscalardata.cc,v 1.17 2005/07/06 22:48:34 rasdev Exp $"; + +#include "qlparser/qtscalardata.hh" + +#include "relcatalogif/basetype.hh" + +#include "raslib/rmdebug.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#include <cstring> +#include <cstdlib> +using namespace std; +#endif + +#include <iostream> + +// deprecated, not available any longer -- PB 2005-jan-14 +// #include <strstream.h> + +QtScalarData::QtScalarData() + : valueBuffer(NULL), + valueType(NULL) +{ +} + + + +QtScalarData::QtScalarData( const QtScalarData& obj ) + : QtData( obj ) +{ + setLifetime( obj.getLifetime() ); + + // Pointer received from TypeFactory just can be copied. + valueType = obj.valueType; + + if( valueType && obj.valueBuffer ) + { + valueBuffer = new char[ valueType->getSize() ]; + memcpy( (void*)valueBuffer, (void*)obj.valueBuffer, valueType->getSize() ); + } + else + valueBuffer = NULL; +} + + + +QtScalarData::~QtScalarData() +{ + // valueType is not deleted because it is maintained by the typeFactory + + if( valueBuffer ) + { + delete[] valueBuffer; + valueBuffer=NULL; + } +} + + + +QtDataType +QtScalarData::getDataType() const +{ + QtDataType returnValue = QT_BOOL; + + if( valueType ) + switch( valueType->getType() ) + { + case BOOLTYPE: returnValue = QT_BOOL; break; + case CHAR: returnValue = QT_CHAR; break; + case OCTET: returnValue = QT_OCTET; break; + case USHORT: returnValue = QT_USHORT; break; + case SHORT: returnValue = QT_SHORT; break; + case ULONG: returnValue = QT_ULONG; break; + case LONG: returnValue = QT_LONG; break; + case FLOAT: returnValue = QT_FLOAT; break; + case DOUBLE: returnValue = QT_DOUBLE; break; + case STRUCT: returnValue = QT_COMPLEX; break; + default: + RMDBGONCE(0, RMDebug::module_qlparser, "r_QtScalarData", "getDataType() bad type " << valueType->getType()); + break; + } + + return returnValue; +} + + + +bool +QtScalarData::isScalarData() const +{ + return true; +} + + +bool +QtScalarData::equal( const QtData* obj ) const +{ + int returnValue = false; // not equal by initialization + + if( obj->isScalarData() ) + { + QtScalarData* scalarObj = (QtScalarData*)obj; + + if( getDataType() == scalarObj->getDataType() ) // Attention: this is not correct for structs + // compare value buffers + returnValue = (memcmp( (void*)valueBuffer, (void*)scalarObj->valueBuffer, valueType->getSize() ) == 0); + + } + + return returnValue; +} + + + +string +QtScalarData::getSpelling() const +{ + string result; + + // buffer for hex representation of chars + int bufferLen = valueType->getSize() * 2 + 1 + 2; // added final "+2" to remove memleak -- PB 2006-aug-17 + char* buffer = new char[ bufferLen ]; + // replaced deprecated ostrstream -- PB 2005-jan-14 + // ostrstream bufferStream( buffer, bufferLen ); + ostringstream bufferStream( buffer ); + + for( int i=0; i<valueType->getSize(); i++ ) + bufferStream << hex << valueBuffer[i]; + + bufferStream << ends; + + result.append( string( buffer ) ); + + delete[] buffer; + buffer = NULL; + return result; +} + + +char* QtScalarData::getTypeStructure() const +{ + if( valueType ) + return valueType->getTypeStructure(); + else + return NULL; +} + + +void +QtScalarData::printStatus( ostream& stream ) const +{ + if( valueType ) + { + char* typeStructure = valueType->getTypeStructure(); + + stream << "type: " << flush << valueType->getTypeName() + << ", structure: " << flush << typeStructure + << ", value: " << flush; + + valueType->printCell( stream, valueBuffer ); + + free( typeStructure ); + typeStructure=NULL; + QtData::printStatus( stream ); + } + else + stream << "<no type>"; +} diff --git a/qlparser/qtscalardata.hh b/qlparser/qtscalardata.hh new file mode 100644 index 0000000..9ef33cb --- /dev/null +++ b/qlparser/qtscalardata.hh @@ -0,0 +1,137 @@ +#ifndef _QTSCALARDATA_HH_ +#define _QTSCALARDATA_HH_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtdata.hh" +#include "catalogmgr/typefactory.hh" + + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The abstract class represents a scalar data handled by the + query tree. It can either be atomic (\Ref{QtAtomicData}) + or complex (\Ref{QtComplexData}). + +*/ + +class QtScalarData : public QtData +{ + public: + /// default constructor + QtScalarData(); + + /// copy constructor + QtScalarData( const QtScalarData& obj ); + + /// virtual destructor + virtual ~QtScalarData(); + + //@Man: Read/Write methods: + //@{ + /// + + /// returns data type + virtual QtDataType getDataType() const; + + /// returns true meaning that the data is of type scalar + virtual bool isScalarData() const; + + /// returns a pointer to the value type + inline const BaseType* getValueType() const; + + /// sets the value type + inline void setValueType( const BaseType* newType ); + + /// returns a pointer to the internal character representation + inline const char* getValueBuffer() const; + + /// sets the value buffer + inline void setValueBuffer( char* buffer ); + + /// returns a null-terminated string describing the type structure + virtual char* getTypeStructure() const; + /** + The string pointer has to be free using free() by the caller. + */ + + /// + //@} + + /// compares data content + virtual bool equal( const QtData* obj ) const; + + /// returns content dependent string representation + virtual std::string getSpelling() const; + + /// print status of the object to the specified stream + virtual void printStatus( std::ostream& stream = std::cout ) const; + + protected: + /// pointer to the value type + const BaseType* valueType; + + /// pointer to the value buffer + char* valueBuffer; +}; + +#include "qlparser/qtscalardata.icc" + +#endif + + + + + + + + + + + + + + + + + + + + + + diff --git a/qlparser/qtscalardata.icc b/qlparser/qtscalardata.icc new file mode 100644 index 0000000..873f0b7 --- /dev/null +++ b/qlparser/qtscalardata.icc @@ -0,0 +1,58 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const BaseType* +QtScalarData::getValueType() const +{ + return valueType; +} + + + +inline void +QtScalarData::setValueType( const BaseType* newType ) +{ + valueType = newType; +} + + + +inline const char* +QtScalarData::getValueBuffer() const +{ + return valueBuffer; +} + + + +inline void +QtScalarData::setValueBuffer( char* buffer ) +{ + valueBuffer = buffer; +} diff --git a/qlparser/qtselectioniterator.cc b/qlparser/qtselectioniterator.cc new file mode 100644 index 0000000..f6d2529 --- /dev/null +++ b/qlparser/qtselectioniterator.cc @@ -0,0 +1,281 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtSelectionIterator: $Id: qtselectioniterator.cc,v 1.24 2001/08/07 12:00:12 barbat Exp $"; + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtselectioniterator.hh" +#include "qlparser/qtatomicdata.hh" + +#include "relcatalogif/type.hh" + +#include <iostream> +#include <string> +#include <vector> +using namespace std; + +const QtNode::QtNodeType QtSelectionIterator::nodeType = QtNode::QT_SELECTION_ITERATOR; + + +QtSelectionIterator::QtSelectionIterator() + : QtIterator(), + conditionTree(NULL) +{ +} + + +QtSelectionIterator::QtSelectionIterator( QtNode* node ) + : QtIterator( node ), + conditionTree(NULL) +{ +} + + +QtSelectionIterator::~QtSelectionIterator() +{ + if( conditionTree ) + { + delete conditionTree; + conditionTree=NULL; + } +} + + +QtNode::QtNodeList* +QtSelectionIterator::getChilds( QtChildType flag ) +{ + QtNodeList* resultList=NULL; + QtNodeList* subList=NULL; + + RMDBGENTER( 1, RMDebug::module_qlparser, "QtSelectionIterator", " QtSelectionIterator::getChilds() ") + + resultList = QtIterator::getChilds( flag ); + + RMDBGIF( 4, RMDebug::module_qlparser, "QtSelectionIterator", \ + RMInit::dbgOut << "1. childs from stream subtree " << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=resultList->begin(); debugIter!=resultList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); \ + ) + + if( conditionTree ) + { + if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) + { + subList = conditionTree->getChilds( flag ); + + RMDBGIF( 4, RMDebug::module_qlparser, "QtSelectionIterator", \ + RMInit::dbgOut << "2. childs from operation subtree (without direct childs) " << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=subList->begin(); debugIter!=subList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); \ + ) + + // remove all elements in subList and insert them at the beginning in resultList + resultList->splice( resultList->begin(), *subList ); + + RMDBGIF( 4, RMDebug::module_qlparser, "QtSelectionIterator", \ + RMInit::dbgOut << "3. merge of the lists " << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=resultList->begin(); debugIter!=resultList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); \ + ) + + + RMDBGIF( 4, RMDebug::module_qlparser, "QtSelectionIterator", \ + RMInit::dbgOut << "4. old list (must be empty)" << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=subList->begin(); debugIter!=subList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); \ + ) + + // delete temporary subList + delete subList; + subList=NULL; + }; + + // add nodes of next level + if( flag == QT_DIRECT_CHILDS || flag == QT_ALL_NODES ) + resultList->push_back( conditionTree ); + + RMDBGIF( 4, RMDebug::module_qlparser, "QtSelectionIterator", + RMInit::dbgOut << "4. current child list including direct childs " << endl; \ + list<QtNode*>::iterator debugIter; \ + for( debugIter=resultList->begin(); debugIter!=resultList->end(); debugIter++ ) \ + (*debugIter)->printTree( 2, RMInit::dbgOut, QtNode::QT_DIRECT_CHILDS ); \ + ) + + }; + + return resultList; +} + + +void +QtSelectionIterator::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtSelectionIterator Object: type " << flush; + dataStreamType.printStatus( s ); + s << endl; + + if( mode != QtNode::QT_DIRECT_CHILDS ) + { + if( conditionTree ) + { + s << SPACE_STR(tab).c_str() << "condition : " << endl; + conditionTree->printTree( tab + 2, s ); + } + else + s << SPACE_STR(tab).c_str() << "no condition" << endl; + } + + QtIterator::printTree( tab, s, mode ); +} + + + +void +QtSelectionIterator::printAlgebraicExpression( ostream& s ) +{ + s << "sel<"; + + conditionTree->printAlgebraicExpression( s ); + + s << ">"; + + QtIterator::printAlgebraicExpression( s ); +} + + + +QtNode::QtDataList* +QtSelectionIterator::next() +{ + RMDBGENTER( 1, RMDebug::module_qlparser, "QtSelectionIterator", "QtSelectionIterator::next()" ) + + QtDataList* returnValue = NULL; + + if( inputs ) + { + bool nextTupelValid = false; + QtDataList* actualTupel=NULL; + + while( !nextTupelValid ) + { + actualTupel = (*inputs)[0]->next(); + + if( actualTupel ) + { + if( conditionTree ) + { + // evaluate the condition tree + QtData* resultData = conditionTree->evaluate( actualTupel ); + + if( resultData ) + { + if( resultData->getDataType() == QT_BOOL ) + nextTupelValid = (bool)((QtAtomicData*)resultData)->getUnsignedValue(); + else + { + RMInit::logOut << "Error: QtSelectionIterator::next() - result of the WHERE part must be of type Bool." << endl; + parseInfo.setErrorNo(359); + throw parseInfo; + } + + resultData->deleteRef(); + + if( !nextTupelValid ) + { + // delete transient objects + vector<QtData*>::iterator iter; + + for( iter=actualTupel->begin(); iter!=actualTupel->end(); iter++) + if( *iter ) (*iter)->deleteRef(); + + // delete vector itself + delete actualTupel; + actualTupel = NULL; + }; + } + } + else + nextTupelValid = true; + } + else + break; + } + + returnValue = actualTupel; + } + + RMDBGEXIT( 1, RMDebug::module_qlparser, "QtSelectionIterator", "QtSelectionIterator::next()" ) + + return returnValue; +} + +/* +inline void +QtSelectionIterator::preOptimize() +{ + if( conditionTree ) + conditionTree->optimizeLoad( new QtNode::QtTrimList ); + + // pass it to the input streams + QtIterator::preOptimize(); +}; +*/ + +const QtTypeTuple& +QtSelectionIterator::checkType() +{ + RMDBCLASS( "QtSelectionIterator", "checkType()", "qlparser", __FILE__, __LINE__ ) + + // concatenate types of inputs + getInputTypeTuple( dataStreamType ); + + // type check for condition tree + if( conditionTree ) + { + const QtTypeElement& type = conditionTree->checkType( (QtTypeTuple*)&dataStreamType ); + + if( type.getDataType() != QT_BOOL ) + { + RMInit::logOut << "Error: QtSelectionIterator::next() - result of the WHERE part must be of type Bool." << endl; + parseInfo.setErrorNo(359); + throw parseInfo; + } + } + + // pass type tuple + return dataStreamType; +} diff --git a/qlparser/qtselectioniterator.hh b/qlparser/qtselectioniterator.hh new file mode 100644 index 0000000..d187e68 --- /dev/null +++ b/qlparser/qtselectioniterator.hh @@ -0,0 +1,119 @@ +#ifndef _QTSELECTIONITERATOR_ +#define _QTSELECTIONITERATOR_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtiterator.hh" +#include "qlparser/qtoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +An condition expression specified through a reference to +an instance of the QtOperation sub-hierarchy, is evaluated for the actual input +The boolean result determines if the tupel is passed to the output stream or not. +So the method {\tt next()} reads tupels from its inputs until one can be +passed to its caller. The class represents the WHERE condition in the query + +*/ + +class QtSelectionIterator : public QtIterator +{ + public: + /// default constructor + QtSelectionIterator(); + + /// constructor getting a pointer to the parent + QtSelectionIterator( QtNode* node ); + + /// virtual destructor + virtual ~QtSelectionIterator(); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// method for query rewrite + inline virtual void setInput( QtOperation* child, QtOperation* input); + + /// optimizing load access +// virtual void preOptimize(); + /** + Trigger load optimization in the condition tree and pass the optimization step to + the input streams. + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + //@Man: Operations of the ONC protocol: + //@{ + /// + QtDataList* next(); + //@} + + //@Man: Read/Write methods: + //@{ + /// + //inline virtual void setParents(); + /// + inline void setConditionTree( QtOperation* operation ); + /// + inline QtOperation* getConditionTree(); + //@} + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking + virtual const QtTypeTuple& checkType(); + + private: + /// pointer to a tree representing the where part of the query + QtOperation* conditionTree; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtselectioniterator.icc" + +#endif + + diff --git a/qlparser/qtselectioniterator.icc b/qlparser/qtselectioniterator.icc new file mode 100644 index 0000000..5947f9c --- /dev/null +++ b/qlparser/qtselectioniterator.icc @@ -0,0 +1,68 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline void +QtSelectionIterator::setConditionTree( QtOperation* operation ) +{ + conditionTree = operation; + + if( operation ) + operation->setParent( this ); +}; + + + +inline QtOperation* +QtSelectionIterator::getConditionTree() +{ + return( conditionTree ); +}; + + + +inline void +QtSelectionIterator::setInput( QtOperation* inputOld, QtOperation* inputNew ) +{ + if( conditionTree == inputOld ) + { + setConditionTree( inputNew ); + + if( inputNew ) + inputNew->setParent( this ); + } +}; + + + +inline const QtNode::QtNodeType +QtSelectionIterator::getNodeType() const +{ + return nodeType; +} + diff --git a/qlparser/qtstringdata.cc b/qlparser/qtstringdata.cc new file mode 100644 index 0000000..41abcfa --- /dev/null +++ b/qlparser/qtstringdata.cc @@ -0,0 +1,88 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtStringData: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtstringdata.cc,v 1.8 2003/12/27 20:51:28 rasdev Exp $"; + +#include "qlparser/qtstringdata.hh" + +#include <iostream> +#include <cstring> + + + +QtStringData::QtStringData( const std::string& str ) + : stringData(str), QtData() +{ +} + + + +QtDataType +QtStringData::getDataType() const +{ + return QT_STRING; +} + + + +bool +QtStringData::equal( const QtData* obj ) const +{ + bool returnValue = false; // not equal by initialization + + if( obj->getDataType() == QT_STRING ) + returnValue = (stringData == ((QtStringData*)obj)->getStringData()); + + return returnValue; +} + + + +std::string +QtStringData::getSpelling() const +{ + return stringData; +} + + + +char* QtStringData::getTypeStructure() const +{ + return strdup("string"); +} + + + +void +QtStringData::printStatus( std::ostream& stream ) const +{ + stream << "string, value: " << stringData.c_str() << std::flush; + + QtData::printStatus( stream ); +} diff --git a/qlparser/qtstringdata.hh b/qlparser/qtstringdata.hh new file mode 100644 index 0000000..837ac05 --- /dev/null +++ b/qlparser/qtstringdata.hh @@ -0,0 +1,97 @@ +#ifndef _QTSTRINGDATA_ +#define _QTSTRINGDATA_ + +#include "qlparser/qtdata.hh" + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + The class encapsulates a string. +*/ + +class QtStringData : public QtData +{ + public: + /// constructor getting the string + QtStringData( const std::string& str ); + + //@Man: Read/Write methods: + //@{ + /// + + /// + inline const std::string& getStringData() const; + /// + inline void setStringData( const std::string& str ); + + /// returns a null-terminated string describing the type structure + virtual char* getTypeStructure() const; + /** + The string pointer has to be free using free() by the caller. + */ + + /// + //@} + + /// returns {\tt QT_STRING} + virtual QtDataType getDataType() const; + + /// compares data content + virtual bool equal( const QtData* obj ) const; + + /// returns content dependent string representation + virtual std::string getSpelling() const; + + /// print status of the object to the specified stream + virtual void printStatus( std::ostream& stream = std::cout ) const; + + private: + /// prevents from using the default constructor + QtStringData(){}; + + /// + std::string stringData; +}; + +#include "qlparser/qtstringdata.icc" + +#endif + + + + diff --git a/qlparser/qtstringdata.icc b/qlparser/qtstringdata.icc new file mode 100644 index 0000000..eea6747 --- /dev/null +++ b/qlparser/qtstringdata.icc @@ -0,0 +1,42 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline const std::string& +QtStringData::getStringData() const +{ + return stringData; +} + + +inline void +QtStringData::setStringData( const std::string& str ) +{ + stringData = str; +} diff --git a/qlparser/qtunaryfunc.cc b/qlparser/qtunaryfunc.cc new file mode 100644 index 0000000..fa151fd --- /dev/null +++ b/qlparser/qtunaryfunc.cc @@ -0,0 +1,414 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtIntervalLoOp, QtIntervalHiOp, QtSDom: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtunaryfunc.cc,v 1.11 2003/12/27 20:51:28 rasdev Exp $"; + +#include "qlparser/qtunaryfunc.hh" +#include "qlparser/qtintervaldata.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtmintervaldata.hh" +#include "qlparser/qtmdd.hh" + +const QtNode::QtNodeType QtIntervalLoOp::nodeType = QtNode::QT_LO; + + +QtIntervalLoOp::QtIntervalLoOp( QtOperation* newInput ) + : QtUnaryOperation( newInput ) +{ +} + + + +QtData* +QtIntervalLoOp::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtIntervalLoOp", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtData* operand = NULL; + + operand = input->evaluate( inputList ); + + if( operand ) + { +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() != QT_INTERVAL ) + { + RMInit::logOut << "Internal error in QtIntervalLoOp::evaluate() - " + << "runtime type checking failed (INTERVAL)." << std::endl; + + // delete old operand + if( operand ) operand->deleteRef(); + return 0; + } +#endif + + QtIntervalData* intervalData = (QtIntervalData*)operand; + + r_Sinterval sinterval = intervalData->getIntervalData(); + + if( sinterval.is_low_fixed() ) + { + returnValue = new QtAtomicData( (r_Long)(sinterval.low()), 4 ); + } + else + { + RMInit::logOut << "Error: QtIntervalLoOp::evaluate() - operation lo() can not be used for an open bound." << std::endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + parseInfo.setErrorNo(394); + throw parseInfo; + } + + // delete old operand + if( operand ) operand->deleteRef(); + + } + else + { + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtIntervalLoOp", "Information: QtIntervalLoOp::evaluate() - operand is not provided." ) + } + + return returnValue; +} + + + +void +QtIntervalLoOp::printTree( int tab, std::ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtIntervalLoOp Object: " << std::endl; + + QtUnaryOperation::printTree( tab, s, mode ); +} + + + +void +QtIntervalLoOp::printAlgebraicExpression( std::ostream& s ) +{ + s << "(" << std::flush; + + if( input ) + input->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ").lo "; +} + + + +const QtTypeElement& +QtIntervalLoOp::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtIntervalLoOp", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input ) + { + + // get input type + const QtTypeElement& inputType = input->checkType( typeTuple ); + + if( inputType.getDataType() != QT_INTERVAL ) + { + RMInit::logOut << "Error: QtIntervalLoOp::checkType() - operation lo() must be of type interval." << std::endl; + parseInfo.setErrorNo(393); + throw parseInfo; + } + + dataStreamType.setDataType( QT_LONG ); + } + else + RMInit::logOut << "Error: QtIntervalLoOp::checkType() - operand branch invalid." << std::endl; + + return dataStreamType; +} + + + +const QtNode::QtNodeType QtIntervalHiOp::nodeType = QtNode::QT_HI; + + +QtIntervalHiOp::QtIntervalHiOp( QtOperation* newInput ) + : QtUnaryOperation( newInput ) +{ +} + + + +QtData* +QtIntervalHiOp::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtIntervalHiOp", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtData* operand = NULL; + + operand = input->evaluate( inputList ); + + if( operand ) + { +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() != QT_INTERVAL ) + { + RMInit::logOut << "Internal error in QtIntervalHiOp::evaluate() - " + << "runtime type checking failed (INTERVAL)." << std::endl; + + // delete old operand + if( operand ) operand->deleteRef(); + return 0; + } +#endif + + QtIntervalData* intervalData = (QtIntervalData*)operand; + + r_Sinterval sinterval = intervalData->getIntervalData(); + + if( sinterval.is_high_fixed() ) + { + returnValue = new QtAtomicData( (r_Long)(sinterval.high()), 4 ); + } + else + { + RMInit::logOut << "Error: QtIntervalHiOp::evaluate() - operation lo() can not be used for an open bound." << std::endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + parseInfo.setErrorNo(394); + throw parseInfo; + } + + // delete old operand + if( operand ) operand->deleteRef(); + } + else + { + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtIntervalHiOp", "Information: QtIntervalHiOp::evaluate() - operand is not provided." ) + } + + return returnValue; +} + + + +void +QtIntervalHiOp::printTree( int tab, std::ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtIntervalHiOp Object: " << std::endl; + + QtUnaryOperation::printTree( tab, s, mode ); +} + + + +void +QtIntervalHiOp::printAlgebraicExpression( std::ostream& s ) +{ + s << "(" << std::flush; + + if( input ) + input->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ").hi "; +} + + + +const QtTypeElement& +QtIntervalHiOp::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtIntervalHiOp", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input ) + { + + // get input type + const QtTypeElement& inputType = input->checkType( typeTuple ); + + if( inputType.getDataType() != QT_INTERVAL ) + { + RMInit::logOut << "Error: QtIntervalHiOp::checkType() - operation lo() must be of type interval." << std::endl; + parseInfo.setErrorNo(393); + throw parseInfo; + } + + dataStreamType.setDataType( QT_LONG ); + } + else + RMInit::logOut << "Error: QtIntervalHiOp::checkType() - operand branch invalid." << std::endl; + return dataStreamType; +} + + + + +const QtNode::QtNodeType QtSDom::nodeType = QtNode::QT_SDOM; + + +QtSDom::QtSDom( QtOperation* newInput ) + : QtUnaryOperation( newInput ) +{ +} + + + +QtData* +QtSDom::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtSDom", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtData* operand = NULL; + + operand = input->evaluate( inputList ); + + if( operand ) + { +#ifdef QT_RUNTIME_TYPE_CHECK + if( operand->getDataType() != QT_MDD ) + { + RMInit::logOut << "Internal error in QtSDom::evaluate() - " + << "runtime type checking failed (MDD)." << std::endl; + + // delete old operand + if( operand ) operand->deleteRef(); + return 0; + } +#endif + + QtMDD* qtMDD = (QtMDD*) operand; + + returnValue = new QtMintervalData( qtMDD->getLoadDomain() ); + + // delete old operand + if( operand ) operand->deleteRef(); + } + else + { + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtSDom", "Information: QtSDom::evaluate() - operand is not provided." ) + } + + return returnValue; +} + + + +void +QtSDom::optimizeLoad( QtTrimList* trimList ) +{ + RMDBCLASS( "QtSDom", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) + + // reset trimList because optimization enters a new MDD area + + // delete list + vector<QtNode::QtTrimElement*>::iterator iter; + for( iter=trimList->begin(); iter!=trimList->end(); iter++ ) + { + delete *iter; + *iter=NULL; + } + delete trimList; + trimList=NULL; + + if( input ) + input->optimizeLoad( new QtNode::QtTrimList ); +} + + + +void +QtSDom::printTree( int tab, std::ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtSDom Object: " << std::endl; + + QtUnaryOperation::printTree( tab, s, mode ); +} + + + +void +QtSDom::printAlgebraicExpression( std::ostream& s ) +{ + s << "sdom(" << std::flush; + + if( input ) + input->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtTypeElement& +QtSDom::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtSDom", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input ) + { + + // get input type + const QtTypeElement& inputType = input->checkType( typeTuple ); + + if( inputType.getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtSDom::checkType() - operand must be of type MDD." << std::endl; + parseInfo.setErrorNo(395); + throw parseInfo; + } + + dataStreamType.setDataType( QT_MINTERVAL ); + } + else + RMInit::logOut << "Error: QtSDom::checkType() - operand branch invalid." << std::endl; + + return dataStreamType; +} + + diff --git a/qlparser/qtunaryfunc.hh b/qlparser/qtunaryfunc.hh new file mode 100644 index 0000000..b78ea35 --- /dev/null +++ b/qlparser/qtunaryfunc.hh @@ -0,0 +1,161 @@ +#ifndef _QTUNARYFUNC_HH__ +#define _QTUNARYFUNC_HH___ + +#include "qlparser/qtunaryoperation.hh" + +// forward declarations +class QtOperation; + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represenst a function returning the lower bound of an interval. + +*/ + +class QtIntervalLoOp : public QtUnaryOperation +{ + public: + /// constructor getting operand + QtIntervalLoOp( QtOperation* newInput ); + + /// evaluates the node + QtData* evaluate( QtDataList* inputList ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represenst a function returning the higher bound of an interval. + +*/ + +class QtIntervalHiOp : public QtUnaryOperation +{ + public: + /// constructor getting operand + QtIntervalHiOp( QtOperation* newInput ); + + /// evaluates the node + QtData* evaluate( QtDataList* inputList ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class represenst a function returning the spatial domain of an mdd object. + +*/ + +class QtSDom : public QtUnaryOperation +{ + public: + /// constructor getting operand + QtSDom( QtOperation* newInput ); + + /// evaluates the node + QtData* evaluate( QtDataList* inputList ); + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + /** + The method deletes the given {\tt trimList} and passes the {\tt optimizeLoad} + message with empty triming list to its operand tree. + + Optimization process enters a new MDD area. + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + +#include "qlparser/qtunaryfunc.icc" + +#endif + diff --git a/qlparser/qtunaryfunc.icc b/qlparser/qtunaryfunc.icc new file mode 100644 index 0000000..c6cccf1 --- /dev/null +++ b/qlparser/qtunaryfunc.icc @@ -0,0 +1,51 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline const QtNode::QtNodeType +QtIntervalLoOp::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtIntervalHiOp::getNodeType() const +{ + return nodeType; +} + + +inline const QtNode::QtNodeType +QtSDom::getNodeType() const +{ + return nodeType; +} + + diff --git a/qlparser/qtunaryinduce.cc b/qlparser/qtunaryinduce.cc new file mode 100644 index 0000000..60322d1 --- /dev/null +++ b/qlparser/qtunaryinduce.cc @@ -0,0 +1,1013 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtUnaryInduce: $Id: qtunaryinduce.cc,v 1.47 2002/08/19 11:13:27 coman Exp $"; + +#include "raslib/rmdebug.hh" + +#include "qlparser/qtunaryinduce.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtcomplexdata.hh" +#include "qlparser/qtnode.hh" + +#include "mddmgr/mddobj.hh" +#include "tilemgr/tile.hh" + +#include "catalogmgr/typefactory.hh" +#include "relcatalogif/structtype.hh" + +#include <sstream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +const QtNode::QtNodeType QtUnaryInduce::nodeType = QtNode::QT_UNARY_INDUCE; + +QtUnaryInduce::QtUnaryInduce( QtOperation* initInput ) + : QtUnaryOperation( initInput ) +{ +} + + + +bool +QtUnaryInduce::getOperand( QtDataList* inputList, QtData* &operand ) +{ + bool success = false; + + // get the operands + operand = input->evaluate( inputList ); + + // Test, if the operands are valid. + if( operand ) + success = true; + else + { + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QtUnaryInduce", "Information: QtUnaryInduce::getOperand() - operand is not provided." ) + } + + return success; +} + + + +QtData* +QtUnaryInduce::computeOp( QtData* operand, Ops::OpType operation ) +{ + QtData* returnValue = NULL; + + if( operand->getDataType() == QT_MDD ) + { + QtMDD* mdd = (QtMDD*) operand; + + const BaseType* resultCellType = (BaseType*)(Ops::getResultType( operation, mdd->getCellType() )); + + returnValue = computeUnaryMDDOp( mdd, resultCellType, operation); + } + else if( operand->isScalarData() ) + { + QtScalarData* scalar = (QtScalarData*) operand; + + const BaseType* resultCellType = (BaseType*)(Ops::getResultType( operation, scalar->getValueType() )); + + returnValue = computeUnaryOp( scalar, resultCellType, operation ); + } + + return returnValue; +} + + + +QtData* +QtUnaryInduce::computeUnaryMDDOp( QtMDD* operand, const BaseType* resultBaseType, + Ops::OpType operation, unsigned int operandOffset ) +{ + RMDBCLASS( "QtUnaryInduce", "computeUnaryMDDOp( QtMDD*, BaseType*, Ops::OpType, unsigned int ) ", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + + // get the MDD object + MDDObj* op = ((QtMDD*)operand)->getMDDObject(); + + // get the area, where the operation has to be applied + const r_Minterval &areaOp = ((QtMDD*)operand)->getLoadDomain(); + + // contains all tiles of the operand + vector<Tile*>* allTiles=NULL; + + // iterator for tiles + + // create MDDObj for result + MDDBaseType* mddBaseType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( mddBaseType ); + + MDDObj* mddres = new MDDObj( mddBaseType, areaOp ); + + // get all tiles in relevant area + allTiles = op->intersect(areaOp); + std::vector<Tile*>::iterator tileIt = allTiles->begin(); + if (tileIt != allTiles->end()) + { + Tile* resTile = NULL; + UnaryOp* myOp = NULL; + if (operation == Ops::OP_IDENTITY) + { + myOp = Ops::getUnaryOp(operation, resultBaseType, resultBaseType, 0, operandOffset); + } + else { + myOp = Ops::getUnaryOp(operation, resultBaseType, (*tileIt)->getType(), 0, 0); + } + if (myOp == NULL) + { + RMInit::logOut << "QtUnaryInduce::computeUnaryMDDOp(...) could not get operation for result type " << resultBaseType->getName() << " argument type " << (*tileIt)->getType() << " operation " << operation << endl; + delete myOp; + myOp = NULL; + delete allTiles; + allTiles = NULL; + //contents of allTiles are deleted when index is deleted + delete mddres; + mddres = NULL; + delete resTile; + resTile = NULL; + delete mddres; + mddres = NULL; + // i am not sure about that error number... + parseInfo.setErrorNo(366); + throw parseInfo; + } + // and iterate over them + try { + for( ; tileIt != allTiles->end(); tileIt++ ) + { + // domain of the actual tile + const r_Minterval &tileDom = (*tileIt)->getDomain(); + + // domain of the relevant area of the actual tile + r_Minterval intersectDom( tileDom.create_intersection( areaOp ) ); + + // create tile for result + resTile = new Tile( intersectDom, resultBaseType ); + + // carry out operation on the relevant area of the tiles + resTile->execUnaryOp(myOp, intersectDom, (*tileIt), intersectDom); + // insert Tile in result mdd + mddres->insertTile( resTile ); + } + } + catch(r_Error& err) + { + RMInit::logOut << "QtUnaryInduce::computeUnaryMDDOp caught " << err.get_errorno() << " " << err.what() << endl; + delete myOp; + myOp = NULL; + delete allTiles; + allTiles = NULL; + //contents of allTiles are deleted when index is deleted + delete mddres; + mddres = NULL; + delete resTile; + resTile = NULL; + delete mddres; + mddres = NULL; + parseInfo.setErrorNo(err.get_errorno()); + throw parseInfo; + } + catch (int err) + { + RMInit::logOut << "QtUnaryInduce::computeUnaryMDDOp caught errno error (" << err << ") in unaryinduce" << endl; + delete myOp; + myOp = NULL; + delete allTiles; + allTiles = NULL; + //contents of allTiles are deleted when index is deleted + delete mddres; + mddres = NULL; + delete resTile; + resTile = NULL; + delete mddres; + mddres = NULL; + parseInfo.setErrorNo(err); + throw parseInfo; + } + + delete myOp; + myOp = NULL; + } + // delete tile vector + delete allTiles; + allTiles = NULL; + + // create a new QtMDD object as carrier object for the transient MDD object + returnValue = new QtMDD( (MDDObj*)mddres ); + + // The following is now done when deleting the last reference to the operand + // delete the obsolete MDD object + // delete op; + + return returnValue; +} + + +QtData* +QtUnaryInduce::computeUnaryOp( QtScalarData* operand, const BaseType* resultBaseType, + Ops::OpType operation, unsigned int operandOffset ) +{ + RMDBCLASS( "QtUnaryInduce", "computeUnaryOp( QtScalarData*, BaseType*, Ops::OpType, unsigned int ) ", "qlparser", __FILE__, __LINE__ ) + + QtScalarData* scalarDataObj = NULL; + + // allocate memory for the result + char* resultBuffer = new char[ resultBaseType->getSize() ]; + + RMDBGIF( 4, RMDebug::module_qlparser, "QtUnaryInduce", \ + RMInit::dbgOut << "Operand value "; \ + operand->getValueType()->printCell( RMInit::dbgOut, operand->getValueBuffer() ); \ + RMInit::dbgOut << endl; \ + ) + + if(( operation == Ops::OP_IDENTITY )) // || ( operation == Ops::OP_SQRT )) + // operand type is the same as result type + Ops::execUnaryConstOp( operation, resultBaseType, + resultBaseType, + resultBuffer, + operand->getValueBuffer(), + 0, operandOffset ); + else + try + { + Ops::execUnaryConstOp( operation, resultBaseType, + operand->getValueType(), + resultBuffer, + operand->getValueBuffer(), + 0, operandOffset ); + } + catch(int err) + { + delete[] resultBuffer; + resultBuffer = NULL; + parseInfo.setErrorNo(err); + throw parseInfo; + } + + RMDBGIF( 4, RMDebug::module_qlparser, "QtUnaryInduce", \ + RMInit::dbgOut << "Result value "; \ + resultBaseType->printCell( RMInit::dbgOut, resultBuffer ); \ + RMInit::dbgOut << endl; \ + ) + + if( resultBaseType->getType() == STRUCT ) + scalarDataObj = new QtComplexData(); + else + scalarDataObj = new QtAtomicData(); + + scalarDataObj->setValueType ( resultBaseType ); + scalarDataObj->setValueBuffer( resultBuffer ); + + return scalarDataObj; +} + + +const QtNode::QtNodeType QtNot::nodeType = QtNode::QT_NOT; + +QtNot::QtNot( QtOperation* initInput ) + : QtUnaryInduce( initInput ) +{ +} + + +QtData* +QtNot::evaluate( QtDataList* inputList ) +{ + QtData* returnValue = NULL; + QtData* operand = NULL; + + if( getOperand( inputList, operand ) ) + { + returnValue = computeOp( operand, Ops::OP_NOT ); + + // delete old operand + if( operand ) operand->deleteRef(); + } + return returnValue; +} + + + +void +QtNot::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtNot Object" << endl; + + QtUnaryInduce::printTree( tab+2, s, mode ); +} + + + +void +QtNot::printAlgebraicExpression( ostream& s ) +{ + s << "not("; + + if( input ) + input->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")"; +} + + + +const QtTypeElement& +QtNot::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtNot", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input ) + { + + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + + RMDBGIF( 4, RMDebug::module_qlparser, "QtNot", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + + if( inputType.getDataType() == QT_MDD ) + { + const BaseType* baseType = ((const MDDBaseType*)(inputType.getType()))->getBaseType(); + + const BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_NOT, baseType )); + + if( !resultBaseType ) + { + RMInit::logOut << "Error: QtNot::checkType() - induce operand type is not supported." << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + + dataStreamType.setType( resultMDDType ); + } + else if( inputType.isBaseType() ) + { + BaseType* baseType = (BaseType*)(inputType.getType()); + + const BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_NOT, baseType )); + + if( !resultBaseType ) + { + RMInit::logOut << "Error: QtNot::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + + // MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + // TypeFactory::addTempType( resultMDDType ); + + // dataStreamType.setType( resultMDDType ); + dataStreamType.setType( resultBaseType ); + } + else + { + RMInit::logOut << "Error: QtNot::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtNot::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + + + + +const QtNode::QtNodeType QtDot::nodeType = QtNode::QT_DOT; + + + +QtDot::QtDot( const string& initElementName ) + : QtUnaryInduce( NULL ), + elementName( initElementName ), + elementNo(-1) +{ +} + + + +QtDot::QtDot( unsigned initElementNo ) + : QtUnaryInduce( NULL ), + elementNo( initElementNo ) +{ +} + + + +bool +QtDot::equalMeaning( QtNode* node ) +{ + bool result = false; + + if( nodeType == node->getNodeType() ) + { + QtDot* dotNode = (QtDot* ) node; // by force + + // In future, elementName have to be converted to elementNo + // and then just the numbers are compared. + if( (elementNo != -1 && elementNo == dotNode->elementNo) || + (elementNo == -1 && elementName == dotNode->elementName) ) + result = input->equalMeaning( dotNode->getInput() ); + }; + + return result; +} + + +string +QtDot::getSpelling() +{ + char tempStr[20]; + sprintf(tempStr, "%ud", (unsigned long)getNodeType()); + string result = string(tempStr); + + if( elementNo == -1 ) + result.append( elementName ); + else + { + std::ostringstream bufferStream; + bufferStream << elementNo << ends; + + result.append( bufferStream.str() ); + } + + result.append( "(" ); + result.append( input->getSpelling() ); + result.append( ")" ); + + return result; +} + + +QtData* +QtDot::evaluate( QtDataList* inputList ) +{ + RMDBCLASS( "QtDot", "evaluate( QtDataList* )", "qlparser", __FILE__, __LINE__ ) + + QtData* returnValue = NULL; + QtData* operand = NULL; + + if( getOperand( inputList, operand ) ) + { + if( operand->getDataType() == QT_MDD ) + { + QtMDD* mdd = (QtMDD*) operand; + +#ifdef QT_RUNTIME_TYPE_CHECK + // test, if operand has complex base type + if( mdd->getCellType()->getType() != STRUCT ) + { + RMInit::logOut << "Internal error in QtDot::evaluate() - " + << "runtime type checking failed." << endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + return 0; + } +#endif + + StructType* operandType = (StructType*)mdd->getCellType(); + unsigned int operandOffset; + const BaseType* resultCellType = NULL; + + if( elementNo == -1 ) + resultCellType = operandType->getElemType( (char*)(elementName.c_str()) ); + else + resultCellType = operandType->getElemType( (unsigned int)elementNo ); + + if( !resultCellType ) + { + RMInit::logOut << "Error: QtDot::evaluate() - struct selector is not valid." << endl; + parseInfo.setErrorNo(370); + throw parseInfo; + } + + if( elementNo == -1 ) + operandOffset = operandType->getOffset( (char*)(elementName.c_str()) ); + else + operandOffset = operandType->getOffset( (unsigned int)elementNo ); + + RMDBGIF( 1, RMDebug::module_qlparser, "QtUnaryInduce", \ + char* typeStructure = operandType->getTypeStructure(); \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtUnaryInduce", "Operand base type " << operandType->getTypeName() << ", structure " << typeStructure ) \ + free( typeStructure ); typeStructure=NULL; \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtUnaryInduce", "Operand base offset " << operandOffset ) \ + typeStructure = resultCellType->getTypeStructure(); \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtUnaryInduce", "Result base type " << resultCellType->getTypeName() << ", structure " << typeStructure ) \ + free( typeStructure ); typeStructure=NULL; \ + ) + + returnValue = computeUnaryMDDOp( mdd, resultCellType, Ops::OP_IDENTITY, operandOffset ); + } + else if( operand->isScalarData() ) + { + QtScalarData* scalar = (QtScalarData*) operand; + +#ifdef QT_RUNTIME_TYPE_CHECK + // test, if operand has complex base type + if( scalar->getValueType()->getType() != STRUCT ) + { + RMInit::logOut << "Internal error in QtDot::evaluate() - " + << "runtime type checking failed." << endl; + + // delete old operand + if( operand ) operand->deleteRef(); + + return 0; + } +#endif + + StructType* operandType = (StructType*)scalar->getValueType(); + unsigned int operandOffset; + const BaseType* resultCellType=NULL; + + if( elementNo == -1 ) + resultCellType = operandType->getElemType( (char*)(elementName.c_str()) ); + else + resultCellType = operandType->getElemType( (unsigned int)elementNo ); + + if( !resultCellType ) + { + RMInit::logOut << "Error: QtDot::evaluate() - struct selector is not valid." << endl; + parseInfo.setErrorNo(370); + throw parseInfo; + } + + if( elementNo == -1 ) + operandOffset = operandType->getOffset( (char*)(elementName.c_str()) ); + else + operandOffset = operandType->getOffset( (unsigned int)elementNo ); + + RMDBGIF( 1, RMDebug::module_qlparser, "QtUnaryInduce", \ + char* typeStructure = operandType->getTypeStructure(); \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtUnaryInduce", "Operand scalar type " << operandType->getTypeName() << ", structure " << typeStructure ) \ + free( typeStructure ); typeStructure=NULL; \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtUnaryInduce", "Operand scalar offset " << operandOffset ) \ + typeStructure = resultCellType->getTypeStructure(); \ + RMDBGMIDDLE( 4, RMDebug::module_qlparser, "QtUnaryInduce", "Result scalar type " << resultCellType->getTypeName() << ", structure " << typeStructure ) \ + free( typeStructure ); typeStructure=NULL; \ + ) + + returnValue = computeUnaryOp( scalar, resultCellType, Ops::OP_IDENTITY, operandOffset ); + } + else + { + RMInit::logOut << "Error: QtDot::evaluate() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + + // delete old operand + if( operand ) operand->deleteRef(); + } + + return returnValue; +} + + + +void +QtDot::printTree( int tab, ostream& s, QtChildType mode ) +{ + if( elementNo == -1 ) + s << SPACE_STR(tab).c_str() << "QtDot Object: access " << elementName.c_str() << endl; + else + s << SPACE_STR(tab).c_str() << "QtDot Object: access no " << elementNo << endl; + + QtUnaryInduce::printTree( tab+2, s, mode ); +} + +void +QtDot::printAlgebraicExpression( ostream& s ) +{ + s << "("; + + if( input ) + input->printAlgebraicExpression( s ); + else + s << "<nn>"; + + s << ")."; + + if( elementNo == -1 ) + s << elementName.c_str(); + else + s << elementNo; + + s << " "; +} + +const QtTypeElement& +QtDot::checkType( QtTypeTuple* typeTuple ) +{ + RMDBCLASS( "QtDot", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if( input ) + { + + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + + RMDBGIF( 4, RMDebug::module_qlparser, "QtDot", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + + if( inputType.getDataType() == QT_MDD ) + { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + + // test, if operand has complex base type + if( baseType->getType() != STRUCT ) + { + RMInit::logOut << "Error: QtDot::evaluate() - operand of induce dot operation must be complex." << endl; + parseInfo.setErrorNo(368); + throw parseInfo; + } + + StructType* structType = (StructType*)baseType; + const BaseType* resultBaseType = NULL; + + if( elementNo == -1 ) + resultBaseType = structType->getElemType( (char*)(elementName.c_str()) ); + else + resultBaseType = structType->getElemType( (unsigned int)elementNo ); + + if( !resultBaseType ) + { + RMInit::logOut << "Error: QtDot::evaluate() - struct selector is not valid." << endl; + parseInfo.setErrorNo(370); + throw parseInfo; + } + + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + + dataStreamType.setType( resultMDDType ); + } + else if( inputType.isBaseType() ) + { + BaseType* baseType = (BaseType*)(inputType.getType()); + + // test, if operand has complex base type + if( baseType->getType() != STRUCT ) + { + RMInit::logOut << "Error: QtDot::evaluate() - operand of dot operation must be complex." << endl; + parseInfo.setErrorNo(369); + throw parseInfo; + } + + StructType* structType = (StructType*)baseType; + const BaseType* resultBaseType = NULL; + + if( elementNo == -1 ) + resultBaseType = structType->getElemType( (char*)(elementName.c_str()) ); + else + resultBaseType = structType->getElemType( (unsigned int)elementNo ); + + if( !resultBaseType ) + { + RMInit::logOut << "Error: QtDot::evaluate() - struct selector is not valid." << endl; + parseInfo.setErrorNo(370); + throw parseInfo; + } + + dataStreamType.setType( resultBaseType ); + } + else + { + RMInit::logOut << "Error: QtDot::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } else + RMInit::logOut << "Error: QtDot::checkType() - operand branch invalid." << endl; + return dataStreamType; +} + +//-------------------------------------------- +// QtCast +//-------------------------------------------- + +const QtNode::QtNodeType QtCast::nodeType = QtNode::QT_CAST; + +QtCast::QtCast(QtOperation* initInput, cast_types t): + QtUnaryInduce(initInput), castType(t) {} + +QtData* QtCast::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) + returnValue = computeOp( operand, getOp(castType)); + + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtCast::printTree(int tab, ostream& s, QtChildType mode) { + const char *type_name[] = { + "bool", "octet", "char", "short", "ushort", + "long", "ulong", "float", "double" + }; + s << SPACE_STR(tab).c_str() << "QtCastObject " + << getNodeType() + << "<" << type_name[castType] << ">" + << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} + +void QtCast::printAlgebraicExpression(ostream& s) { + const char *type_name[] = { + "bool", "octet", "char", "short", "ushort", + "long", "ulong", "float", "double" + }; + s << "cast<" << type_name[castType] << ">("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtCast::checkType(QtTypeTuple* typeTuple) { + + RMDBCLASS( "QtCast", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if(input) { + + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 4, RMDebug::module_qlparser, "QtCast", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( getOp(castType), baseType )); + + + if(!resultBaseType) { + RMInit::logOut << "Error: QtCast::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( getOp(castType), baseType )); + + if(!resultBaseType) { + RMInit::logOut << "Error: QtCast::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtCast::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtCast::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + + +//-------------------------------------------- +// QtRealPartOp +//-------------------------------------------- + +const QtNode::QtNodeType QtRealPartOp::nodeType = QtNode::QT_REALPART; + +QtRealPartOp::QtRealPartOp(QtOperation* initInput): QtUnaryInduce(initInput) {} + +QtData* QtRealPartOp::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) + returnValue = computeOp( operand, Ops::OP_REALPART ); + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtRealPartOp::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtRealPartOpObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} + +void QtRealPartOp::printAlgebraicExpression(ostream& s) { + s << "Re("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtRealPartOp::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtRealPartOp", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if(input) { + + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + RMDBGIF( 1, RMDebug::module_qlparser, "QtRealPartOp", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; + ) + + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_REALPART, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtRealPartOp::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_REALPART, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtRealPartOp::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtRealPartOp::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } else + RMInit::logOut << "Error: QtRealPartOp::checkType() - operand branch invalid." << endl; + + return dataStreamType; +} + +//-------------------------------------------- +// QtImaginarPartOp +//-------------------------------------------- + +const QtNode::QtNodeType QtImaginarPartOp::nodeType = QtNode::QT_IMAGINARPART; + +QtImaginarPartOp::QtImaginarPartOp(QtOperation* initInput): QtUnaryInduce(initInput) {} + +QtData* QtImaginarPartOp::evaluate(QtDataList* inputList) { + QtData* returnValue = NULL; + QtData* operand = NULL; + + if(getOperand(inputList, operand)) + returnValue = computeOp( operand, Ops::OP_IMAGINARPART ); + // delete old operand + if(operand) operand->deleteRef(); + return returnValue; +} + +void QtImaginarPartOp::printTree(int tab, ostream& s, QtChildType mode) { + s << SPACE_STR(tab).c_str() << "QtImaginarPartObject " << getNodeType() << endl; + QtUnaryInduce::printTree( tab + 2, s, mode ); +} + +void QtImaginarPartOp::printAlgebraicExpression(ostream& s) { + s << "Im("; + if(input) + input->printAlgebraicExpression(s); + else + s << "<nn>"; + s << ")"; +} + +const QtTypeElement& QtImaginarPartOp::checkType(QtTypeTuple* typeTuple) { + RMDBCLASS( "QtImaginarPart", "checkType( QtTypeTuple* )", "qlparser", __FILE__, __LINE__ ) + + dataStreamType.setDataType( QT_TYPE_UNKNOWN ); + + // check operand branches + if(input) + { + + // get input types + const QtTypeElement& inputType = input->checkType( typeTuple ); + + RMDBGIF( 4, RMDebug::module_qlparser, "QtImaginarPartOp", \ + RMInit::dbgOut << "Operand: " << flush; \ + inputType.printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + + if(inputType.getDataType() == QT_MDD) { + const BaseType* baseType = ((MDDBaseType*)(inputType.getType()))->getBaseType(); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType( Ops::OP_IMAGINARPART, baseType )); + if(!resultBaseType) { + RMInit::logOut << "Error: QtImaginarPart::checkType() - induce operand type is not support" << endl; + parseInfo.setErrorNo(366); + throw parseInfo; + } + MDDBaseType* resultMDDType = new MDDBaseType( "tmp", resultBaseType ); + TypeFactory::addTempType( resultMDDType ); + dataStreamType.setType( resultMDDType ); + } + else if(inputType.isBaseType()) { + BaseType* baseType = (BaseType*)(inputType.getType()); + BaseType* resultBaseType = (BaseType*)(Ops::getResultType(Ops::OP_IMAGINARPART, baseType)); + if(!resultBaseType) { + RMInit::logOut << "Error: QtImaginarPart::checkType() - operand type is not supported." << endl; + parseInfo.setErrorNo(367); + throw parseInfo; + } + dataStreamType.setType( resultBaseType ); + } + else { + RMInit::logOut << "Error: QtImaginarPart::checkType() - operation is not supported for strings." << endl; + parseInfo.setErrorNo(385); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtImaginarPart::checkType() - operand branch invalid." << endl; + return dataStreamType; +} + +#include "autogen_qtui.cc" diff --git a/qlparser/qtunaryinduce.hh b/qlparser/qtunaryinduce.hh new file mode 100644 index 0000000..ebd69d4 --- /dev/null +++ b/qlparser/qtunaryinduce.hh @@ -0,0 +1,267 @@ +#ifndef _QTUNARYINDUCE_HH_ +#define _QTUNARYINDUCE_HH_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include "qlparser/qtunaryoperation.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtatomicdata.hh" + +#include "catalogmgr/ops.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +This class has just QtNot as subclass which represents the not operations +{\tt MDD<Bool> -> MDD<Bool>} and {\tt MDD<Int> -> MDD<Int>}. + +*/ + +class QtUnaryInduce : public QtUnaryOperation +{ + public: + /// constructor getting the operand + QtUnaryInduce( QtOperation* input ); + + protected: + /// computes the unary operation + QtData* computeOp( QtData* operand, Ops::OpType operation ); + + /// method for testing and evaluating the input branch + bool getOperand( QtDataList* inputList, QtData* &operand ); + /** + The method checks if the input branch is valid. Then it passes the evaluate message to its + operand with the {\tt inputList} as argument. The returned result is provided through the argument + {\tt operand} called by reference. The method returns {\tt true} it the operand is + valid, otherwise {\tt false}. + */ + + /// computes an unary induce operation with one MDD object + QtData* computeUnaryMDDOp( QtMDD* operand, const BaseType* resultBaseType, Ops::OpType operation, unsigned int operandOffset = 0 ); + /** + The method carries out the unary induce operation specified by {\tt operation} on the operand. For + the result, a new transient MDD object is created and returned. In the end, the MDD object of the operand + is freed. + */ + + /// computes an unary induce operation with one MDD object + QtData* computeUnaryOp( QtScalarData* operand, const BaseType* resultBaseType, Ops::OpType operation, unsigned int operandOffset = 0 ); + /** + The method carries out the unary operation specified by {\tt operation} on the operand. + */ + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtNot : public QtUnaryInduce +{ + public: + /// constructor getting the operand + QtNot( QtOperation* input ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + + /** + The method invokes the evaluate method of its superclass {\tt QtUnaryInduce} with the not + operation as an additional argument to compute the result of the node. + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + + + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtDot : public QtUnaryInduce +{ + public: + /// constructor getting operand and element name + QtDot( const std::string& elementName ); + + /// constructor getting operand and element number + QtDot( unsigned int elementNo ); + + /// creates a unique name for a common subexpression + virtual std::string getSpelling(); + + /// tests if the two nodes have an equal meaning in the query tree + virtual bool equalMeaning( QtNode* node ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ); + /** + The method invokes the evaluate method of its superclass {\tt QtUnaryInduce} with the not + operation as an additional argument to compute the result of the node. + */ + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ); + + private: + /// attribute for identification of nodes + static const QtNodeType nodeType; + + /// attribute storing selection element name + std::string elementName; + + /// attribute storing selection element number + int elementNo; + /** + The number is either positive, which means that the number + is valid, or -1 saying that the element name is valid for + selection. + */ +}; + + +//-------------------------------------------- +// QtCast +//-------------------------------------------- +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: +QtCast provides type conversions +*/ + +class QtCast : public QtUnaryInduce { +public: + enum cast_types { + t_bool, t_octet, t_char, t_short, t_ushort, + t_long, t_ulong, t_float, t_double + }; + + QtCast(QtOperation*, cast_types); + /// method for evaluating the node + QtData* evaluate(QtDataList*); + /// prints the tree + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES); + /// prints the algebraic expression + virtual void printAlgebraicExpression(std::ostream& = std::cout); + /// retrives node type + inline virtual const QtNodeType getNodeType() const; + /// semantics check + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL ); + +private: + Ops::OpType getOp(cast_types); + + static const QtNodeType nodeType; + cast_types castType; +}; + + +//-------------------------------------------- +// QtRealPartOp +//-------------------------------------------- + +class QtRealPartOp : public QtUnaryInduce { +public: + QtRealPartOp(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL); + +private: + static const QtNodeType nodeType; +}; + +//-------------------------------------------- +// QtImaginarPartOp +//-------------------------------------------- + +class QtImaginarPartOp : public QtUnaryInduce { +public: + QtImaginarPartOp(QtOperation*); + QtData* evaluate(QtDataList*); + virtual void printTree(int, std::ostream& = std::cout, QtChildType = QT_ALL_NODES); + virtual void printAlgebraicExpression(std::ostream& = std::cout); + inline virtual const QtNodeType getNodeType() const; + virtual const QtTypeElement& checkType(QtTypeTuple* = NULL); + +private: + static const QtNodeType nodeType; +}; + +#include "autogen_qtui.hh" +#include "qlparser/qtunaryinduce.icc" +#include "autogen_qtui.icc" + + +#endif + diff --git a/qlparser/qtunaryinduce.icc b/qlparser/qtunaryinduce.icc new file mode 100644 index 0000000..80691a4 --- /dev/null +++ b/qlparser/qtunaryinduce.icc @@ -0,0 +1,84 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + +inline const QtNode::QtNodeType +QtNot::getNodeType() const +{ + return nodeType; +} + + + +inline const QtNode::QtNodeType +QtDot::getNodeType() const +{ + return nodeType; +} + + +//---- QtCast ---- + +inline const QtNode::QtNodeType QtCast::getNodeType() const { + return nodeType; +} + +inline Ops::OpType QtCast::getOp(QtCast::cast_types t) { + Ops::OpType c=Ops::OP_CAST_BOOL; + switch(t) { + case QtCast::t_bool: c=Ops::OP_CAST_BOOL; break; + case QtCast::t_octet: c=Ops::OP_CAST_OCTET; break; + case QtCast::t_char: c=Ops::OP_CAST_CHAR; break; + case QtCast::t_short: c=Ops::OP_CAST_SHORT; break; + case QtCast::t_ushort: c=Ops::OP_CAST_USHORT; break; + case QtCast::t_long: c=Ops::OP_CAST_LONG; break; + case QtCast::t_ulong: c=Ops::OP_CAST_ULONG; break; + case QtCast::t_float: c=Ops::OP_CAST_FLOAT; break; + case QtCast::t_double: c=Ops::OP_CAST_DOUBLE; break; + default: RMInit::logOut << "Error: QtCast::getOp - undefined cast type." << endl; break; + } + return c; +} + + +//---- QtRealPartOp ---- + +inline const QtNode::QtNodeType QtRealPartOp::getNodeType() const { + return nodeType; +} + +//---- QtImaginarPartOp ---- + +inline const QtNode::QtNodeType QtImaginarPartOp::getNodeType() const { + return nodeType; +} + + +//---------------- + diff --git a/qlparser/qtunaryoperation.cc b/qlparser/qtunaryoperation.cc new file mode 100644 index 0000000..e05bb23 --- /dev/null +++ b/qlparser/qtunaryoperation.cc @@ -0,0 +1,204 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtUnaryOperation: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtunaryoperation.cc,v 1.23 2003/12/27 20:51:28 rasdev Exp $"; + +#include "qlparser/qtunaryoperation.hh" +#include "qlparser/qtconst.hh" + +#include <iostream> +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif + +QtUnaryOperation::QtUnaryOperation() + : QtOperation(), + input(NULL) +{ +} + + +QtUnaryOperation::QtUnaryOperation( QtOperation* inputInit ) + : QtOperation(), + input( inputInit ) +{ + if( input ) + input->setParent( this ); +} + + +QtUnaryOperation::~QtUnaryOperation() +{ + if( input ) + { + delete input; + input=NULL; + } +} + + + +string +QtUnaryOperation::getSpelling() +{ + char tempStr[20]; + sprintf(tempStr, "%ud", (unsigned long)getNodeType()); + string result = string(tempStr); + result.append( "(" ); + result.append( input->getSpelling() ); + result.append( ")" ); + + return result; +} + + + +void +QtUnaryOperation::simplify() +{ + RMDBCLASS( "QtUnaryOperation", "simplify()", "qlparser", __FILE__, __LINE__ ) + + // In order to work bottom up, first inspect the descendants + QtNode::simplify(); + + // Test, if operand is available. + if( input ) + { + // Test, if operand is of const type. + if( input->getNodeType() == QT_CONST ) + { + // evaluate the self node with no input list + QtData* newConst = this->evaluate( NULL ); + + if( newConst ) + { + // create a new constant node and fill it with newConst + QtConst* newNode = new QtConst( newConst ); + + // set its data stream type + newNode->checkType( NULL ); + + // link it to the parent + getParent()->setInput( this, newNode ); + + // delete the self node and its descendants + delete this; + } + } + } +} + + + +bool +QtUnaryOperation::equalMeaning( QtNode* node ) +{ + RMDBCLASS( "QtUnaryOperation", "equalMeaning( QtNode* )", "qlparser", __FILE__, __LINE__ ) + + bool result = false; + + if( getNodeType() == node->getNodeType() ) + { + QtUnaryOperation* unaryNode = (QtUnaryOperation*) node; // by force + + result = input->equalMeaning( unaryNode->getInput() ); + }; + + return ( result ); +} + + + +QtNode::QtNodeList* +QtUnaryOperation::getChilds( QtChildType flag ) +{ + RMDBCLASS( "QtUnaryOperation", "getChilds( QtChildType )", "qlparser", __FILE__, __LINE__ ) + + QtNodeList* resultList=NULL; + + if( flag == QT_DIRECT_CHILDS ) + resultList = new QtNodeList(); + + if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) + resultList = input->getChilds( flag ); + + if( flag == QT_DIRECT_CHILDS || flag == QT_ALL_NODES ) + resultList->push_back( input ); + + return resultList; +} + + +QtNode::QtAreaType +QtUnaryOperation::getAreaType() +{ + return( input->getAreaType() ); +} + + +void +QtUnaryOperation::optimizeLoad( QtTrimList* trimList ) +{ + RMDBCLASS( "QtUnaryOperation", "optimizeLoad( QtTrimList* )", "qlparser", __FILE__, __LINE__ ) + + // by default, pass load domain to the input + if( input ) + input->optimizeLoad( trimList ); + else + { + delete trimList; + trimList=NULL; + } +} + + +void +QtUnaryOperation::printTree( int tab, ostream& s, QtChildType mode ) +{ + if( mode != QtNode::QT_DIRECT_CHILDS ) + if( input ) + { + s << SPACE_STR(tab).c_str() << "input: " << endl; + input->printTree( tab+2, s, mode ); + } + else + s << SPACE_STR(tab).c_str() << "no input" << endl; +} + + + + + + diff --git a/qlparser/qtunaryoperation.hh b/qlparser/qtunaryoperation.hh new file mode 100644 index 0000000..e7602b8 --- /dev/null +++ b/qlparser/qtunaryoperation.hh @@ -0,0 +1,111 @@ +#ifndef _QTUNARYOPERATION_ +#define _QTUNARYOPERATION_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include <stdio.h> + +#include "qlparser/qtoperation.hh" + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************** + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +The class serves as superclass for all operation classes taking one +argument. + +*/ + +class QtUnaryOperation : public QtOperation +{ + public: + /// default constructor + QtUnaryOperation(); + + /// constructor getting the node to its operand + QtUnaryOperation( QtOperation* input ); + + /// virtual destructor + virtual ~QtUnaryOperation(); + + /// creates a unique name for a common subexpression + virtual std::string getSpelling(); + + /// simplifies the tree + virtual void simplify(); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// test if the edge to the parent node is of type mdd or atomic + virtual QtAreaType getAreaType(); + + /// tests if the two nodes have an equal meaning in the query tree + virtual bool equalMeaning( QtNode* node ); + + /// method for query rewrite + inline virtual void setInput( QtOperation* inputOld, QtOperation* inputNew ); + + /// optimizing load access + virtual void optimizeLoad( QtTrimList* trimList ); + + /** + The method passes the given {\tt trimList} list to its input tree. + */ + + /// debugging method + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + //@Man: Read/Write methods for the operand + //@{ + /// + + /// + inline virtual void setInput( QtOperation* input ); + /// + inline QtOperation* getInput(); + + //@} + + protected: + /// operation operand + QtOperation* input; +}; + +#include "qlparser/qtunaryoperation.icc" + +#endif + diff --git a/qlparser/qtunaryoperation.icc b/qlparser/qtunaryoperation.icc new file mode 100644 index 0000000..a208cdc --- /dev/null +++ b/qlparser/qtunaryoperation.icc @@ -0,0 +1,59 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline void +QtUnaryOperation::setInput( QtOperation* inputNew ) +{ + input = inputNew; + + if( inputNew ) + inputNew->setParent( this ); +}; + + +inline void +QtUnaryOperation::setInput( QtOperation* inputOld, QtOperation* inputNew ) +{ + if( input == inputOld ) + { + input = inputNew; + + if( inputNew ) + inputNew->setParent( this ); + } +}; + + +inline QtOperation* +QtUnaryOperation::getInput() +{ + return input; +}; + + diff --git a/qlparser/qtupdate.cc b/qlparser/qtupdate.cc new file mode 100644 index 0000000..a5ca731 --- /dev/null +++ b/qlparser/qtupdate.cc @@ -0,0 +1,812 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QtUpdate: $Header: /home/rasdev/CVS-repository/rasdaman/qlparser/qtupdate.cc,v 1.28 2003/12/27 20:51:28 rasdev Exp $"; + +#include "raslib/dlist.hh" + +#include "qlparser/qtupdate.hh" +#include "qlparser/qtdata.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtmintervaldata.hh" + +#include "tilemgr/tile.hh" +#include "tilemgr/tiler.hh" + +#include "mddmgr/mddobj.hh" + +#include <iostream> +#include <memory> + + +const QtNode::QtNodeType QtUpdate::nodeType = QtNode::QT_UPDATE; + + + +QtUpdate::QtUpdate( QtOperation* initUpdateTarget, QtOperation* initUpdateDomain, QtOperation* initUpdateSource ) + : QtExecute(), input(NULL), + updateTarget( initUpdateTarget ), + updateDomain( initUpdateDomain ), + updateSource( initUpdateSource ) +{ + if( updateTarget ) updateTarget->setParent( this ); + if( updateDomain ) updateDomain->setParent( this ); + if( updateSource ) updateSource->setParent( this ); +} + + + +QtUpdate::~QtUpdate() +{ + if( updateTarget ) + { + delete updateTarget; + updateTarget=NULL; + } + + if( updateDomain ) + { + delete updateDomain; + updateDomain=NULL; + } + + if( updateSource ) + { + delete updateSource; + updateSource=NULL; + } + + if( input ) + { + delete input; + input=NULL; + } +} + + + +int +QtUpdate::evaluate() +{ + RMDBCLASS( "QtUpdate", "evaluate()", "qlparser", __FILE__, __LINE__ ) + + // Test, if all necessary operands are available. + if( updateTarget && updateSource && input ) + { + QtNode::QtDataList* nextTupel; + + // open input stream + try + { + input->open(); + } + catch( ... ) + { + input->close(); + throw; + } + + try + { + while( (nextTupel = input->next()) ) + { + // get obligatory operands + QtData* target = updateTarget->evaluate( nextTupel ); + QtData* source = updateSource->evaluate( nextTupel ); + + // Test, if the operands are valid. + if( target && source ) + { + // check update target + if( target->getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtUpdate::evaluate() - update target must be an iterator variable." << endl; + + // delete tupel vector received by next() + for( vector<QtData*>::iterator dataIter=nextTupel->begin(); + dataIter!=nextTupel->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete nextTupel; + nextTupel=NULL; + + // delete the operands + if( target ) target->deleteRef(); + if( source ) source->deleteRef(); + + parseInfo.setErrorNo(950); + throw parseInfo; + } + + // check update source + if( source->getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtUpdate::evaluate() - update source must be an expression resulting in an MDD" << endl; + + // delete tupel vector received by next() + for( vector<QtData*>::iterator dataIter=nextTupel->begin(); + dataIter!=nextTupel->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete nextTupel; + nextTupel=NULL; + + // delete the operands + if( target ) target->deleteRef(); + if( source ) source->deleteRef(); + + parseInfo.setErrorNo(951); + throw parseInfo; + } + + QtMDD* targetMDD = (QtMDD*) target; + QtMDD* sourceMDD = (QtMDD*) source; + + MDDObj* targetObj = targetMDD->getMDDObject(); + MDDObj* sourceObj = sourceMDD->getMDDObject(); + + // test, if target is a persistent object + if( !targetObj->isPersistent() ) + { + RMInit::logOut << "Error: QtUpdate::evaluate() - result of target expression must be an assignable value (l-value)." << endl; + + // delete tupel vector received by next() + for( vector<QtData*>::iterator dataIter=nextTupel->begin(); + dataIter!=nextTupel->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete nextTupel; + nextTupel=NULL; + + // delete the operands + if( target ) target->deleteRef(); + if( source ) source->deleteRef(); + + parseInfo.setErrorNo(954); + throw parseInfo; + } + + // get optional domain + QtData* domainData = NULL; + r_Minterval domain; + + if( updateDomain ) + { + domainData = updateDomain->evaluate( nextTupel ); + + if( domainData ) + domain = ((QtMintervalData*)domainData)->getMintervalData(); + } + + RMDBGIF( 1, RMDebug::module_qlparser, "QtUpdate", \ + if( domainData ) \ + RMInit::dbgOut << endl << " target MDD, domain " << domain << endl; \ + else \ + RMInit::dbgOut << endl << " target MDD" << endl; \ + + targetMDD->printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl << " source MDD" << endl; \ + sourceMDD->printStatus( RMInit::dbgOut ); \ + RMInit::dbgOut << endl; \ + ) + + // 1st update strategy: + // + // 1. All cell values of the source domain which are already defined are + // updated with the corresponding new values. + // 2. If a source tile does not intersect with any tile of the target + // object, it is inserted. + + // In case of update domain existence, test for compatibility. + if( domainData ) + { + // Dimensionality of the udate domain specification has to be equal to + // the target MDD dimensionality. + if( domain.dimension() != targetMDD->getLoadDomain().dimension() ) + { + RMInit::logOut << "Error: QtUpdate::evaluate() - Update domain dimensionality must match target MDD dimensionaltiy." << endl; + + // delete tupel vector received by next() + for( vector<QtData*>::iterator dataIter=nextTupel->begin(); + dataIter!=nextTupel->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete nextTupel; + nextTupel=NULL; + + // delete the operands + if( target ) target->deleteRef(); + if( domainData ) domainData->deleteRef(); + if( source ) source->deleteRef(); + + parseInfo.setErrorNo(963); + throw parseInfo; + } + + // The number of interval dimension of the update domain has to be + // equal to the number of dimensions of the source domain. + int updateIntervals = 0; + + const vector<bool>* trimFlags = ((QtMintervalData*)domainData)->getTrimFlags(); + for( int i=0; i<trimFlags->size(); i++ ) + if( (*trimFlags)[i] ) + updateIntervals++; + + if( updateIntervals != sourceMDD->getLoadDomain().dimension() ) + { + RMInit::logOut << "Error: QtUpdate::evaluate() - Number of update intervals must match source dimensionality." << endl; + + // delete tupel vector received by next() + for( vector<QtData*>::iterator dataIter=nextTupel->begin(); + dataIter!=nextTupel->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete nextTupel; + nextTupel=NULL; + + // delete the operands + if( target ) target->deleteRef(); + if( domainData ) domainData->deleteRef(); + if( source ) source->deleteRef(); + + parseInfo.setErrorNo(962); + throw parseInfo; + } + + // Warning: Fixed bounds in update domain specifications are ignored. + } + + r_Minterval sourceMDDDomain( sourceMDD->getLoadDomain() ); + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "source mdd domain " << sourceMDDDomain ) + + // compute source MDD domain taking into account update domain + if( domainData ) + { + const vector<bool>* trimFlags = ((QtMintervalData*)domainData)->getTrimFlags(); + r_Minterval newSourceMDDDomain( targetMDD->getLoadDomain().dimension() ); + + for( int i=0, j=0; i<trimFlags->size(); i++ ) + if( (*trimFlags)[i] ) + newSourceMDDDomain << sourceMDDDomain[j++]; + else + newSourceMDDDomain << domain[i]; + + sourceMDDDomain = newSourceMDDDomain; + + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "source update domain " << sourceMDDDomain ) + } + // check if you may update that are ( you should not go out of bounds for mdddomaintype ) + if (!targetObj->getMDDBaseType()->compatibleWithDomain(&sourceMDDDomain)) + { + RMInit::logOut << "Error: QtUpdate::evaluate() - The update domain is outside the allowed domain of the target mdd." << endl; + + // delete tupel vector received by next() + for( vector<QtData*>::iterator dataIter=nextTupel->begin(); + dataIter!=nextTupel->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete nextTupel; + nextTupel=NULL; + + // delete the operands + if( target ) target->deleteRef(); + if( domainData ) domainData->deleteRef(); + if( source ) source->deleteRef(); + + parseInfo.setErrorNo(953); + throw parseInfo; + + } + // + // get all source tiles + // + vector<Tile*>* sourceTiles = sourceObj->getTiles(); +RMDBGIF(1, RMDebug::module_qlparser, "QtUpdate", \ + if (sourceTiles) \ + RMDBGMIDDLE(1, RMDebug::module_qlparser, "QtUpdate", "there are " << sourceTiles->size() << " source tiles") \ + else \ + RMDBGMIDDLE(1, RMDebug::module_qlparser, "QtUpdate", "there are no source tiles") ) + + // + // get all target tiles in the relevant area + // + + vector<Tile*>* targetTiles = NULL; +//this is not a very good idea +// try{ + targetTiles = targetObj->intersect( sourceMDDDomain ); +/* } + catch(...) + { + RMInit::logOut << "BUG of MDDObj::intersect" << endl; + targetTiles = new vector<Tile*>; + } +*/ + if( !targetTiles ) + { + targetTiles = new vector<Tile*>; + RMDBGMIDDLE(1, RMDebug::module_qlparser, "QtUpdate", "found no target tiles") + } + else { + RMDBGMIDDLE(1, RMDebug::module_qlparser, "QtUpdate", "found " << targetTiles->size() << " target tiles in mdd") + } + + // + // iterate over source tiles + // + unsigned long targetTileArea = 0; + unsigned long sourceTileArea = 0; + unsigned long targetTileDomain = 0; + unsigned long updatedArea = 0; + bool computed = false; + vector<r_Minterval> insertedDomains; + vector<r_Minterval> sourceDomains; + vector<r_Minterval> targetDomains; + vector<r_Minterval>::iterator domIt; + vector<r_Minterval>::iterator intervalIt; + vector<Tile*> retval; + vector<Tile*>::iterator retvalIt; + vector<Tile*>::iterator sourceIt; + vector<Tile*>::iterator targetIt; + sourceIt = sourceTiles->begin(); + //this lives here because we don't want memory leaks because of exceptions + //of course we seldom use this operation ( as we use copy tile most of the time ) + + UnaryOp* tempOp = NULL; + if (sourceIt != sourceTiles->end()) + tempOp = Ops::getUnaryOp(Ops::OP_IDENTITY, targetObj->getCellType(), (*sourceIt)->getType(), 0, 0); + std::auto_ptr<UnaryOp> myOp(tempOp); + for( ; sourceIt != sourceTiles->end(); sourceIt++ ) + { + // calculate relevant area of source tile + r_Minterval sourceTileDomain = (*sourceIt)->getDomain().create_intersection( sourceMDD->getLoadDomain() ); + + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "original source tile domain " << sourceTileDomain ) + + // compute update source tile domain taking into account update domain + r_Minterval updateSourceTileDomain; + + if( domainData ) + { + updateSourceTileDomain = r_Minterval( targetMDD->getLoadDomain().dimension() ); + const vector<bool>* trimFlags = ((QtMintervalData*)domainData)->getTrimFlags(); + + for( int i=0, j=0; i<trimFlags->size(); i++ ) + if( (*trimFlags)[i] ) + updateSourceTileDomain << sourceTileDomain[j++]; + else + updateSourceTileDomain << domain[i]; + } + else + updateSourceTileDomain = sourceTileDomain; + + //calculate number of cells in this area + sourceTileArea = sourceTileArea + sourceTileDomain.cell_count(); + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "update source tile domain " << updateSourceTileDomain ) + + bool intersection = false; + + for( targetIt = targetTiles->begin(); targetIt != targetTiles->end(); targetIt++ ) + { + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "target tile domain " << (*targetIt)->getDomain()) + if (!computed) + { + targetTileArea = targetTileArea + sourceMDDDomain.create_intersection((*targetIt)->getDomain()).cell_count(); + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "target area sum " << targetTileArea) + } + // if tiles are intersecting + if( updateSourceTileDomain.intersects_with( (*targetIt)->getDomain() ) ) + { + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "source tile domain " << updateSourceTileDomain << " intersects with target domain " << (*targetIt)->getDomain()) + intersection = true; + + // get intersecting updateSourceTileDomain + r_Minterval intersectUpdateSourceTileDomain = updateSourceTileDomain.create_intersection( (*targetIt)->getDomain() ); + + // compute corresponding sourceTileDomain + r_Minterval intersectSourceTileDomain = intersectUpdateSourceTileDomain; + if( domainData ) + { + const vector<bool>* trimFlags = ((QtMintervalData*)domainData)->getTrimFlags(); + + for( int i=0, j=0; i<trimFlags->size(); i++ ) + if( !((*trimFlags)[i]) ) + intersectSourceTileDomain.delete_dimension( j ); + else + j++; + } + + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "update domains: target tile " << (*targetIt)->getDomain() << " update target at " << intersectUpdateSourceTileDomain << ", source tile " << (*sourceIt)->getDomain() << " update with data at " << intersectSourceTileDomain ) + //(*targetIt)->execUnaryOp( Ops::OP_IDENTITY, intersectUpdateSourceTileDomain, *sourceIt, intersectSourceTileDomain ); + (*targetIt)->copyTile(intersectUpdateSourceTileDomain, *sourceIt, intersectSourceTileDomain); + updatedArea = updatedArea + intersectUpdateSourceTileDomain.cell_count(); + } + } + computed = true; + // insert the tile + if (!intersection) + { + // Create a new persistent tile, copy the transient data, + // and insert it into the target mdd object. + Tile* newPersTile = new Tile(updateSourceTileDomain, targetObj->getCellType(), (*sourceIt)->getDataFormat()); + if (updateSourceTileDomain.dimension() == sourceTileDomain.dimension()) + newPersTile->copyTile( updateSourceTileDomain, *sourceIt, sourceTileDomain ); + else + newPersTile->execUnaryOp( &(*myOp), updateSourceTileDomain, *sourceIt, sourceTileDomain ); + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "update domains: target tile " << newPersTile->getDomain() << " update target at " << updateSourceTileDomain << ", source tile " << (*sourceIt)->getDomain() << " update with data at " << sourceTileDomain ) + // this will make a crash in updateset3 because of a strange triming doman + //newPersTile->copyTile(updateSourceTileDomain, *sourceIt, sourceTileDomain); + + targetObj->insertTile( newPersTile ); + updatedArea = updatedArea + updateSourceTileDomain.cell_count(); + insertedDomains.push_back((*sourceIt)->getDomain()); + } + }//for is done + + if (sourceTileArea > updatedArea) + { + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "the source area was not updated completely, tiling the rest") + while (!insertedDomains.empty()) + { + intervalIt = insertedDomains.begin(); + for (sourceIt = sourceTiles->begin(); sourceIt != sourceTiles->end(); sourceIt++) + if ((*sourceIt)->getDomain() == *intervalIt) + { + sourceTiles->erase(sourceIt); + break; + } + insertedDomains.erase(intervalIt); + } + for (sourceIt = sourceTiles->begin(); sourceIt != sourceTiles->end(); sourceIt++) + sourceDomains.push_back((*sourceIt)->getDomain()); + for (targetIt = targetTiles->begin(); targetIt != targetTiles->end(); targetIt++) + targetDomains.push_back((*targetIt)->getDomain()); + r_Tiler t(sourceDomains, targetDomains); + t.split(); + t.removeDoubleDomains(); + t.removeCoveredDomains(); + t.mergeDomains(); + retval = t.generateTiles(*sourceTiles); + for (retvalIt = retval.begin(); retvalIt != retval.end(); retvalIt++) + { + targetObj->insertTile((Tile*)(*retvalIt)); + } + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QtUpdate", "insertion of the rest is done") + } + + // delete tile vectors + delete sourceTiles; + sourceTiles=NULL; + delete targetTiles; + targetTiles=NULL; + + // delete optional operand + if( domainData ) domainData->deleteRef(); + } + else + RMInit::logOut << "Error: QtUpdate::evaluate() - target or source is not provided." << endl; + + // delete the operands + if( target ) target->deleteRef(); + if( source ) source->deleteRef(); + + // delete tupel vector received by next() + for( vector<QtData*>::iterator dataIter=nextTupel->begin(); + dataIter!=nextTupel->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete nextTupel; + nextTupel=NULL; + + } // while + + } + catch( ... ) + { + input->close(); + throw; + } + + input->close(); + } + else + RMInit::logOut << "Error: QtUpdate::evaluate() - at least one operand branch is invalid." << endl; + + return 0; +} + + + +QtNode::QtNodeList* +QtUpdate::getChilds( QtChildType flag ) +{ + RMDBCLASS( "QtUpdate", "getChilds( QtChildType flag )", "qlparser", __FILE__, __LINE__ ) + + QtNodeList* resultList=NULL; + + // allocate resultList + resultList = new QtNodeList(); + + if( flag == QT_LEAF_NODES || flag == QT_ALL_NODES ) + { + if( input ) + { + QtNodeList* subList = input->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; + } + + if( updateTarget ) + { + QtNodeList* subList = updateTarget->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; + } + + if( updateDomain ) + { + QtNodeList* subList = updateDomain->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; + } + + if( updateSource ) + { + QtNodeList* subList = updateSource->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( input ); + resultList->push_back( updateTarget ); + resultList->push_back( updateDomain ); + resultList->push_back( updateSource ); + } + + return resultList; +} + + + +void +QtUpdate::printTree( int tab, ostream& s, QtChildType mode ) +{ + s << SPACE_STR(tab).c_str() << "QtUpdate Object" << endl; + + if( mode != QtNode::QT_DIRECT_CHILDS ) + { + if( updateTarget ) + { + s << SPACE_STR(tab).c_str() << "target: " << endl; + updateTarget->printTree( tab + 2, s ); + + if( updateDomain ) + { + s << SPACE_STR(tab+2).c_str() << "domain: " << endl; + updateDomain->printTree( tab + 4, s ); + } + else + s << SPACE_STR(tab+2).c_str() << "no domain" << endl; + } + else + s << SPACE_STR(tab).c_str() << "no target" << endl; + + if( updateSource ) + { + s << SPACE_STR(tab).c_str() << "source: " << endl; + updateSource->printTree( tab + 2, s ); + } + else + s << SPACE_STR(tab).c_str() << "no source" << endl; + + if( input ) + { + s << SPACE_STR(tab).c_str() << "input: " << endl; + input->printTree( tab+2, s, mode ); + } + else + s << SPACE_STR(tab).c_str() << "no input" << endl; + + s << endl; + } +} + + + +void +QtUpdate::printAlgebraicExpression( ostream& s ) +{ + s << "update<" << std::flush; + + if( updateTarget ) + updateTarget->printAlgebraicExpression( s ); + else + s << "<no target>"; + + if( updateDomain ) + updateDomain->printAlgebraicExpression( s ); + + s << "," << std::flush; + + if( updateSource ) + updateSource->printAlgebraicExpression( s ); + else + s << "<no source>"; + + s << ">" << std::flush; + + if( input ) + { + s << "( "; + input->printAlgebraicExpression( s ); + s << " )"; + } + else + s << "(<no input>)" << std::flush; +} + + + +void +QtUpdate::setStreamInput( QtONCStream* newInput ) +{ + input = newInput; + input->setParent( this ); +}; + +QtOperation* +QtUpdate::getUpdateTarget() +{ + return updateTarget; +} + +QtOperation* +QtUpdate::getUpdateDomain() +{ + return updateDomain; +} + +QtOperation* +QtUpdate::getUpdateSource() +{ + return updateSource; +} + +QtONCStream* +QtUpdate::getInput() +{ + return input; +} + +/* +void +QtUpdate::preOptimize() +{ + if( updateTarget ) + updateTarget->optimizeLoad( new QtNode::QtTrimList ); + + if( updateDomain ) + updateDomain->optimizeLoad( new QtNode::QtTrimList ); + + if( updateSource ) + updateSource->optimizeLoad( new QtNode::QtTrimList ); + + if( input ) + input->preOptimize(); +} +*/ + + +void +QtUpdate::checkType() +{ + RMDBCLASS( "QtUpdate", "checkType()", "qlparser", __FILE__, __LINE__ ) + + // check operand branches + if( updateTarget && updateSource && input ) + { + + // get input type + QtTypeTuple inputType = input->checkType(); + + // check target + const QtTypeElement& targetType = updateTarget->checkType( &inputType ); + if( targetType.getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtUpdate::checkType() - update target must be an iterator variable." << endl; + parseInfo.setErrorNo(950); + throw parseInfo; + } + + // check domain + if( updateDomain ) + { + const QtTypeElement& domainType = updateDomain->checkType( &inputType ); + if( domainType.getDataType() != QT_MINTERVAL ) + { + RMInit::logOut << "Error: QtUpdate::checkType() - update domain must be of type Minterval." << endl; + parseInfo.setErrorNo(961); + throw parseInfo; + } + } + + // check source + const QtTypeElement& sourceType = updateSource->checkType( &inputType ); + if( sourceType.getDataType() != QT_MDD ) + { + RMInit::logOut << "Error: QtUpdate::checkType() - update source must be an expression resulting in an MDD." << endl; + parseInfo.setErrorNo(951); + throw parseInfo; + } + + // test for compatible base types + bool compatible = false; + char* type1 = ((MDDBaseType*)(targetType.getType()))->getBaseType()->getTypeStructure(); + char* type2 = ((MDDBaseType*)(sourceType.getType()))->getBaseType()->getTypeStructure(); + compatible = (strcmp(type1, type2) == 0); + free(type1); + free(type2); + type1 = NULL; + type2 = NULL; + + if( !compatible ) + { + RMInit::logOut << "Error: QtUpdate::checkType() - update base type does not match mdd base type." << endl; + parseInfo.setErrorNo(952); + throw parseInfo; + } + } + else + RMInit::logOut << "Error: QtUpdate::checkType() - operand branch invalid." << endl; +} + + + + + diff --git a/qlparser/qtupdate.hh b/qlparser/qtupdate.hh new file mode 100644 index 0000000..429a6e2 --- /dev/null +++ b/qlparser/qtupdate.hh @@ -0,0 +1,119 @@ +#ifndef __QTUPDATE_HH__ +#define __QTUPDATE_HH___ + +#include "qlparser/qtexecute.hh" +#include "qlparser/qtoncstream.hh" +#include "qlparser/qtoperation.hh" + +#include <iostream> + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +*/ + +class QtUpdate : public QtExecute +{ + public: + /// constructor getting target, domain, and source expressions of the update + QtUpdate( QtOperation* initUpdateTarget, QtOperation* initUpdateDomain, QtOperation* initUpdateSource ); + + /// virtual destructor + virtual ~QtUpdate(); + + /// method for evaluating the node + virtual int evaluate(); + + /// return childs of the node + virtual QtNodeList* getChilds( QtChildType flag ); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + //@Man: Read/Write methods: + //@{ + /// + /// + void setStreamInput( QtONCStream* newInput ); + /// + /// returns updateTarget + QtOperation* getUpdateTarget(); + /// returns updateDomain + QtOperation* getUpdateDomain(); + ///returns updateSource + QtOperation* getUpdateSource(); + ///returns input + QtONCStream* getInput(); + //@} + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// method for query rewrite + inline virtual void setInput( QtOperation* child, QtOperation* input); + + /// pre optimization + //virtual void preOptimize(); + /** + Pre-Optimization step is passed to the input streams. + */ + + /// type checking + virtual void checkType(); + + private: + /// one input stream + QtONCStream* input; + + /// target expression + QtOperation* updateTarget; + + /// target domain expression + QtOperation* updateDomain; + + /// target expression + QtOperation* updateSource; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtupdate.icc" + +#endif + + + diff --git a/qlparser/qtupdate.icc b/qlparser/qtupdate.icc new file mode 100644 index 0000000..5b98b0e --- /dev/null +++ b/qlparser/qtupdate.icc @@ -0,0 +1,65 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtUpdate::getNodeType() const +{ + return nodeType; +} + + +inline void +QtUpdate::setInput( QtOperation* inputOld, QtOperation* inputNew ) +{ + if( inputOld == updateTarget ) + { + updateTarget = inputNew; + + if( inputNew ) + inputNew->setParent( this ); + } + + if( inputOld == updateDomain ) + { + updateDomain = inputNew; + + if( inputNew ) + inputNew->setParent( this ); + } + + if( inputOld == updateSource ) + { + updateSource = inputNew; + + if( inputNew ) + inputNew->setParent( this ); + } +}; + + diff --git a/qlparser/qtvariable.cc b/qlparser/qtvariable.cc new file mode 100644 index 0000000..730ad16 --- /dev/null +++ b/qlparser/qtvariable.cc @@ -0,0 +1,392 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * 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 <iostream> +#include <sstream> +#include <vector> +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<bool>(); +} + + +QtVariable::QtVariable( const string& initName, const r_Minterval& initDomain ) + : iteratorName( initName ), + loadDomain( initDomain ), + oldLoadDomain(), + dataIndex(-1) +{ + domainFlag = new vector<bool>(); +} + + +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<bool>(maxDimension+1); + + for( int j=0; j<loadDomain.dimension(); j++ ) + { + loadDomain[j] = r_Sinterval('*','*'); + (*domainFlag)[j] = true; + } + + // fill the loadDomain object with the QtTrimList specifications + for( i=trimList->begin(); 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<QtData*>::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; i<domainFlag->size(); 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<QtTypeElement>::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; +} + + + diff --git a/qlparser/qtvariable.hh b/qlparser/qtvariable.hh new file mode 100644 index 0000000..f056da7 --- /dev/null +++ b/qlparser/qtvariable.hh @@ -0,0 +1,136 @@ +#ifndef _QTVARIABLE_ +#define _QTVARIABLE_ + +#include "qlparser/qtoperation.hh" +#include "raslib/minterval.hh" + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif + +#include <stdio.h> + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + + //@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + The class stands for a MDD variable which corresponds to an element of the + tupel passed by the evaluate() method. + +*/ + + +class QtVariable : public QtOperation +{ + public: + /// constructor getting iterator variable name + QtVariable( const std::string& iteratorName ); + + /// constructor getting iterator variable name and load domain + QtVariable( const std::string& iteratorName, const r_Minterval& loadDomain ); + + /// destructor + virtual ~QtVariable(); + + /// test if the two nodes have an equal meaning in the query tree + virtual bool equalMeaning( QtNode* node ); + + /// creates a unique name for a common subexpression + virtual std::string getSpelling(); + + /// test if the edge to the parent node is of type mdd or atomic + virtual QtAreaType getAreaType(); + + /// optimizing load access + void optimizeLoad( QtTrimList* trimList ); + + /// method for evaluating the node + QtData* evaluate( QtDataList* inputList ) throw (ParseInfo); + + /// prints the tree + virtual void printTree( int tab, std::ostream& s = std::cout, QtChildType mode = QT_ALL_NODES ); + + /// prints the algebraic expression + virtual void printAlgebraicExpression( std::ostream& s = std::cout ); + + /// methods for iterator name + inline const std::string getIteratorName() const; + inline void setIteratorName( std::string& str ); + + /// method for loadDomain + inline const r_Minterval getLoadDomain() const; + + /// method for loadDomain + inline void setLoadDomain( r_Minterval& loadDomain ); + + /// method for oldLoadDomain + inline void setOldLoadDomain(); + + /// method for oldLoadDomain + inline const r_Minterval getOldLoadDomain(); + + /// method for LoadDomain + inline vector<bool>* getLoadDomainFlag(); + + /// method for identification of nodes + inline virtual const QtNodeType getNodeType() const; + + /// type checking of the subtree + virtual const QtTypeElement& checkType( QtTypeTuple* typeTuple = NULL ) throw (ParseInfo); + + private: + + /// attribute storing the iterator name + std::string iteratorName; + + /// minterval storing the minimal domain which is needed in the upper tree + r_Minterval loadDomain; + + /// unique backup of the loadDomain + r_Minterval oldLoadDomain; + + /// bitvector for discrimination of trimming and projections + vector<bool>* domainFlag; + + /// attribute storing the index of the variable's data element in the data vector + int dataIndex; + + /// attribute for identification of nodes + static const QtNodeType nodeType; +}; + +#include "qlparser/qtvariable.icc" + +#endif + diff --git a/qlparser/qtvariable.icc b/qlparser/qtvariable.icc new file mode 100644 index 0000000..0625b32 --- /dev/null +++ b/qlparser/qtvariable.icc @@ -0,0 +1,84 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + ************************************************************/ + +inline const QtNode::QtNodeType +QtVariable::getNodeType() const +{ + return nodeType; +} + + +inline const std::string +QtVariable::getIteratorName() const +{ + return iteratorName; +} + +inline void +QtVariable::setIteratorName( std::string& str ) +{ + iteratorName = str; +} + + +inline const r_Minterval +QtVariable::getLoadDomain() const +{ + return loadDomain; +} + + +inline void +QtVariable::setLoadDomain( r_Minterval& loadDomainNew ) +{ + if( oldLoadDomain.dimension() == 0 ) + oldLoadDomain = loadDomain; + loadDomain = loadDomainNew; +} + + +inline void +QtVariable::setOldLoadDomain() +{ + loadDomain = oldLoadDomain; +} + + +inline const r_Minterval +QtVariable::getOldLoadDomain() +{ + return oldLoadDomain; +} + + +inline std::vector<bool>* +QtVariable::getLoadDomainFlag() +{ + return domainFlag; +} diff --git a/qlparser/querytree.cc b/qlparser/querytree.cc new file mode 100644 index 0000000..4a14ed6 --- /dev/null +++ b/qlparser/querytree.cc @@ -0,0 +1,489 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * SOURCE: querytree.cc + * + * MODULE: qlparser + * CLASS: QueryTree + * + * PURPOSE: + * + * COMMENTS: + * + ************************************************************/ + +static const char rcsid[] = "@(#)qlparser, QueryTree: $Id: querytree.cc,v 1.52 2005/06/28 08:42:13 rasdev Exp $"; + + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +using namespace std; +#endif +#include <iostream> +#include <dlfcn.h> + +#include "raslib/rmdebug.hh" +#include "globals.hh" + +#include "qlparser/querytree.hh" +#include "qlparser/qtnode.hh" +#include "qlparser/qtoperationiterator.hh" +#include "qlparser/qtselectioniterator.hh" +#include "qlparser/qtjoiniterator.hh" +#include "qlparser/qtvariable.hh" +#include "qlparser/qtmdd.hh" +#include "qlparser/qtdomainoperation.hh" +#include "qlparser/qtexecute.hh" + +#include "catalogmgr/typefactory.hh" +#include "relcatalogif/mdddomaintype.hh" +#include "relcatalogif/settype.hh" + +void (*QueryTree::optimizationFnc)(unsigned int, QtNode*) = NULL; + +unsigned int QueryTree::nextCSENo = 0; + +SymbolTable<int> QueryTree::symtab; + +QueryTree::QueryTree() + : rootNode(NULL), + optimizationLevel(4) +{ +} + + +QueryTree::QueryTree( QtNode* root ) + : rootNode( root ), + optimizationLevel(4) +{ +} + + +QueryTree::~QueryTree() +{ + if( rootNode ) + { + delete rootNode; + rootNode=NULL; + } + releaseDynamicObjects(); +} + + +void +QueryTree::checkSemantics() +{ + RMDBCLASS( "QueryTree", "checkSemantics()", "qlparser", __FILE__, __LINE__ ) + + switch( rootNode->getNodeType() ) + { + case QtNode::QT_MDD_ACCESS: + case QtNode::QT_OPERATION_ITERATOR: + case QtNode::QT_JOIN_ITERATOR: + case QtNode::QT_SELECTION_ITERATOR: + { + const QtTypeTuple& resultType = ((QtONCStream*)rootNode)->checkType(); + // RMInit::logOut << "result type: " << flush; + // resultType.printStatus( RMInit::logOut ); + } + break; + + case QtNode::QT_UPDATE: + case QtNode::QT_INSERT: + case QtNode::QT_DELETE: + case QtNode::QT_COMMAND: + case QtNode::QT_PYRAMID: + ((QtExecute*)rootNode)->checkType(); + break; + + default: + { + const QtTypeElement& resultType = ((QtOperation*)rootNode)->checkType(); + // RMInit::logOut << "result type: " << flush; + // resultType.printStatus( RMInit::logOut ); + } + break; + } +} + + +void +QueryTree::optimize( unsigned int currentOptimizationLevel ) +{ + RMDBCLASS( "QueryTree", "optimize( unsigned int )", "qlparser", __FILE__, __LINE__ ) + + if (optimizationFnc == NULL) { + char *dir = CONFDIR; + char libName[255]; + sprintf(libName,"%s/lib/libqloptimizer.so", dir); + + if (access(libName, X_OK | R_OK) == 0) { + void *handle = dlopen(libName, RTLD_NOW); + if (handle == NULL) { + RMInit::logOut << "Optimization library found, however could not be loaded" << endl; + printf("DLERROR = %s\n", dlerror()); + RMInit::logOut << dlerror() << endl; + return; + } + + *(void **)(&optimizationFnc) = dlsym(handle, "runOptimizations"); + if (optimizationFnc == NULL) { + RMInit::logOut << "Optimization library found, however the entry point was not found" << endl; + return; + } + } else { + RMInit::logOut << "No optimization library found" << endl; + return; + } + } + + optimizationFnc(currentOptimizationLevel, rootNode); + + RMDBGIF( 1, RMDebug::module_qlparser, "QueryTree", \ + RMInit::logOut << endl << " "; \ + rootNode->printAlgebraicExpression( RMInit::logOut ); \ + RMInit::logOut << endl << endl; \ + rootNode->printTree( 2, RMInit::logOut ); \ + RMInit::logOut << endl; \ + ) +} + +vector<QtData*>* +QueryTree::evaluateRetrieval() throw (r_Error, ParseInfo) +{ + vector<QtData*>* returnValue=NULL; + + if( rootNode ) + { + if( rootNode->getNodeType() != QtNode::QT_MDD_ACCESS && + rootNode->getNodeType() != QtNode::QT_OPERATION_ITERATOR && + rootNode->getNodeType() != QtNode::QT_JOIN_ITERATOR && + rootNode->getNodeType() != QtNode::QT_SELECTION_ITERATOR ) + { + RMInit::logOut << "QueryTree::evaluateRetrieval() - Retrieval query must start with an ONC node." << endl; + ParseInfo errorInfo = rootNode->getParseInfo(); + errorInfo.setErrorNo(371); + throw errorInfo; + } + + QtNode::QtDataList* dataList=NULL; + QtNode::QtDataList::iterator dataIter; + QtONCStream* oncRootNode = (QtONCStream*)rootNode; + + try + { + oncRootNode->open(); + } + catch( ... ) + { + oncRootNode->close(); + RMInit::logOut << "QueryTree::evaluateRetrieval() - rethrow exception from oncRootNode->open()." << endl; + throw; + } + + // removed to have uniform, compact log output -- PB 2003-nov-20 + // RMInit::logOut << endl; + + // create result collection + vector<QtData*>* resultData = new vector<QtData*>(); + + try + { + while( (dataList = oncRootNode->next()) ) + { + if( dataList->size() > 1 || (*dataList)[0] == NULL ) + { + // Delete the tupel vector received by next(). Just tupel elements which are not + // further referenced are deleted. + for( dataIter=dataList->begin(); dataIter!=dataList->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete dataList; + dataList=NULL; + + if( resultData ) + { + // Delete the result vector + for( dataIter=resultData->begin(); dataIter!=resultData->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete resultData; + resultData = NULL; + } + + RMInit::logOut << "QueryTree::evaluateTree() - multiple query targets are not supported." << endl; + ParseInfo errorInfo = oncRootNode->getParseInfo(); + errorInfo.setErrorNo(361); + throw errorInfo; + } + + QtData* resultElement = (*dataList)[0]; + + // take the data element as result data and reset it in the tupel vector + resultData->push_back( resultElement ); + (*dataList)[0] = NULL; + + RMDBGMIDDLE( 2, RMDebug::module_qlparser, "QueryTree", endl << endl << "NEXT RESULT ITEM OF THE QUERY INSERTED" << endl << endl ) + + // Delete the tupel vector received by next(). Just tupel elements which are not + // set to zero and which are not further referenced are deleted. + for( dataIter=dataList->begin(); dataIter!=dataList->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + + // delete the tuple vector + delete dataList; + dataList=NULL; + } + } + catch(r_Error& myErr) { + RMInit::logOut << endl << "Caught BAD exception when evaluating query! " << endl; + RMInit::logOut << myErr.what() << endl; + if( resultData ) + { + // Delete the result vector + for( dataIter=resultData->begin(); dataIter!=resultData->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete resultData; + resultData = NULL; + } + + oncRootNode->close(); + RMInit::logOut << "QueryTree::evaluateTree() - rethrow exception." << endl; + throw; + } + catch( ... ) + { + if( resultData ) + { + // Delete the result vector + for( dataIter=resultData->begin(); dataIter!=resultData->end(); dataIter++ ) + if( *dataIter ) (*dataIter)->deleteRef(); + delete resultData; + resultData = NULL; + } + + oncRootNode->close(); + RMInit::logOut << "QueryTree::evaluateTree() - rethrow exception." << endl; + throw; + } + + oncRootNode->close(); + + returnValue = resultData; + } + + return returnValue; +} + + + +void +QueryTree::evaluateUpdate() throw (r_Error,ParseInfo) +{ + if( rootNode ) + { + if( rootNode->getNodeType() != QtNode::QT_UPDATE && + rootNode->getNodeType() != QtNode::QT_INSERT && + rootNode->getNodeType() != QtNode::QT_DELETE && + rootNode->getNodeType() != QtNode::QT_COMMAND && + rootNode->getNodeType() != QtNode::QT_PYRAMID + ) + { + RMInit::logOut << "QueryTree::evaluateUpdate() - update query must start with an INSERT, UPDATE, DELETE, DROP or CREATE statement." << endl; + ParseInfo errorInfo = rootNode->getParseInfo(); + errorInfo.setErrorNo(372); + throw errorInfo; + } + + QtExecute* executeNode = (QtExecute*) rootNode; + + // evaluate the update query + executeNode->evaluate(); + } +} + + + +void QueryTree::printTree( int tab, ostream& s ) { + if ( rootNode ) { + s << SPACE_STR(tab).c_str() << "QueryTree:" << endl; + rootNode->printTree( tab + 2, s ); + } else + s << SPACE_STR(tab).c_str() << "QueryTree: Qt has no root node." << endl; +} + +void QueryTree::addDynamicObject( QtNode *node ) { + qtNodeList.push_back( node ); +} + +void QueryTree::removeDynamicObject( QtNode *node ) { + qtNodeList.remove( node ); +} + +void QueryTree::addDynamicObject( QtData *node ) { + qtDataList.push_back( node ); +} + +void QueryTree::removeDynamicObject( QtData *node ) { + qtDataList.remove( node ); +} + +void QueryTree::addDynamicObject( ParseInfo *node ) { + parseInfoList.push_back( node ); +} + +void QueryTree::removeDynamicObject( ParseInfo *node ) { + parseInfoList.remove( node ); +} + +void QueryTree::addDynamicObject( vector<QtONCStream *> *node ) { + vectorList.push_back( node ); +} + +void QueryTree::removeDynamicObject( vector<QtONCStream*> *node ) { + vectorList.remove( node ); +} + +void QueryTree::releaseDynamicObjects() { + list<QtNode*>::iterator iter1; + for( iter1 = qtNodeList.begin(); iter1 != qtNodeList.end(); iter1++ ) + { + delete *iter1; + *iter1=NULL; + } + + list<QtData*>::iterator iter2; + for( iter2 = qtDataList.begin(); iter2 != qtDataList.end(); iter2++ ) + { + delete *iter2; + *iter2=NULL; + } + + list<ParseInfo*>::iterator iter3; + for( iter3 = parseInfoList.begin(); iter3 != parseInfoList.end(); iter3++ ) + { + delete *iter3; + *iter3=NULL; + } + + list<vector<QtONCStream*>*>::iterator iter4; + for( iter4 = vectorList.begin(); iter4 != vectorList.end(); iter4++ ) + { + delete *iter4; + *iter4=NULL; + } + + list<char *>::iterator iter5; + for( iter5 = lexedCStringList.begin(); iter5 != lexedCStringList.end(); iter5++ ) + { + free(*iter5); + *iter5=NULL; + } +} + +void QueryTree::addDomainObject( QtDomainOperation *dop ) { + dopList.push_back( dop ); +} + +void QueryTree::removeDomainObject( QtDomainOperation *dop ) { + dopList.remove( dop ); +} + +void QueryTree::printDomainObjects() { + list<QtDomainOperation*>::iterator iter; + for( iter = dopList.begin(); iter != dopList.end(); iter++ ) { + cout << endl; + (*iter)->printTree( 2 ); + } +} + +void QueryTree::releaseDomainObjects() { + list<QtDomainOperation*>::iterator iter; + for( iter = dopList.begin(); iter != dopList.end(); iter++ ) + { + delete *iter; + *iter=NULL; + } +} + +void QueryTree::rewriteDomainObjects(r_Minterval *greatDomain, string *greatIterator, QtMarrayOp2::mddIntervalListType *greatList) { + + RMDBGENTER( 2, RMDebug::module_qlparser, "QueryTree", endl << "QueryTree: Iterator: <" << *greatIterator << "> Domain: " << *greatDomain << endl ) + list<QtDomainOperation*>::iterator iter; + + for( iter = dopList.begin(); iter != dopList.end(); iter++ ) { + + // 1. get var name from iter + QtVariable *qtVar = ((QtVariable *)((*iter)->getInput())); + string stVar = qtVar->getIteratorName(); + const char *varname = stVar.c_str(); + + // 2. get position of varname in varList + bool bcond = false; + QtMarrayOp2::mddIntervalListType *varList = greatList; + QtMarrayOp2::mddIntervalListType::iterator varIter; + r_Long varpos = 0; + for (varIter = varList->begin(); varIter != varList->end(); varIter++) { + + if (!strcmp(varname, varIter->variable.c_str())) { + bcond = true; + break; + }; + QtData *data = varIter->tree->evaluate(0); + r_Dimension dimension = ((QtMintervalData*)data)->getMintervalData().dimension(); + varpos = varpos+dimension; + }; + // postcond: bcond == false: varname not found in list. else varpos gives the position. + + if (bcond) { + + // 3. set domain expression to old one incremented by varpos + QtNode::QtOperationList *lop = new QtNode::QtOperationList(1); + (*lop)[0] = + new QtPlus( + (*iter)->getMintervalOp(), + new QtConst( + new QtAtomicData( + varpos, sizeof(varpos) + ) + ) + ); + + (*iter)->setMintervalOp( new QtPointOp( lop ) ); + + // 4. set varname to greatIterator + QtVariable *var1 = new QtVariable( string(*greatIterator) ); + (*iter)->setInput(var1); + + } else + { + // TODO: insert some error notify code here! + RMDBGMIDDLE( 1, RMDebug::module_qlparser, "QueryTree", " variable name not found in list " ) + } + } +} + +void QueryTree::addCString( char *str ) { + lexedCStringList.push_back( str ); +} diff --git a/qlparser/querytree.hh b/qlparser/querytree.hh new file mode 100644 index 0000000..d6f28cc --- /dev/null +++ b/qlparser/querytree.hh @@ -0,0 +1,265 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +#ifndef _QUERYTREE_ +#define _QUERYTREE_ + +#ifndef CPPSTDLIB +#include <ospace/string.h> // STL<ToolKit> +#else +#include <string> +#endif +#include <algorithm> + +#include "mddmgr/mddcoll.hh" + +#include "qlparser/qtnode.hh" +#include "qlparser/qtatomicdata.hh" +#include "qlparser/qtbinaryinduce.hh" +#include "qlparser/qtconst.hh" +#include "qlparser/qtdomainoperation.hh" +#include "qlparser/qtmarrayop2.hh" +#include "qlparser/qtpointop.hh" +#include "qlparser/symtab.hh" + +// forward declarations +class MDDObj; +class QtONCStream; +class QtDomainOperation; + + +/************************************************************* + * + * + * INCLUDE: querytree.hh + * + * MODULE: qlparser + * CLASS: QueryTree + * + * COMMENTS: + * + ************************************************************/ + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + +The Query Tree is the internal representation of a RasML query string. It +consists of instances of the above class hierarchy. The tree is created in +the Query Parser Modul in the action sections of the yacc grammar. According +to the parser semantics, the tree is built bottom up which means that the leaf +objects are created first. They are given up via the parse stack. Inner objects +get references to the subobjects after they are created. The whole tree is a +dynamic data structure. The semantics is that if an object is deleted also its +subobjects are deleted which means that the deletion of the root object cleans +up the whole tree. + +The class QueryTree encapsulates a query tree consisting of suclasses of type +QtNode. It consists of the entry point and methods working on the whole tree +(e.g. traversing). + +*/ + +class QueryTree +{ + public: + + + /// default constructor + QueryTree(); + + /// constructor getting the root of the query tree + QueryTree( QtNode* root ); + + /// destructor (deletes the whole query tree) + ~QueryTree(); + + /// checks semantics (e.g., type checking) + void checkSemantics(); + + /// optimizes the tree + void optimize( unsigned int optimizationLevel ); + + /*@Doc: + The method optimizes the query tree. + */ + + /// recognize common subexpressions + vector<QtNode::QtNodeList>* seeSubexpression(); + + /*@Doc: + The method returns a list of all common subexpressions in the query tree. + The private methods seeSubexpression(..) are used. + */ + + /// build in common subexpressions in the query tree + void insertSubexpression( vector<QtNode::QtNodeList>* nodeList ); + + /*@Doc: + The method manipulates the query tree to handle common subexpressions. + */ + + /// executes a retrieval tree and gives back the result collection + vector<QtData*>* evaluateRetrieval() throw (r_Error, ParseInfo); + + /*@Doc: + The method evaluates a retrieval tree and returns the result collection. For this purpose, + first, the {\tt open()} message is sent to the root node of the tree. Then {\tt next()} + is invoked on the root node which, each time, returns one element of the result + collection. It indicates the end of the evaluation process through returning a null pointer. + At the end, {\tt close()} is called to clean up the ressources. If errors occur, various exceptions + are thrown. + */ + + /// executes an update tree and throws a ParseInfo if query does not begin with INSERT, DELETE, UPDATE, ... + void evaluateUpdate() throw (r_Error,ParseInfo); + + /// debugging method + void printTree( int tab, ostream& s = cout ); + + //@Man: read/write methods + //@{ + /// + + /// + inline QtNode* getRoot() const; + /// + inline void setRoot( QtNode* root ); + /// + inline void setOptimizationLevel( unsigned int level ); + /// + inline unsigned int getOptimizationLevel(); + + /// + //@} + + //@Man: methods used to maintain pointers to dynamic data structures used in the parse process + //@{ + /// + + /// + void addDynamicObject( QtNode* ); + /// + void removeDynamicObject( QtNode* ); + /// + void addDynamicObject( QtData* ); + /// + void removeDynamicObject( QtData* ); + /// + void addDynamicObject( ParseInfo* ); + /// + void removeDynamicObject( ParseInfo* ); + /// + void addDynamicObject( vector<QtONCStream*>* ); + /// + void removeDynamicObject( vector<QtONCStream*>* ); + /// + void releaseDynamicObjects(); + /// + void addDomainObject( QtDomainOperation * ); + /// + void removeDomainObject( QtDomainOperation * ); + /// + void rewriteDomainObjects(r_Minterval *greatDomain, std::string *greatIterator, QtMarrayOp2::mddIntervalListType *greatList); + /// + void printDomainObjects(); + /// + void releaseDomainObjects(); + /// + void addCString( char * ); + /// + //@} + + /// + static SymbolTable<int> symtab; + + private: + /// attribute storing the root of the query tree + QtNode* rootNode; + + static void (*optimizationFnc)(unsigned int, QtNode*); + + /// used by public seeSubexpression() + vector<QtNode::QtNodeList>* seeSubexpression( QtNode::QtNodeList* leafList ); + + /// used by public seeSubexpression() + QtNode::QtNodeList* seeSubexpression( QtNode::QtNodeList* leafList, vector<QtNode::QtNodeList>* leafListsNew ); + + /// level of optimization restricted for this query + unsigned int optimizationLevel; + + /// attribute carrying next free number for CSE iterator + static unsigned int nextCSENo; + + /// list of unlinked subtrees + std::list<QtNode*> qtNodeList; + /** + This list is used to store subtrees of type \Ref{QtNode} generated in the parse + process and not linked to the result tree yet. In case of an error + during the parse process, this list is freed. + */ + + /// list of unlinked subtrees + std::list<QtData*> qtDataList; + /** + This list is used to store subtrees of type \Ref{QtData} generated in the parse + process and not linked to the result tree yet. In case of an error + during the parse process, this list is freed. + */ + + /// list of unlinked subtrees + std::list<ParseInfo*> parseInfoList; + /** + This list is used to store elements of type \Ref{ParseInfo} generated in the parse + process and not linked to the result tree yet. In case of an error + during the parse process, this list is freed. + */ + + /// list of unlinked lists + std::list<vector<QtONCStream*>*> vectorList; + /** + This list is used to store elements of type \Ref{vector<QtONCStream*>} generated + in the parse process and not linked to the result tree yet. In case of an error + during the parse process, this list is freed. + */ + + /// list of domain operations relevant to variables in an MArray. + std::list<QtDomainOperation *> dopList; // contains basically QtDomainOperation (everything else is evil :-) ) + /** + This list is used to store elements of type \Ref{QtDomainOperation *} generated + in the parse process for the purpose of a tree rewrite. In case of an error + during the parse process, this list is freed. + */ + + /// list of lexed c-strings + std::list<char *> lexedCStringList; + /** + This list is used to store elements of type char* generated during the lexing + process and not freed yet. In case of an error this list is freed. + */ + +}; + +#include "querytree.icc" + +#endif + diff --git a/qlparser/querytree.icc b/qlparser/querytree.icc new file mode 100644 index 0000000..251704d --- /dev/null +++ b/qlparser/querytree.icc @@ -0,0 +1,47 @@ +/************************************************************* + * + * Copyright (C) 1996 FORWISS + * + * INLINE SOURCE: querytree.icc + * + * MODULE: qlparser + * CLASS: QueryTree + * + * CHANGE HISTORY (append further entries): + * when who what + * ---------------------------------------------------------- + * 04-09-96 Ritsch created + * 11-08-97 Ritsch merged with version 1.5.1.2 + * + * COMMENTS: + * + ************************************************************/ + +inline QtNode* +QueryTree::getRoot() const +{ + return rootNode; +}; + + +inline void +QueryTree::setRoot( QtNode* root ) +{ + rootNode = root; +}; + + +inline void +QueryTree::setOptimizationLevel( unsigned int level ) +{ + optimizationLevel = level; +}; + + +inline unsigned int +QueryTree::getOptimizationLevel() +{ + return optimizationLevel; +}; + + diff --git a/qlparser/rasml.awk b/qlparser/rasml.awk new file mode 100644 index 0000000..124d6ab --- /dev/null +++ b/qlparser/rasml.awk @@ -0,0 +1,9 @@ +BEGIN { paren = 0; sec = 0 } +/\%\%/ { sec += 1; next; } +sec!=1 { next; } +# /^ *$/ { next; } +/\/\// && !paren { x=$0; sub(/\/\/.*/, "", x); print x; next; } +/{/ { x=$0; sub(/\{.*/, "", x); if(!paren) print x; paren += 1; } +/(\/\*)/ { paren += 1; } +/}|(\*\/)/ { paren -= 1; next; } +!paren { print $0; } diff --git a/qlparser/rasmlgrammar.html b/qlparser/rasmlgrammar.html new file mode 100644 index 0000000..d192d21 --- /dev/null +++ b/qlparser/rasmlgrammar.html @@ -0,0 +1,27 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> +<HTML> +<HEAD> + <TITLE>RasDaMan: Specification</TITLE> + <META NAME="GENERATOR" CONTENT="Mozilla/3.0b6Gold (X11; I; HP-UX B.10.01 9000/770) [Netscape]"> +</HEAD> +<BODY> + +<!-- BASE HREF=http://www.forwiss.tu-muenchen.de/ --> + +<H1><IMG SRC="/public/forwiss/projekte/rasdaman/rmanlogo-s.gif" ALT="[RasDaMan-Logo]" >Implementation +Specification: RasML Grammar</H1> + +<P>The following grammar specifies RasML.</P> + +<PRE> + +<grammar> + +</PRE> + +<P><HR WIDTH="100%"></P> + +<P><A HREF="mailto:ritsch@forwiss.tu-muenchen.de">Roland Ritsch</A>, 1997-09-10</P> + +</BODY> +</HTML>
\ No newline at end of file diff --git a/qlparser/symtab.cc b/qlparser/symtab.cc new file mode 100644 index 0000000..f96e49e --- /dev/null +++ b/qlparser/symtab.cc @@ -0,0 +1,159 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * store symbols (identifiers) during the parse process + * + * + * COMMENTS: + * none + * + ***********************************************************************/ + +//************************************************************** +// Symbol Table class +//************************************************************** + +//************************************************************** +// Implementation +//************************************************************** + +#include "symtab.hh" + +// constructor +template <class T> +SymbolTable<T>::SymbolTable() { + initScope(); + STVars.clear(); +} + +// destructor +template <class T> +SymbolTable<T>::~SymbolTable() { + exitScope(); +} + +// put symbol in keys and in the hash-table +template <class T> +bool SymbolTable<T>::putSymbol(const std::string& symbol, T value) { + bool retVal = false; + // if not locally declared + if ( (STVars.find(symbol) == STVars.end()) ) { + if (getSymbol(symbol) == 0) + keys.push_back(symbol); + STVars[symbol] = value; + retVal = true; + } else + retVal = false; + return retVal; +} + +// store symbol into hash-table +template <class T> +void SymbolTable<T>::storeSymbol( const std::string& symbol, T value ) { + STVars[symbol] = value; +} + +// get symbol from table +template <class T> +T SymbolTable<T>::getSymbol( const std::string& symbol ) { + T retVal=NULL; + + // find if locally declared + if ( !(STVars.find(symbol) == STVars.end()) ) + { + retVal=STVars[symbol]; + } + else + { + // find if declared in outer scopes + size_t idx=STScopes.size(); + while (idx > 0) { + idx--; + if ( !(STScopes[idx].find(symbol) == STScopes[idx].end()) ) + retVal=STScopes[idx][symbol]; + } + } + return retVal; +} + +// lookup symbol in table +template <class T> +bool SymbolTable<T>::lookupSymbol( const std::string& symbol ) { + bool retVal=false; + + // find if locally declared + if ( !(STVars.find(symbol) == STVars.end()) ) + { + retVal=true; + } + else + { + // find if declared in outer scopes + size_t idx = STScopes.size(); + while (idx > 0) { + idx--; + if ( !(STScopes[idx].find(symbol) == STScopes[idx].end()) ) + retVal=true; + } + } + return retVal; +} + +// output the current scope +template <class T> +void SymbolTable<T>::outScope() { + RMInit::logOut << "Scope: " << STScopes.size() << endl; +} + +// init scope by clearing inner symbols +template <class T> +void SymbolTable<T>::clearScope() { + STVars.clear(); +} + +// enter new scope +template <class T> +void SymbolTable<T>::initScope() { + STScopes.push_back(STVars); + STVars.clear(); +} + +// exit current scope to previous one +template <class T> +void SymbolTable<T>::exitScope() { + if (!STScopes.empty()) { + STVars = STScopes[STScopes.size() - 1]; + STScopes.pop_back(); + } +} + +// wipe out everything from symbol table +template <class T> +void SymbolTable<T>::wipe() { + keys.clear(); + STVars.clear(); + STScopes.clear(); +} diff --git a/qlparser/symtab.hh b/qlparser/symtab.hh new file mode 100644 index 0000000..c3e5fba --- /dev/null +++ b/qlparser/symtab.hh @@ -0,0 +1,110 @@ +#ifndef _SYMTAB_HH_ +#define _SYMTAB_HH_ + +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************************* + * + * + * PURPOSE: + * store symbols (identifiers) during the parse process + * + * + * COMMENTS: + * none + * + ***********************************************************************/ + +#include <iostream> +#include <vector> +#include <map> +#include <string> +#include "raslib/rmdebug.hh" + +//@ManMemo: Module: {\bf qlparser} + +/*@Doc: + + This class represents a generic symbol table. The operations on + symbols in the symbol table are: putSymbol, getSymbol, lookupSymbol. + The operations on scopes are: initScope, exitScope, outScope, clearScope, + wipe. + +*/ + +template <class T> +class SymbolTable { +public: + /// This vector stores keys available in the map. + std::vector<std::string > keys; + /// This is an iterator for the vector storing the keys available in the map. + std::vector<std::string >::iterator keyIterator; + + /// default constructor creates an empty symbol table, calls initScope(), clears local symbols. + SymbolTable(); + + /// default destructor, calls exitScope(). + ~SymbolTable(); + + //@Man: Methods for symbol manipulation + //@{ + /// Puts value at position symbol in the table. Returns true if it succeeded, otherwise false. + bool putSymbol( const std::string& symbol, T value ); + /// Get value at position symbol from the table. If symbol doesn't exist, it returns NULL. + T getSymbol( const std::string& symbol ); + /// Returns true if symbol is in table. + bool lookupSymbol( const std::string& symbol ); + //@} + + //@Man: Methods for scope manipulation + //@{ + /// Enter new scope. + void initScope(); + /// Exit current scope. + void exitScope(); + /// Output current scope to RMInit::logOut. + void outScope(); + /// Init scope by clearing inner symbols. + void clearScope(); + /// Clear all symbols in all scopes. + void wipe(); + //@} + +private: + /// Store symbol in map. + void storeSymbol( const std::string& symbol, T value ); // put only in the hash_map + + /// Stores local variables. + std::map<std::string , T> STVars; + + /// Stores scopes. + std::vector<std::map<std::string , T> > STScopes; +}; + +#ifdef EARLY_TEMPLATE +#ifdef __EXECUTABLE__ +#include "symtab.cc" +#endif +#endif + +#endif diff --git a/qlparser/test/Makefile b/qlparser/test/Makefile new file mode 100644 index 0000000..fbf0bff --- /dev/null +++ b/qlparser/test/Makefile @@ -0,0 +1,89 @@ +# -*-Makefile-*- +# +# 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 <http://www.gnu.org/licenses/>. +# +# Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +# rasdaman GmbH. +# +# For more information please see <http://www.rasdaman.org> +# or contact Peter Baumann via <baumann@rasdaman.com>. # Top Level makefile. This points to the various modules that have to be build +# and/or deployed +# +# MAKEFILE FOR: +# test programs of module qlparser +# +# COMMENTS: +# +################################################################## +# +# This is just an example Makefile for a test program. +# The dependency of the test program on the lib of the +# corresponding module is in the Makefile of the module. +# + +######################### Definitions ############################ + +# all test programs +SRCCXX = test_qlparser.cc test_evaluate.cc +OBJS = ${SRCCXX:%.cc=%.o} +ALLTESTS = ${SRCCXX:%.cc=%} +MISCCLEAN := core + +# add compile and link options for STL +CXXFLAGS += $(STLCXXFLAGS) +LDFLAGS += $(STLLDFLAGS) + +########################### Targets ############################## + +# test target for qlparser +.PHONY : qlparser +qlparser: test_module test_qlparser + +.PHONY : evaluate +evaluate: test_module test_evaluate + +.PHONY : test_module +test_module: + cd $(RMANBASE)/qlparser; $(MAKE) + +test_evaluate: test_evaluate.o $(QLPARSER) \ + $(RASLIB) \ + $(CACHETAMGR) \ + $(MDDIF) \ + $(CATALOGIF) \ + $(INDEXIF) \ + $(INDEXMGR) \ + $(BLOBIF) \ + $(ADMINIF) \ + $(CONVERSION) + $(PURIFY) $(CXX) $(LDFLAGS) $(BASEDBLDFLAGS) -o $@ $^ + + +test_qlparser: $(QLPARSER) test_qlparser.o $(RMANHOME)/qlparser/*.o \ + $(QLPARSER) \ + $(RMANHOME)/lib/librasodmg.a \ + $(RASLIB) \ + $(CACHETAMGR) \ + $(MDDIF) \ + $(CATALOGIF) \ + $(INDEXIF) \ + $(INDEXMGR) \ + $(BLOBIF) \ + $(ADMINIF) \ + $(CONVERSION) \ + $(RMANHOME)/rasdl/symbtbl.o + $(PURIFY) $(CXX) $(LDFLAGS) $(BASEDBLDFLAGS) -o $@ $^ + diff --git a/qlparser/test/insertbin.cpp b/qlparser/test/insertbin.cpp new file mode 100644 index 0000000..7779472 --- /dev/null +++ b/qlparser/test/insertbin.cpp @@ -0,0 +1,316 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + * + * + ************************************************************/ + +#define FASTCONNECT +#define DEBUG_MAIN +#define DEBUG +#define __EXECUTABLE__ +#include "debug.hh" +#include "template_inst.hh" + +#define RMANVERSION 6100 +#define RASARCHITECTURE X86 + +extern unsigned long maxTransferBufferSize = 4000000; +bool udfEnabled = true; +extern char* dbSchema = 0; +extern int noTimeOut= 0; + +#include <iostream> // cout +#include <vector> +#include <stdio.h> // fopen, perror +#include <stdlib.h> +#include <string.h> +#include <time.h> + + +#include "qlparser/querytree.hh" +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" + + +#include "adminif.hh" +#include "databaseif.hh" +#include "transactionif.hh" + +#include "mddmgr/mddobj.hh" +#include "mddmgr/mddcoll.hh" +#include "mddmgr/mddcolliter.hh" + +char globalConnectId[256]="RASBASE"; + +// init globals for server initialization + +extern int yyparse(void *); +extern char* myExecArgv0 = ""; +extern int globalOptimizationLevel = 4; +extern char* beginParseString; +extern char* iterParseString; + +extern int RManDebug; +extern int RManInfo = 0; +extern int rewrite = 0; +extern int loadopt = 0; + +extern QueryTree* parseQueryTree; + + +int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex ) +{ + int found = 0; + int i=1; + + while( !found && i<argc ) + found = !strcmp( searchText, argv[i++] ); + + if( found && i<argc && !strchr(argv[i],'-') ) + optionValueIndex = i; + else + optionValueIndex = 0; + + return found; +} + + +int main( int argc, char** argv ) +{ + FILE* inFile; + char baseName[255]; + char query[4096]; + struct timezone tzp; + struct timeval startTime, stopTime, deltaTime; + int timeTest; + int optionValueIndex; + int noOutput; + + if( checkArguments( argc, argv, "-h", optionValueIndex ) ) + { + cout << "Usage: test_evaluate basename queryfile [options]" << endl; + cout << "Options: -h ... this help" << endl; + cout << " -l <file> ... log is printed to <file> (default: server.log)" << endl; + cout << " -l log is printed to standard out" << endl; + cout << " -d <file> ... debug output is printed to <file> (default: server.dbg)" << endl; + cout << " -d debug output is printed to standard out" << endl; + cout << " -dl n ... debug level is set to n (0-4, default: 0)" << endl; + cout << " - 0 = no / 4 = maximal debug information" << endl; + cout << " -opt n ... maximal optimization level (0-4, default: 4)" << endl; + cout << " - 0 = no / 4 = maximal optimization" << endl; + cout << " -t time test is enabled" << endl; + cout << " -nooutput ... no output of result" << endl; + cout << endl; + return 0; + } + + strcpy( baseName, "RASBASE" ); + + inFile = fopen( "query", "r" ); + + if( inFile == NULL ) + { + cout << "Error opening query file " << argv[2] << endl; + return -1; + } + + fread( &query, 1, 4095, inFile ); + fclose( inFile ); + + cout << endl << "Query:" << endl << endl << query << endl; + + // + // open database, start transaction + // + + // variables representing O2 database, ta and session + DatabaseIf db; + TransactionIf ta; + + // don't forget to initialize before using AdminIf! + cout << "Connecting to O2 ..." << flush; + myExecArgv0 = argv[0]; + AdminIf* myAdmin = AdminIf::instance(); + cout << "OK" << endl; + + // connect to the database + cout << "Opening database " << baseName << "... " << flush; + db.open( baseName ); + cout << "OK" << endl; + + cout << "Starting transaction ... " << flush; + ta.begin(&db); + cout << "OK" << endl; + + // + // body of test program + // + + beginParseString = query; + iterParseString = query; + + parseQueryTree = new QueryTree(); // create a query tree object... + + if( timeTest ) + gettimeofday (&startTime, &tzp); + + RMInit::logOut << "Parsing..." << flush; + + if( yyparse(NULL) == 0 ) + { + RMInit::logOut << "OK" << endl << endl; + + parseQueryTree->printTree( 2, RMInit::logOut ); + RMInit::logOut << endl; + + parseQueryTree->getRoot()->printAlgebraicExpression(); + cout << endl << endl; + + unsigned int localOptimizationLevel = globalOptimizationLevel < parseQueryTree->getOptimizationLevel() ? + globalOptimizationLevel : parseQueryTree->getOptimizationLevel(); + + RMInit::logOut << "Optimizing query on level " << localOptimizationLevel << endl; + try + { + parseQueryTree->optimize( localOptimizationLevel ); + } + catch( ParseInfo& info ) + { + RMInit::logOut << endl << "Optimization Error" << endl; + info.printStatus(); + cout << endl; + + return 0; + } + + RMInit::logOut << endl; + parseQueryTree->printTree( 2, RMInit::logOut ); + RMInit::logOut << endl; + parseQueryTree->getRoot()->printAlgebraicExpression( RMInit::logOut ); + RMInit::logOut << endl << endl; + + RMInit::logOut << "Evaluating... " << flush; + + vector<QtData*>* transColl = 0; + + try + { + transColl = parseQueryTree->evaluateRetrieval(); + } + catch( ParseInfo& info ) + { + RMInit::logOut << endl << "Query Execution Error" << endl; + info.printStatus(); + cout << endl; + + return 0; + } + + RMInit::logOut << "OK" << endl << endl; + + if( timeTest ) + { + gettimeofday(&stopTime, &tzp); + + if(startTime.tv_usec > stopTime.tv_usec) { + stopTime.tv_usec += 1000000; + stopTime.tv_sec--; + } + + deltaTime.tv_usec = stopTime.tv_usec - startTime.tv_usec; + deltaTime.tv_sec = stopTime.tv_sec - startTime.tv_sec; + + cout << "Time for query processing " << deltaTime.tv_sec << " sec " << deltaTime.tv_usec << " msec " << endl; + } + + vector<QtData*>::iterator transIter; + int collNum; + collNum = transColl->size(); + + cout << "The result collection has " << collNum << " entries." << endl; + + if( transColl != 0 && !noOutput ) + { + int i; + + for( transIter = transColl->begin(), i=0; transIter != transColl->end(); transIter++, i++ ) + { + QtData* mddObj = *transIter; + + cout << endl << " --" << i << ". MDD object in set:" << endl << " "; + mddObj->printStatus(); + + /*vector<Tile* >* tiles = mddObj->getTiles(); + vector<Tile* >::iterator tileIter; + + for( tileIter = tiles->begin(); tileIter!=tiles->end(); tileIter++ ) + { + cout << endl << " Tile" << endl; + (*tileIter)->printStatus(); + } + + // delete the Tile elements of the vector and the vector itself + // release( tiles->begin(), tiles->end() ); + for( tileIter = tiles->begin(); tileIter!=tiles->end(); tileIter++ ) + delete *tileIter; + + delete tiles;*/ + } + + // release dynamic memory for the collection (delete MDDObjs) + // transColl->eraseAll(); + delete transColl; + + // delete transIter; + }; + + } + else { + RMInit::logOut << " failed" << endl; + printf("Error parsing query\n"); + } + + delete parseQueryTree; + + // + // end of body + // + + cout << "Committing transaction ... " << flush; + ta.commit(); + cout << "OK" << endl; + + cout << "Closing database ..." << flush; + db.close(); + cout << "OK" << endl; + cout << "Ending O2 session ..." << endl; + delete myAdmin; + cout << "OK" << endl; + + return 0; +} diff --git a/qlparser/test/template_inst.hh b/qlparser/test/template_inst.hh new file mode 100644 index 0000000..9ce08ed --- /dev/null +++ b/qlparser/test/template_inst.hh @@ -0,0 +1,152 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +// This version was created based on rview. Let's see if the other programs compile +// also. + +#ifndef _TEMPLATE_INST_RASLIB_ +#define _TEMPLATE_INST_RASLIB_ + +#include <vector> + +#include "qlparser/symtab.hh" + +#include "raslib/attribute.hh" +#include "raslib/itertype.hh" +#include "raslib/dlist.hh" + +#include "tile.hh" + +#include "indexmgr/keyobject.hh" + +#include "reladminif/dbref.hh" +#include "reladminif/dbobjectiditerator.hh" + +#include "relblobif/blobtile.hh" +#include "relblobif/dbtile.hh" +#include "relblobif/inlinetile.hh" + +#include "relcatalogif/typeiterator.hh" +#include "relcatalogif/settype.hh" +#include "relcatalogif/structtype.hh" +#include "relcatalogif/mddtype.hh" +#include "relcatalogif/inlineminterval.hh" +#include "relcatalogif/dbminterval.hh" + +#include "relindexif/dbtcindex.hh" +#include "relindexif/hierindex.hh" +#include "relindexif/dbrcindexds.hh" + +#include "relmddif/dbmddobj.hh" +#include "relmddif/dbmddset.hh" + +#include "relstorageif/dbudfds.hh" +#include "relstorageif/dbudfpackageds.hh" +#include "relstorageif/dbstoragelayout.hh" + + +#include <qlparser/symtab.hh> +#include <raslib/attribute.hh> +#include <raslib/itertype.hh> +#include <raslib/dlist.hh> +#include <raslib/minterval.hh> + + +#include "reladminif/dbref.hh" +#include "reladminif/dbobjectiditerator.hh" + +#include "relindexif/dbtcindex.hh" +#include "relindexif/hierindex.hh" +#include "relindexif/dbrcindexds.hh" + + +template class DBRef<DBHierIndex>; +template class DBRef<DBRCIndexDS>; +template class DBRef<DBTCIndex>; +template class DBRef<BLOBTile>; +template class DBRef<DBTile>; +template class DBRef<InlineTile>; +template class DBRef<DBMDDSet>; +template class DBRef<DBMinterval>; +template class DBRef<DBStorageLayout>; +template class DBRef<DBUDFDS>; +template class DBRef<DBUDFPackageDS>; +template bool operator< (const DBRef<DBMDDObj>&, const DBRef<DBMDDObj>&); + + +#include <rasodmg/tiling.hh> +#include <rasodmg/stattiling.hh> +#include <rasodmg/iterator.hh> +#include <rasodmg/transaction.hh> +#include <rasodmg/ref.hh> +#include <rasodmg/object.hh> +#include <rasodmg/set.hh> +#include <rasodmg/collection.hh> +#include <rasodmg/gmarray.hh> +#include <rasodmg/marray.hh> +#include <rasodmg/dirdecompose.hh> + +template class r_Ref<r_Object>; +template class r_Ref<r_Minterval>; +template class r_Collection<r_Transaction::GenRefElement *>; +template class r_Set<r_Transaction::GenRefElement *>; +template class r_Iterator<r_GMarray *>; +template class r_Iterator<r_Ref<r_GMarray > >; +template class r_Collection<r_Ref<r_GMarray> >; +template class r_Collection<r_GMarray *>; +template class r_Set<r_GMarray *>; +template class r_Iterator<r_Ref<r_Object> >; +template class r_IterType<r_Attribute>; +template class r_Collection<r_Ref<r_Object> >; +template class r_Set<r_Ref<r_Object> >; +template class r_Iterator<r_Ref_Any>; +template class r_Ref<r_GMarray>; +template class r_Collection<r_Ref_Any>; +template class std::vector<r_Minterval>; +template class r_Iterator<r_Transaction::GenRefElement *>; +template class r_Set<r_Ref<r_GMarray> >; +template class r_Ref<r_Set<r_Ref<r_GMarray> > >; +template class r_Set<r_Ref_Any>; +template class r_Marray<r_ULong>; +template class r_Marray<r_Char>; + +template class DBRef<DBMDDObj>; +template class DBRef<DBObject>; + +template class DBObjectIdIterator<DBMDDObj>; +template class DBObjectIterator<DBMDDObj>; +template class DBObjectIterator<DBMDDSet>; +template class DBObjectIterator<StructType>; +template class DBObjectIterator<SetType>; +template class DBObjectIterator<MDDType>; +template class DBRef<StructType>; +template class DBRef<SetType>; +template class DBRef<MDDType>; + + +template std::ostream& operator << (std::ostream& os, const std::vector<r_Minterval>& list); +template std::ostream& operator << (std::ostream& os, const std::vector<r_Dir_Decompose>& list); +template std::ostream& operator << (std::ostream& os, const std::vector<r_Access>& list); +template std::ostream& operator << (std::ostream& os, const std::vector<double>& list); +template class SymbolTable<int>; + +#endif diff --git a/qlparser/test/test_evaluate.cc b/qlparser/test/test_evaluate.cc new file mode 100644 index 0000000..b34ce9d --- /dev/null +++ b/qlparser/test/test_evaluate.cc @@ -0,0 +1,338 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * COMMENTS: + * + * + * + ************************************************************/ + +#include <iostream.h> // cout +#include <stdio.h> // fopen, perror +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "qlparser/querytree.hh" +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" + +#include "adminif.hh" +#include "databaseif.hh" +#include "transactionif.hh" + +#include "mddmgr/mddobj.hh" +#include "mddmgr/mddcoll.hh" +#include "mddmgr/mddcolliter.hh" + +// init globals for server initialization +RMINITGLOBALS('S') + +extern int yyparse(); +extern char* myExecArgv0 = ""; +extern int globalOptimizationLevel = 4; +extern char* beginParseString; +extern char* iterParseString; + +extern int RManDebug; +extern int RManInfo = 0; +extern int rewrite = 0; +extern int loadopt = 0; + +extern QueryTree* parseQueryTree; + + +int checkArguments( int argc, char** argv, const char* searchText, int& optionValueIndex ) +{ + int found = 0; + int i=1; + + while( !found && i<argc ) + found = !strcmp( searchText, argv[i++] ); + + if( found && i<argc && !strchr(argv[i],'-') ) + optionValueIndex = i; + else + optionValueIndex = 0; + + return found; +} + + +int main( int argc, char** argv ) +{ + FILE* inFile; + char baseName[255]; + char query[4096]; + struct timezone tzp; + struct timeval startTime, stopTime, deltaTime; + int timeTest; + int optionValueIndex; + int noOutput; + + if( checkArguments( argc, argv, "-h", optionValueIndex ) ) + { + cout << "Usage: test_evaluate basename queryfile [options]" << endl; + cout << "Options: -h ... this help" << endl; + cout << " -l <file> ... log is printed to <file> (default: server.log)" << endl; + cout << " -l log is printed to standard out" << endl; + cout << " -d <file> ... debug output is printed to <file> (default: server.dbg)" << endl; + cout << " -d debug output is printed to standard out" << endl; + cout << " -dl n ... debug level is set to n (0-4, default: 0)" << endl; + cout << " - 0 = no / 4 = maximal debug information" << endl; + cout << " -opt n ... maximal optimization level (0-4, default: 4)" << endl; + cout << " - 0 = no / 4 = maximal optimization" << endl; + cout << " -t time test is enabled" << endl; + cout << " -nooutput ... no output of result" << endl; + cout << endl; + return 0; + } + + strcpy( baseName, argv[1] ); + + if( checkArguments( argc, argv, "-l", optionValueIndex ) ) + if( optionValueIndex ) + { + RMInit::logFileOut.open( argv[optionValueIndex] ); + // RMInit::logOut = RMInit::logFileOut; + } + else { + // RMInit::logOut = cout.rdbuf(); + } + else + { + // default + RMInit::logFileOut.open("server.log"); + // RMInit::logOut = RMInit::logFileOut; + } + + if( checkArguments( argc, argv, "-d", optionValueIndex ) ) + if( optionValueIndex ) + { + RMInit::dbgFileOut.open( argv[optionValueIndex] ); + // RMInit::dbgOut = RMInit::dbgFileOut; + } + else { + // RMInit::logOut = cout.rdbuf(); + } + else + { + // default + RMInit::dbgFileOut.open("server.dbg"); + // RMInit::dbgOut = RMInit::dbgFileOut; + } + + if( checkArguments( argc, argv, "-dl", optionValueIndex ) ) + if( optionValueIndex ) + RManDebug = (int)strtoul( argv[optionValueIndex], (char **)NULL, 10); + + if( checkArguments( argc, argv, "-opt", optionValueIndex ) ) + if( optionValueIndex ) + globalOptimizationLevel = (int)strtoul( argv[optionValueIndex], (char **)NULL, 10); + + timeTest = checkArguments( argc, argv, "-t", optionValueIndex ); + noOutput = checkArguments( argc, argv, "-nooutput", optionValueIndex ); + + inFile = fopen( argv[2], "r" ); + + if( inFile == NULL ) + { + cout << "Error opening query file " << argv[2] << endl; + return -1; + } + + fread( &query, 1, 4095, inFile ); + fclose( inFile ); + + cout << endl << "Query:" << endl << endl << query << endl; + + // + // open database, start transaction + // + + // variables representing O2 database, ta and session + DatabaseIf db; + TransactionIf ta; + + // don't forget to initialize before using AdminIf! + cout << "Connecting to O2 ..." << flush; + myExecArgv0 = argv[0]; + AdminIf* myAdmin = AdminIf::instance(); + cout << "OK" << endl; + + // connect to the database + cout << "Opening database " << baseName << "... " << flush; + db.open( baseName ); + cout << "OK" << endl; + + cout << "Starting transaction ... " << flush; + ta.begin(&db); + cout << "OK" << endl; + + // + // body of test program + // + + beginParseString = query; + iterParseString = query; + + parseQueryTree = new QueryTree(); // create a query tree object... + + if( timeTest ) + gettimeofday (&startTime, &tzp); + + RMInit::logOut << "Parsing..." << flush; + + if( yyparse() == 0 ) + { + RMInit::logOut << "OK" << endl << endl; + + parseQueryTree->printTree( 2, RMInit::logOut ); + RMInit::logOut << endl; + + parseQueryTree->getRoot()->printAlgebraicExpression(); + cout << endl << endl; + + unsigned int localOptimizationLevel = globalOptimizationLevel < parseQueryTree->getOptimizationLevel() ? + globalOptimizationLevel : parseQueryTree->getOptimizationLevel(); + + RMInit::logOut << "Optimizing query on level " << localOptimizationLevel << endl; + try + { + parseQueryTree->optimize( localOptimizationLevel ); + } + catch( ParseInfo& info ) + { + RMInit::logOut << endl << "Optimization Error" << endl; + info.printStatus(); + cout << endl; + + return 0; + } + + RMInit::logOut << endl; + parseQueryTree->printTree( 2, RMInit::logOut ); + RMInit::logOut << endl; + parseQueryTree->getRoot()->printAlgebraicExpression( RMInit::logOut ); + RMInit::logOut << endl << endl; + + RMInit::logOut << "Evaluating... " << flush; + + vector<QtData*>* transColl = 0; + + try + { + transColl = parseQueryTree->evaluateRetrieval(); + } + catch( ParseInfo& info ) + { + RMInit::logOut << endl << "Query Execution Error" << endl; + info.printStatus(); + cout << endl; + + return 0; + } + + RMInit::logOut << "OK" << endl << endl; + + if( timeTest ) + { + gettimeofday(&stopTime, &tzp); + + if(startTime.tv_usec > stopTime.tv_usec) { + stopTime.tv_usec += 1000000; + stopTime.tv_sec--; + } + + deltaTime.tv_usec = stopTime.tv_usec - startTime.tv_usec; + deltaTime.tv_sec = stopTime.tv_sec - startTime.tv_sec; + + cout << "Time for query processing " << deltaTime.tv_sec << " sec " << deltaTime.tv_usec << " msec " << endl; + } + + vector<QtData*>::iterator transIter; + int collNum; + collNum = transColl->size(); + + cout << "The result collection has " << collNum << " entries." << endl; + + if( transColl != 0 && !noOutput ) + { + int i; + + for( transIter = transColl->begin(), i=0; transIter != transColl->end(); transIter++, i++ ) + { + QtData* mddObj = *transIter; + + cout << endl << " --" << i << ". MDD object in set:" << endl << " "; + mddObj->printStatus(); + + /*vector<Tile* >* tiles = mddObj->getTiles(); + vector<Tile* >::iterator tileIter; + + for( tileIter = tiles->begin(); tileIter!=tiles->end(); tileIter++ ) + { + cout << endl << " Tile" << endl; + (*tileIter)->printStatus(); + } + + // delete the Tile elements of the vector and the vector itself + // release( tiles->begin(), tiles->end() ); + for( tileIter = tiles->begin(); tileIter!=tiles->end(); tileIter++ ) + delete *tileIter; + + delete tiles;*/ + } + + // release dynamic memory for the collection (delete MDDObjs) + // transColl->eraseAll(); + delete transColl; + + // delete transIter; + }; + + } + else + RMInit::logOut << " failed" << endl; + + delete parseQueryTree; + + // + // end of body + // + + cout << "Committing transaction ... " << flush; + ta.commit(); + cout << "OK" << endl; + + cout << "Closing database ..." << flush; + db.close(); + cout << "OK" << endl; + cout << "Ending O2 session ..." << endl; + delete myAdmin; + cout << "OK" << endl; + + return 0; +} diff --git a/qlparser/test/test_qlparser.cc b/qlparser/test/test_qlparser.cc new file mode 100644 index 0000000..7753f2c --- /dev/null +++ b/qlparser/test/test_qlparser.cc @@ -0,0 +1,205 @@ +/* +* 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 <http://www.gnu.org/licenses/>. +* +* Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann / +rasdaman GmbH. +* +* For more information please see <http://www.rasdaman.org> +* or contact Peter Baumann via <baumann@rasdaman.com>. +*/ +/************************************************************* + * + * + * PURPOSE: + * Test program for the RasQL parser. + * + * + * COMMENTS: + * + * + ************************************************************/ + +#ifdef EARLY_TEMPLATE +#define __EXECUTABLE__ +#ifdef __GNUG__ +#include "qlparser/symtab.hh" +#include "raslib/template_inst.hh" +#endif +#endif + + +using namespace std; + +#define DEBUG_MAIN +#include "debug-clt.hh" + + +#include <iostream.h> // cout +#include <stdio.h> // fopen, perror +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "qlparser/querytree.hh" + +#include "raslib/rminit.hh" +#include "raslib/rmdebug.hh" + +#include "adminif.hh" +#include "databaseif.hh" +#include "transactionif.hh" + +#include "mddmgr/mddobj.hh" +#include "mddmgr/mddcoll.hh" +#include "mddmgr/mddcolliter.hh" + +// init globals for server initialization +// RMINITGLOBALS('C') + +extern int yyparse(); +extern char* myExecArgv0 = ""; +extern char* beginParseString; +extern char* iterParseString; + +extern QueryTree* parseQueryTree; + +int main( int ac, char** av ) +{ + FILE* inFile; + char baseName[255]; + char query[4096]; + + // + // read program arguments + // + + if( ac <= 2 ) + { + cout << "usage: test_qlparser basename queryfile" << endl; + return -1; + } + + strcpy( baseName, av[1] ); + + inFile = fopen( av[2], "r" ); + + if( inFile == NULL ) + { + cout << "Error opening file " << av[1] << endl; + return -1; + } + + fread( &query, 1, 4095, inFile ); + fclose( inFile ); + + cout << "Query:" << endl << endl << query << endl; + + // + // open database, start transaction + // + + // variables representing O2 database, ta and session + DatabaseIf db; + TransactionIf ta; + + // don't forget to initialize before using AdminIf! + cout << "Connecting to O2 ..." << flush; + myExecArgv0 = av[0]; + AdminIf* myAdmin = AdminIf::instance(); + cout << "OK" << endl; + + // connect to the database + cout << "Opening database " << baseName << "... " << flush; + db.open( baseName ); + cout << "OK" << endl; + + cout << "Starting transaction ... " << flush; + ta.begin(&db); + cout << "OK" << endl; + + // + // body of test program + // + + beginParseString = query; + iterParseString = query; + + parseQueryTree = new QueryTree(); // create a query tree object... + + cout << endl << "Parsing ..." << flush; + + if( !yyparse() ) + cout << " worked" << endl; + else + cout << " failed" << endl; + + cout << endl; + parseQueryTree->printTree(2); + cout << endl; + parseQueryTree->getRoot()->printAlgebraicExpression(); + cout << endl; + + cout << "Simplifying ..." << flush; + try + { + parseQueryTree->getRoot()->simplify(); + } + catch( ParseInfo& info ) + { + info.printStatus( RMInit::logOut ); + cout << "FAILED" << endl; + } + + cout << "OK" << endl; + + cout << endl; + parseQueryTree->printTree(2); + cout << endl; + parseQueryTree->getRoot()->printAlgebraicExpression(); + cout << endl; + + delete parseQueryTree; + + // + // end of body + // + + cout << "Committing transaction ... " << flush; + ta.commit(); + cout << "OK" << endl; + + cout << "Closing database ..." << flush; + db.close(); + cout << "OK" << endl; + cout << "Ending O2 session ..." << endl; + delete myAdmin; + cout << "OK" << endl; + + return 0; +} + + + + + + + + + + + + + |