• Main Page
  • Modules
  • Namespaces
  • Classes
  • Files

qExpr.h

Go to the documentation of this file.
00001 // File: $Id$
00002 // Author: John Wu <John.Wu at nersc.gov>
00003 //      Lawrence Berkeley National Laboratory
00004 // Copyright 1998-2008 the Regents of the University of California
00005 //
00006 // Primary contact: John Wu <John.Wu at nersc.gov>
00007 #ifndef IBIS_EXPR_H
00008 #define IBIS_EXPR_H
00012 #include "util.h"
00013 #include <functional>   // std::less, std::binary_function<>
00014 
00015 namespace ibis { // additional names related to qExpr
00016     class qRange;       
00017     class qContinuousRange;
00018     class qDiscreteRange;       
00019     class qString;      
00020     class qMultiString; 
00021     class compRange;    
00022     class rangeJoin;    
00023     class qAnyAny;      
00024 }
00025 
00029 class ibis::qExpr {
00030 public:
00033     enum TYPE {
00034         LOGICAL_UNDEFINED, LOGICAL_NOT, LOGICAL_AND, LOGICAL_OR, LOGICAL_XOR,
00035         LOGICAL_MINUS, RANGE, DRANGE, STRING, MSTRING, COMPRANGE, MATHTERM,
00036         JOIN, TOPK, ANYANY
00037     };
00039     enum COMPARE {
00040         OP_UNDEFINED, OP_LT, OP_GT, OP_LE, OP_GE, OP_EQ
00041     };
00042 
00044     qExpr() : type(LOGICAL_UNDEFINED), left(0), right(0) {}
00045 
00047     explicit qExpr(TYPE op) : type(op), left(0), right(0) {}
00049     qExpr(TYPE op, qExpr* qe1, qExpr* qe2) : type(op), left(qe1),
00050                                              right(qe2) {}
00052     qExpr(const qExpr& qe) : type(qe.type),
00053                              left(qe.left ? qe.left->dup() : 0),
00054                              right(qe.right ? qe.right->dup() : 0) {}
00056     virtual ~qExpr() {delete right; delete left;}
00057 
00059     void setLeft(qExpr *expr) {delete left; left=expr;}
00061     void setRight(qExpr *expr) {delete right; right=expr;}
00063     qExpr*& getLeft() {return left;}
00065     qExpr*& getRight() {return right;}
00066 
00068     TYPE getType() const {return type;}
00070     const qExpr* getLeft() const {return left;}
00072     const qExpr* getRight() const {return right;}
00073 
00075     bool hasJoin() const;
00076 
00078     virtual void print(std::ostream&) const;
00079 
00082     virtual void printRange(std::ostream& out) const {
00083         if (left) left->printRange(out);
00084         if (right) right->printRange(out);
00085     };
00086 
00088     struct weight {
00089         virtual double operator()(const qExpr* ex) const = 0;
00090         virtual ~weight() {};
00091     };
00092     double reorder(const weight&); 
00093     // Duplicate this query expression.  Return the pointer to the new object.
00094     virtual qExpr* dup() const {
00095         qExpr* res = new qExpr(type);
00096         if (left)
00097             res->left = left->dup();
00098         if (right)
00099             res->right = right->dup();
00100         return res;
00101     }
00102 
00103     bool isTerminal() const {return (left==0 && right==0);}
00104     bool directEval() const
00105     {return (type==RANGE || type==STRING || type==COMPRANGE ||
00106              type==DRANGE || type==MSTRING || type==ANYANY ||
00107              (type==LOGICAL_NOT && left && left->directEval()));}
00108 
00111     virtual bool isSimple() const {
00112         if (left) {
00113             if (right) return left->isSimple() && right->isSimple();
00114             else return left->isSimple();
00115         }
00116         else if (right) {
00117             return right->isSimple();
00118         }
00119         else { // the derived classes essentially overrides this case.
00120             return true;
00121         }
00122     }
00123 
00127     int separateSimple(ibis::qExpr *&simple, ibis::qExpr *&tail) const;
00128 
00130     void extractJoins(std::vector<const rangeJoin*>& terms) const;
00132     qRange* findRange(const char* vname);
00133 
00137     static void simplify(ibis::qExpr*&);
00138 
00139     const qExpr& operator=(const qExpr& rhs) {
00140         delete left; delete right;
00141         type = rhs.type;
00142         left = (rhs.left != 0 ? rhs.left->dup() : 0);
00143         right = (rhs.right != 0 ? rhs.right->dup() : 0);
00144         return *this;
00145     }
00146 
00147 private:
00148     TYPE   type;        // the type of node, logical operator, type of leaf
00149     qExpr* left;        // the left child
00150     qExpr* right;       // the right child
00151 
00152     // adjust the tree to favor the sequential evaluation order
00153     void adjust();
00154 }; // ibis::qExpr
00155 
00160 class ibis::qRange : public ibis::qExpr {
00161 public:
00163     virtual const char* colName() const = 0;
00166     virtual bool inRange(double val) const = 0;
00167 
00169     virtual void restrictRange(double left, double right) = 0;
00171     virtual const double& leftBound() const = 0;
00173     virtual const double& rightBound() const = 0;
00175     virtual bool empty() const = 0;
00176 
00177     virtual ~qRange() {}; // nothing to do
00178 
00179 protected:
00180     // reduce the scope of the constructor
00181     qRange() : qExpr(RANGE) {};
00182     qRange(TYPE t) : qExpr(t) {};
00183 
00184 private:
00185     qRange(const qRange&) {}; // no copy constructor allowed, must use dup
00186     const qRange& operator=(const qRange&);
00187 }; // ibis::qRange
00188 
00204 class ibis::qContinuousRange : public ibis::qRange {
00205 public:
00207     qContinuousRange() : name(0), lower(0), upper(0), left_op(OP_UNDEFINED),
00208                          right_op(OP_UNDEFINED) {};
00210     qContinuousRange(const char* lstr, COMPARE lop, const char* prop,
00211                      COMPARE rop, const char* rstr);
00213     qContinuousRange(const char* col, COMPARE op, uint32_t val) :
00214         name(ibis::util::strnewdup(col)), lower(val),
00215         upper(DBL_MAX), left_op(op), right_op(OP_UNDEFINED) {};
00217     qContinuousRange(const qContinuousRange& rhs) :
00218         name(ibis::util::strnewdup(rhs.name)), lower(rhs.lower),
00219         upper(rhs.upper), left_op(rhs.left_op), right_op(rhs.right_op) {};
00221     qContinuousRange(double lv, COMPARE lop, const char* prop,
00222                      COMPARE rop, double rv)
00223         : name(ibis::util::strnewdup(prop)), lower(lv),
00224           upper(rv), left_op(lop), right_op(rop) {};
00226     qContinuousRange(const char* prop, COMPARE op, double val)
00227         : name(ibis::util::strnewdup(prop)), lower(-DBL_MAX),
00228           upper(val), left_op(OP_UNDEFINED), right_op(op) {
00229         // prefer to use the operator < and <= rather than > and >=
00230         if (right_op == ibis::qExpr::OP_GT) {
00231             right_op = ibis::qExpr::OP_UNDEFINED;
00232             left_op = ibis::qExpr::OP_LT;
00233             lower = upper;
00234             upper = DBL_MAX;
00235         }
00236         else if (right_op == ibis::qExpr::OP_GE) {
00237             right_op = ibis::qExpr::OP_UNDEFINED;
00238             left_op = ibis::qExpr::OP_LE;
00239             lower = upper;
00240             upper = DBL_MAX;
00241         }
00242     };
00243 
00244     virtual ~qContinuousRange() {delete [] name;}
00245 
00246     // provide read access to all private variables
00247     virtual const char *colName() const {return name;}
00248     COMPARE leftOperator() const {return left_op;}
00249     COMPARE rightOperator() const {return right_op;}
00250     virtual const double& leftBound() const {
00251         return (right_op != OP_EQ ? lower : upper);}
00252     virtual const double& rightBound() const {
00253         return (left_op != OP_EQ ? upper : lower);}
00254     // allow one to possibly change the left and right bounds, the left and
00255     // right operator
00256     double& leftBound() {return lower;}
00257     double& rightBound() {return upper;}
00258     COMPARE& leftOperator() {return left_op;}
00259     COMPARE& rightOperator() {return right_op;}
00260 
00261     // Fold the boundaries to integers.
00262     void foldBoundaries();
00263     // Fold the boundaries to unsigned integers.
00264     void foldUnsignedBoundaries();
00265 
00266     // duplicate *this
00267     virtual qContinuousRange* dup() const {return new qContinuousRange(*this);}
00268     // is val in the specified range
00269     inline virtual bool inRange(double val) const;
00270     virtual void restrictRange(double left, double right);
00271     virtual bool empty() const;
00272 
00273     // print the query expression
00274     virtual void print(std::ostream&) const;
00275     virtual void printRange(std::ostream& out) const;
00276     // an operator for comparing two query expressions
00277     inline bool operator<(const qContinuousRange& y) const;
00278 
00279 private:
00280     char* name;
00281     double lower, upper;
00282     COMPARE left_op, right_op;
00283 
00284     const qContinuousRange& operator=(const qContinuousRange&);
00285     friend void ibis::qExpr::simplify(ibis::qExpr*&);
00286 }; // ibis::qContinuousRange
00287 
00290 class ibis::qDiscreteRange : public ibis::qRange {
00291 public:
00293     qDiscreteRange() : qRange(DRANGE) {};
00295     qDiscreteRange(const char *col, const char *nums);
00298     qDiscreteRange(const char *col, const std::vector<uint32_t>& val);
00301     qDiscreteRange(const char *col, const std::vector<double>& val);
00302 
00304     qDiscreteRange(const qDiscreteRange& dr)
00305         : qRange(DRANGE), name(dr.name), values(dr.values) {}
00306     virtual ~qDiscreteRange() {}; // private variables automatically destructs
00307 
00308     // main access functions
00309     virtual const char* colName() const {return name.c_str();}
00310     const std::vector<double>& getValues() const {return values;}
00311     std::vector<double>& getValues() {return values;}
00312 
00314     virtual qDiscreteRange* dup() const {return new qDiscreteRange(*this);}
00316     inline virtual bool inRange(double val) const;
00317     virtual void restrictRange(double left, double right);
00318     virtual bool empty() const {return values.empty();}
00319     virtual const double& leftBound() const {return values.front();}
00320     virtual const double& rightBound() const {return values.back();}
00321 
00323     ibis::qExpr* convert() const;
00324 
00325     virtual void print(std::ostream& out) const;
00326     virtual void printRange(std::ostream& out) const;
00327 
00328 private:
00329     std::string name;
00330     std::vector<double> values; 
00331 
00332     const qDiscreteRange& operator=(const qDiscreteRange&);
00333 }; // ibis::qDiscreteRange
00334 
00345 class ibis::qString : public ibis::qExpr {
00346 public:
00347     // construct the qString from two strings
00348     qString() : lstr(0), rstr(0) {};
00349     qString(const char* ls, const char* rs);
00350     virtual ~qString() {delete [] rstr; delete [] lstr;}
00351 
00352     const char* leftString() const {return lstr;}
00353     const char* rightString() const {return rstr;}
00354 
00355     virtual qString* dup() const {return new qString(*this);}
00356     virtual void print(std::ostream&) const;
00357 
00358 private:
00359     char* lstr;
00360     char* rstr;
00361 
00362     qString(const qString& rhs) : qExpr(STRING),
00363                                   lstr(ibis::util::strnewdup(rhs.lstr)),
00364                                   rstr(ibis::util::strnewdup(rhs.rstr)) {}
00365     const qString& operator=(const qString&);
00366 }; // ibis::qString
00367 
00368 // A data structure to hold the string-valued version of the IN expression,
00369 // name IN ('aaa', 'bbb', ...).
00370 class ibis::qMultiString : public ibis::qExpr {
00371 public:
00372     qMultiString() : qExpr(MSTRING) {};
00373     qMultiString(const char *col, const char *sval);
00374     virtual ~qMultiString() {}; // name and values automatically destroyed
00375 
00377     virtual qMultiString* dup() const {return new qMultiString(*this);}
00378     virtual void print(std::ostream& out) const;
00379 
00381     const char* colName() const {return name.c_str();}
00383     const std::vector<std::string>& valueList() const {return values;}
00385     ibis::qExpr* convert() const;
00386 
00387 private:
00388     std::string name;
00389     std::vector<std::string> values;
00390 }; // ibis::qMultiString
00391 
00394 class ibis::compRange : public ibis::qExpr {
00395 public:
00396     // types of terms allowed in the mathematical expression
00397     enum TERM_TYPE {UNDEFINED, VARIABLE, NUMBER, STRING, OPERATOR,
00398                     STDFUNCTION1, STDFUNCTION2,
00399                     CUSTOMFUNCTION1, CUSTOMFUNCTION2};
00400     // all arithmetic operators (operador is Spainish for operator)
00401     enum OPERADOR {UNKNOWN=0, BITOR, BITAND,
00402                    PLUS, MINUS, MULTIPLY, DIVIDE, REMAINDER, NEGATE, POWER};
00403     // list standard 1-argument and 2-argument functions
00404     enum STDFUN1 {ACOS=0, ASIN, ATAN, CEIL, COS, COSH, EXP, FABS, FLOOR,
00405                   FREXP, LOG10, LOG, MODF, SIN, SINH, SQRT, TAN, TANH};
00406     enum STDFUN2 {ATAN2=0, FMOD, LDEXP, POW};
00407 
00408     static char* operator_name[];
00409     static char* stdfun1_name[];
00410     static char* stdfun2_name[];
00411 
00412     class term;
00413     class variable;
00414     class bediener;
00416     class barrel {
00417     public:
00418         // public member functions
00419         barrel() {};
00420         barrel(const term* const t) {recordVariable(t);}
00421         virtual ~barrel() {}; // member variables clean themselves
00422 
00423         // access functions to the names and values
00424         uint32_t size() const {return varmap.size();}
00425         const char* name(uint32_t i) const {return namelist[i];}
00426         const double& value(uint32_t i) const {return varvalues[i];}
00427         double& value(uint32_t i) {return varvalues[i];}
00428 
00430         void recordVariable(const term* const t);
00434         inline uint32_t recordVariable(const char* name);
00436         bool equivalent(const barrel& rhs) const;
00437 
00438     protected:
00439         // the data structure to store the variable names in a mathematical
00440         // expression
00441         typedef std::map< const char*, uint32_t, ibis::lessi > termMap;
00442 
00443         // functions used by the class variable for accessing values of the
00444         // variables
00445         friend class variable;
00446         double getValue(uint32_t i) const {return varvalues[i];}
00448         double getValue(const char* nm) const {
00449             termMap::const_iterator it = varmap.find(nm);
00450             if (it != varmap.end()) {
00451                 uint32_t i = (*it).second;
00452                 return varvalues[i];
00453             }
00454             else {
00455                 return DBL_MAX;
00456             }
00457         }
00458 
00461         termMap varmap;
00462         std::vector< double > varvalues; 
00463         std::vector< const char* > namelist; 
00464     }; // class barrel
00465 
00467     class term : public ibis::qExpr { // abstract term class
00468     public:
00469         virtual ~term() {};
00470 
00471         virtual TERM_TYPE termType() const = 0;
00472 
00473         // Evaluate the term.
00474         virtual double eval() const = 0;
00475         // Make a duplicate copy of the term.
00476         virtual term* dup() const = 0;
00477         // Print a human readable version of the expression.
00478         virtual void print(std::ostream& out) const = 0;
00479         // Shorten the expression by evaluating the constants.  Return a
00480         // new pointer if the expression is changed, otherwise return the
00481         // pointer this.
00482         virtual term* reduce() {return this;};
00483 
00484     protected:
00485         term() : qExpr(MATHTERM) {}; // to be used by concrete derived classes
00486     }; // abstract term
00487 
00489     class variable : public term {
00490     public:
00491         // The constructor inserts the variable name to a list in expr and
00492         // record the position in private member variable (that is used
00493         // later to retrieve value from expr class).
00494         variable(const char* var)
00495             : name(ibis::util::strnewdup(var)), myBar(0), varind(0) {}
00496         variable(const variable& v)
00497             : name(ibis::util::strnewdup(v.name)), myBar(v.myBar),
00498               varind(v.varind) {}
00499         virtual ~variable() {delete [] name;}
00500 
00501         virtual TERM_TYPE termType() const {return VARIABLE;}
00502         virtual variable* dup() const {return new variable(*this);}
00503         virtual double eval() const {return myBar->getValue(varind);}
00504         virtual void print(std::ostream& out) const {out << name;}
00505         const char* variableName() const {return name;}
00506 
00507         void recordVariable(barrel& bar) const {
00508             varind = bar.recordVariable(name);
00509             myBar = &bar;
00510         }
00511 
00512     private:
00513         char* name;     // the variable name
00514         mutable barrel* myBar;  // the barrel containing this variable
00515         mutable uint32_t varind;// the token to retrieve value from myBar
00516 
00517         const variable& operator=(const variable&);
00518     }; // the variable term
00519 
00521     class number : public term {
00522     public:
00523         number(const char* num) : val(atof(num)) {};
00524         number(double v) : val(v) {};
00525         virtual ~number() {};
00526 
00527         virtual TERM_TYPE termType() const {return NUMBER;}
00528         virtual number* dup() const {return new number(val);}
00529         virtual double eval() const {return val;}
00530         virtual void print(std::ostream& out) const {out << val;}
00531 
00532         // to negate the value
00533         void negate() {val = -val;}
00534         // to invert the value
00535         void invert() {val = 1.0/val;}
00536 
00537     private:
00538         double val;
00539         friend class bediener;
00540         friend void ibis::qExpr::simplify(ibis::qExpr*&);
00541     }; // number
00542 
00544     class literal : public term {
00545     public:
00546         literal(const char* s) : str(ibis::util::strnewdup(s)) {};
00547         virtual ~literal() {delete [] str;}
00548 
00549         virtual TERM_TYPE termType() const {return ibis::compRange::STRING;}
00550         virtual literal* dup() const {return new literal(str);}
00551         virtual double eval() const {return 0.0;}
00552         virtual void print(std::ostream& out) const {out << str;}
00553 
00554     private:
00555         char* str;
00556 
00557         literal(const literal&);
00558         const literal& operator=(const literal&);
00559     }; // literal
00560 
00561     // An operator.  Bediener is German for operator.
00562     class bediener : public term {
00563     public:
00564         bediener(ibis::compRange::OPERADOR op) : operador(op) {};
00565         virtual ~bediener() {};
00566 
00567         virtual TERM_TYPE termType() const {return OPERATOR;}
00568         virtual bediener* dup() const {
00569             bediener *tmp = new bediener(operador);
00570             tmp->setRight(getRight()->dup());
00571             tmp->setLeft(getLeft()->dup());
00572             return tmp;
00573         }
00574         inline virtual double eval() const;
00575         virtual void print(std::ostream& out) const;
00576         virtual term* reduce();
00577 
00578     private:
00579         ibis::compRange::OPERADOR operador; // Spanish for operator
00580 
00581         void reorder(); // reorder the tree of operators
00582         // place the operands into the list of terms if the operator
00583         // matches the specified one.
00584         void linearize(const ibis::compRange::OPERADOR op,
00585                        std::vector<ibis::compRange::term*>& terms);
00586         // If the right operand is a constant, change operator from - to +
00587         // or from / to *.
00588         void convertConstants();
00589         friend void ibis::qExpr::simplify(ibis::qExpr*&);
00590     }; // bediener
00591 
00593     class stdFunction1 : public term {
00594     public:
00595         stdFunction1(const char* name);
00596         stdFunction1(const STDFUN1 ft) : ftype(ft) {}
00597         virtual ~stdFunction1() {}
00598 
00599         virtual stdFunction1* dup() const {
00600             stdFunction1 *tmp = new stdFunction1(ftype);
00601             tmp->setLeft(getLeft()->dup());
00602             return tmp;
00603         }
00604         virtual TERM_TYPE termType() const {return STDFUNCTION1;}
00605         inline virtual double eval() const;
00606         virtual void print(std::ostream& out) const;
00607         inline virtual term* reduce();
00608 
00609     private:
00610         STDFUN1 ftype;
00611     }; // stdFunction1
00612 
00614     class stdFunction2 : public term {
00615     public:
00616         stdFunction2(const char* name);
00617         stdFunction2(const STDFUN2 ft) : ftype(ft) {}
00618         virtual ~stdFunction2() {}
00619 
00620         virtual stdFunction2* dup() const {
00621             stdFunction2 *tmp = new stdFunction2(ftype);
00622             tmp->setRight(getRight()->dup());
00623             tmp->setLeft(getLeft()->dup());
00624             return tmp;
00625         }
00626         virtual TERM_TYPE termType() const {return STDFUNCTION2;}
00627         inline virtual double eval() const;
00628         virtual void print(std::ostream& out) const;
00629         inline virtual term* reduce();
00630 
00631     private:
00632         STDFUN2 ftype;
00633     }; // stdFunction2
00634 
00635 
00636     // construct the range from strings
00637     compRange() : qExpr(ibis::qExpr::COMPRANGE), expr3(0),
00638                   op12(ibis::qExpr::OP_UNDEFINED),
00639                   op23(ibis::qExpr::OP_UNDEFINED) {;}
00640     compRange(ibis::compRange::term* me1, COMPARE lop,
00641               ibis::compRange::term* me2)
00642         : qExpr(ibis::qExpr::COMPRANGE, me1, me2), expr3(0),
00643           op12(lop), op23(ibis::qExpr::OP_UNDEFINED) {;}
00644     compRange(ibis::compRange::term* me1, ibis::qExpr::COMPARE lop,
00645               ibis::compRange::term* me2, ibis::qExpr::COMPARE rop,
00646               ibis::compRange::term* me3)
00647         : qExpr(ibis::qExpr::COMPRANGE, me1, me2), expr3(me3),
00648           op12(lop), op23(rop) {;}
00649     // copy constructor -- actually copy the math expressions
00650     compRange(const compRange& rhs) :
00651         ibis::qExpr(rhs), expr3(rhs.expr3 ? rhs.expr3->dup() : 0),
00652         op12(rhs.op12), op23(rhs.op23) {};
00653     virtual ~compRange() {delete expr3;}
00654 
00655     // provide read access to the operators
00656     ibis::qExpr::COMPARE leftOperator() const {return op12;}
00657     ibis::qExpr::COMPARE rightOperator() const {return op23;}
00658     term* getTerm3() {return expr3;}
00659     const term* getTerm3() const {return expr3;}
00660     void setTerm3(term* t) {delete expr3; expr3 = t;}
00661 
00663     virtual qExpr* dup() const {return new compRange(*this);}
00665     inline bool inRange() const;
00667     virtual void print(std::ostream&) const;
00668 
00669     virtual bool isSimple() const {return isSimpleRange();}
00671     inline bool isSimpleRange() const;
00672 
00674     bool maybeStringCompare() const;
00675 
00676     // convert a simple expression to qContinuousRange
00677     ibis::qContinuousRange* simpleRange() const;
00678 
00679 private:
00680     ibis::compRange::term *expr3;       // the right most expression
00681     ibis::qExpr::COMPARE op12;  // between qExpr::left and qExpr::right
00682     ibis::qExpr::COMPARE op23;  // between qExpr::right and expr3
00683 }; // ibis::compRange
00684 
00689 class ibis::rangeJoin : public ibis::qExpr {
00690 public:
00691     rangeJoin(const char* n1, const char *n2)
00692         : ibis::qExpr(ibis::qExpr::JOIN), name1(n1), name2(n2), expr(0) {};
00693     rangeJoin(const char* n1, const char *n2, ibis::compRange::term *x) : 
00694         ibis::qExpr(ibis::qExpr::JOIN), name1(n1), name2(n2), expr(x) {};
00695     virtual ~rangeJoin() {delete expr;};
00696 
00697     virtual void print(std::ostream& out) const;
00698     virtual rangeJoin* dup() const
00699     {return new rangeJoin(name1.c_str(), name2.c_str(), expr->dup());};
00700 
00701     const char* getName1() const {return name1.c_str();}
00702     const char* getName2() const {return name2.c_str();}
00703     ibis::compRange::term* getRange() {return expr;}
00704     const ibis::compRange::term* getRange() const {return expr;}
00705     void setRange(ibis::compRange::term *t) {delete expr; expr = t;}
00706 
00707 private:
00708     std::string name1;
00709     std::string name2;
00710     ibis::compRange::term *expr;
00711 
00712     rangeJoin(const rangeJoin&);
00713     const rangeJoin& operator=(const rangeJoin&);
00714 }; // class ibis::rangeJoin
00715 
00727 class ibis::qAnyAny : public ibis::qExpr {
00728 public:
00729     qAnyAny() : qExpr(ANYANY) {};
00730     qAnyAny(const char *pre, const char *val);
00731     ~qAnyAny() {}; // all data members can delete themselves.
00732 
00733     const char* getPrefix() const {return prefix.c_str();}
00734     const std::vector<double>& getValues() const {return values;}
00735 
00736     // Use the compiler generated copy constructor to perform duplication.
00737     virtual qExpr* dup() const {return new qAnyAny(*this);}
00738 
00739     virtual void print(std::ostream& out) const;
00740     virtual void printRange(std::ostream& out) const;
00741 
00742 private:
00743     std::string prefix; 
00744     std::vector<double> values; 
00745 }; // class ibis::qAnyAny
00746 
00747 // return 1 if the incoming value is in the specified range
00748 inline bool ibis::qContinuousRange::inRange(double val) const {
00749     volatile bool res0 = true; 
00750     volatile bool res1 = true; 
00751     switch (left_op) {
00752     case OP_LT: res0 = (lower < val); break;
00753     case OP_LE: res0 = (lower <= val); break;
00754     case OP_GT: res0 = (lower > val); break;
00755     case OP_GE: res0 = (lower >= val); break;
00756     case OP_EQ: res0 = (lower == val); break;
00757     default: break;
00758     } // switch (left_op)
00759     switch (right_op) {
00760     case OP_LT: res1 = (val < upper); break;
00761     case OP_LE: res1 = (val <= upper); break;
00762     case OP_GT: res1 = (val > upper); break;
00763     case OP_GE: res1 = (val >= upper); break;
00764     case OP_EQ: res1 = (val == upper); break;
00765     default:    break;
00766     }
00767     return res0 && res1;
00768 } // bool qContinuousRange::inRange(double val)
00769 
00770 inline void ibis::qContinuousRange::foldBoundaries() {
00771     switch (left_op) {
00772     case ibis::qExpr::OP_LT:
00773         lower = floor(lower);
00774         break;
00775     case ibis::qExpr::OP_LE:
00776         lower = ceil(lower);
00777         break;
00778     case ibis::qExpr::OP_GT:
00779         lower = ceil(lower);
00780         break;
00781     case ibis::qExpr::OP_GE:
00782         lower = floor(lower);
00783         break;
00784     case ibis::qExpr::OP_EQ:
00785         if (lower != floor(lower))
00786             left_op = ibis::qExpr::OP_UNDEFINED;
00787         break;
00788     default:
00789         break;
00790     }
00791     switch (right_op) {
00792     case ibis::qExpr::OP_LT:
00793         upper = ceil(upper);
00794         break;
00795     case ibis::qExpr::OP_LE:
00796         upper = floor(upper);
00797         break;
00798     case ibis::qExpr::OP_GT:
00799         upper = floor(upper);
00800         break;
00801     case ibis::qExpr::OP_GE:
00802         upper = ceil(upper);
00803         break;
00804     case ibis::qExpr::OP_EQ:
00805         if (upper != floor(upper))
00806             right_op = ibis::qExpr::OP_UNDEFINED;
00807         break;
00808     default:
00809         break;
00810     }
00811 } //ibis::qContinuousRange::foldBoundaries
00812 
00813 inline void ibis::qContinuousRange::foldUnsignedBoundaries() {
00814     switch (left_op) {
00815     case ibis::qExpr::OP_LT:
00816         if (lower >= 0.0) {
00817             lower = floor(lower);
00818         }
00819         else {
00820             left_op = ibis::qExpr::OP_LE;
00821             lower = 0.0;
00822         }
00823         break;
00824     case ibis::qExpr::OP_LE:
00825         if (lower >= 0.0)
00826             lower = ceil(lower);
00827         else
00828             lower = 0.0;
00829         break;
00830     case ibis::qExpr::OP_GT:
00831         lower = ceil(lower);
00832         break;
00833     case ibis::qExpr::OP_GE:
00834         lower = floor(lower);
00835         break;
00836     case ibis::qExpr::OP_EQ:
00837         if (lower != floor(lower) || lower < 0.0)
00838             left_op = ibis::qExpr::OP_UNDEFINED;
00839         break;
00840     default:
00841         break;
00842     }
00843     switch (right_op) {
00844     case ibis::qExpr::OP_LT:
00845         upper = ceil(upper);
00846         break;
00847     case ibis::qExpr::OP_LE:
00848         upper = floor(upper);
00849         break;
00850     case ibis::qExpr::OP_GT:
00851         if (upper > 0.0) {
00852             upper = floor(upper);
00853         }
00854         else {
00855             right_op = ibis::qExpr::OP_GE;
00856             upper = 0.0;
00857         }
00858         break;
00859     case ibis::qExpr::OP_GE:
00860         if (upper >= 0.0)
00861             upper = ceil(upper);
00862         else
00863             upper = 0.0;
00864         break;
00865     case ibis::qExpr::OP_EQ:
00866         if (upper != floor(upper) || upper < 0.0)
00867             right_op = ibis::qExpr::OP_UNDEFINED;
00868         break;
00869     default:
00870         break;
00871     }
00872 } //ibis::qContinuousRange::foldUnsignedBoundaries
00873 
00874 // incorrect implementation !! still need to decide how to fill the values
00875 inline bool ibis::compRange::inRange() const {
00876     volatile bool res = false;
00877     volatile double tm1 =
00878         static_cast<const ibis::compRange::term*>(getLeft())->eval();
00879     volatile double tm2 =
00880         static_cast<const ibis::compRange::term*>(getRight())->eval();
00881     switch (op12) {
00882     case OP_LT: res = (tm1 < tm2); break;
00883     case OP_LE: res = (tm1 <= tm2); break;
00884     case OP_GT: res = (tm1 > tm2); break;
00885     case OP_GE: res = (tm1 >= tm2); break;
00886     case OP_EQ: res = (tm1 == tm2); break;
00887     default:    break;
00888     }
00889     if (expr3) {
00890         tm1 = expr3->eval();
00891         switch (op23) {
00892         case OP_LT: res = res && (tm2 < tm1); break;
00893         case OP_LE: res = res && (tm2 <= tm1); break;
00894         case OP_GT: res = res && (tm2 > tm1); break;
00895         case OP_GE: res = res && (tm2 >= tm1); break;
00896         case OP_EQ: res = res && (tm2 == tm1); break;
00897         default:    break;
00898         }
00899     }
00900     return res;
00901 } // bool ibis::compRange::inRange(double val)
00902 
00904 inline bool ibis::qContinuousRange::operator<
00905     (const ibis::qContinuousRange& y) const {
00906     int cmp = strcmp(colName(), y.colName());
00907     if (cmp < 0)
00908         return true;
00909     else if (cmp > 0)
00910         return false;
00911     else if (left_op < y.left_op)
00912         return true;
00913     else if (left_op > y.left_op)
00914         return false;
00915     else if (right_op < y.right_op)
00916         return true;
00917     else if (right_op > y.right_op)
00918         return false;
00919     else if (lower < y.lower)
00920         return true;
00921     else if (lower > y.lower)
00922         return false;
00923     else if (upper < y.upper)
00924         return true;
00925     else
00926         return false;
00927 } // bool ibis::qContinuousRange::operator<
00928 
00933 inline bool ibis::qDiscreteRange::inRange(double val) const {
00934     if (values.empty()) return false;
00935     if (val < values[0] || val > values.back()) return false;
00936 
00937     uint32_t i = 0, j = values.size();
00938     if (j < 32) { // sequential search
00939         // -- because the heavy branch prediction cost, linear search is
00940         // more efficient for fairly large range.
00941         for (i = 0; i < j; ++ i)
00942             if (values[i] == val) return true;
00943     }
00944     else { // binary search
00945         uint32_t m = (i + j) / 2;
00946         while (i < m) {
00947             if (values[m] == val) return true;
00948             if (values[m] < val)
00949                 i = m;
00950             else
00951                 j = m;
00952             m = (i + j) / 2;
00953         }
00954         // upon exiting the while loop, values[i] < val and values[j] > val
00955         // if values[j] exist.
00956     }
00957     return false;
00958 } // ibis::qDiscreteRange::inRange
00959 
00962 inline uint32_t ibis::compRange::barrel::recordVariable(