Main Page | Namespace List | Class Hierarchy | Class List | File List | Class Members | File Members

Expression.h

Go to the documentation of this file.
00001 #ifndef EXPRESSION_H 00002 #define EXPRESSION_H 00003 00004 #include <NMSTL/util> 00005 #include <NMSTL/ptr> 00006 #include <antlr/SemanticException.hpp> 00007 00008 #include "EString.h" 00009 #include "TupleDescription.h" 00010 #include "Exceptions.h" 00011 #include "Registry.h" 00012 #include "Timestamp.h" 00013 00014 // TRUE and FALSE need to be undefined so they do not conflict with the 00015 // enumeration in ExprParserTokenTypes.hpp; which is generated from the 00016 // expr.g grammar file. This file is included by expr.g to achieve this. 00017 // 00018 #ifdef TRUE 00019 #undef TRUE 00020 #endif 00021 00022 #ifdef FALSE 00023 #undef FALSE 00024 #endif 00025 00026 using namespace std; 00027 using namespace NMSTL; 00028 00029 BOREALIS_NAMESPACE_BEGIN 00030 00031 AURORA_EXCEPTION_TYPE( ExprException ); 00032 AURORA_EXCEPTION_TYPE( EvalException ); 00033 00034 00035 00044 class ExprContext 00045 { 00046 public: 00047 // Move to the DataType class??? 00048 static const string to_string( DataType t ); 00049 00054 TupleDescription getTupleDescription() const { return _desc; } 00055 00057 void setTupleDescription(TupleDescription desc) { _desc = desc; } 00058 00061 void getNamedTupleInfo( string name, 00062 TupleDescription &desc, 00063 unsigned int &index 00064 ) const 00065 { 00066 pair<TupleDescription, unsigned int> info = lookup(_named_desc, name); 00067 desc = info.first; 00068 index = info.second; 00069 } 00070 00071 00073 void setNamedTupleInfo(string name, TupleDescription desc, unsigned int index) { 00074 _named_desc[name] = make_pair(desc, index); 00075 } 00076 00077 00081 void findFieldName( string field_name, 00082 string &tuple_name, 00083 unsigned int &tuple_index, 00084 TupleDescription &tuple_desc, 00085 unsigned int &field_index 00086 ) const 00087 throw( ExprException ) 00088 { 00089 bool found = false; 00090 00091 for ( NamedDesc::const_iterator i = _named_desc.begin(); 00092 i != _named_desc.end(); ++i) 00093 { 00094 int off = i->second.first.indexOfField( field_name ); 00095 00096 if ( off >= 0 ) 00097 { if ( found ) 00098 { Throw(ExprException, "multiple fields " + field_name + " in input tuple(s)"); 00099 } 00100 00101 found = true; 00102 // whoa... lispy... 00103 tuple_name = i->first; 00104 tuple_index = i->second.second; 00105 tuple_desc = i->second.first; 00106 field_index = off; 00107 } 00108 } 00109 00110 if ( !found ) 00111 { Throw(ExprException, "no field " + field_name + " in any input tuple"); 00112 } 00113 } 00114 00115 private: 00116 TupleDescription _desc; 00117 00118 typedef map<string, pair<TupleDescription, unsigned int> > NamedDesc; 00119 NamedDesc _named_desc; 00120 00121 // Eventually - multiple descriptions (LEFT/RIGHT for join, etc.) 00122 }; 00123 00124 00125 00138 class EvalContext { 00139 public: 00145 EvalContext(unsigned int num_tuples = 1, 00146 unsigned int pool_size = EStringPool::DEFAULT_INITIAL_SIZE) : 00147 _tuple(num_tuples), _pool(pool_size) 00148 {} 00149 00153 void reset() { 00154 _pool.reset(); 00155 } 00156 00158 void setTuple(const void *tuple) { _tuple[0] = tuple; } 00159 00161 void setTuple(unsigned int index, const void *tuple) 00162 { 00163 ASSERT(index < _tuple.size()); 00164 _tuple[index] = tuple; 00165 } 00166 00168 const char *getTuple(unsigned int index = 0) const 00169 { 00170 ASSERT(index < _tuple.size()); 00171 return static_cast<const char*>(_tuple[index]); 00172 } 00173 00176 char *alloc(unsigned int size) const 00177 { 00178 return _pool.alloc(size); 00179 } 00180 00182 EStringPool& getPool() const 00183 { 00184 return _pool; 00185 } 00186 00187 private: 00188 vector<const void*> _tuple; 00189 mutable EStringPool _pool; 00190 00191 EvalContext(const EvalContext&); 00192 EvalContext& operator = (const EvalContext&); 00193 00194 // Eventually - multiple tuples. 00195 }; 00196 00197 00198 00199 00200 template<class T> class EvalAs; 00201 00204 template<> class EvalAs<int32> {}; 00205 00208 template<> class EvalAs<int64> {}; 00209 00212 template<> class EvalAs<single> {}; 00213 00216 template<> class EvalAs<double> {}; 00217 00220 template<> class EvalAs<bool> {}; 00221 00224 template<> class EvalAs<EString> {}; 00225 00229 template<> class EvalAs<string> {}; 00230 00234 template<> class EvalAs<Timestamp> {}; 00235 00262 class Expression 00263 { 00264 public: 00265 //#ifdef ENABLE_SERIALIZATION 00266 // Expression() {} 00267 //#endif 00268 00270 virtual ~Expression() {} 00271 00274 template<typename T> 00275 T eval( const EvalContext &ctxt ) throw( EvalException ) 00276 { 00277 return( evalImpl( EvalAs<T>(), ctxt )); 00278 } 00279 00282 template<typename T> bool is() const 00283 { 00284 return( isImpl( EvalAs<T>() )); 00285 } 00286 00289 virtual int32 getStringLength() const { return -1; } 00290 00292 int32 getLength() const 00293 { 00294 if ( _type == DataType::INT ) return sizeof( int32 ); 00295 else if ( _type == DataType::LONG ) return sizeof( int64 ); 00296 else if ( _type == DataType::FLOAT ) return sizeof( single ); 00297 else if ( _type == DataType::SINGLE ) return sizeof( single ); 00298 else if ( _type == DataType::DOUBLE ) return sizeof( double ); 00299 else if ( _type == DataType::BOOL ) return sizeof( bool ); 00300 else if ( _type == DataType::TIMESTAMP ) return sizeof( Timestamp ); 00301 else 00302 return( getStringLength() ); 00303 } 00304 00307 void evalInto(char *buf, const EvalContext& ctxt) throw (EvalException) 00308 { 00309 ASSERT( getLength() != -1 ); 00310 00311 if ( _type == DataType::INT ) *(int32*)buf = eval<int32>(ctxt); 00312 else if ( _type == DataType::LONG ) *(int64*)buf = eval<int64>(ctxt); 00313 else if ( _type == DataType::FLOAT ) *(single*)buf = eval<single>(ctxt); 00314 else if ( _type == DataType::SINGLE ) *(single*)buf = eval<single>(ctxt); 00315 else if ( _type == DataType::DOUBLE ) *(double*)buf = eval<double>(ctxt); 00316 else if ( _type == DataType::BOOL ) *(bool*)buf = eval<bool>(ctxt); 00317 else if ( _type == DataType::TIMESTAMP ) *( Timestamp* )buf = eval<Timestamp>(ctxt); 00318 else { 00319 EString str = eval<EString>(ctxt); 00320 __builtin_memcpy( buf, str.data(), str.length() ); 00321 00322 int len = getStringLength(); 00323 ASSERT( len >= 0 ); 00324 ASSERT( str.length() <= (unsigned int)len ); 00325 __builtin_memset( buf + str.length(), 0, len - str.length() ); 00326 } 00327 } 00328 00331 virtual bool is_numeric() const { return( is<double>() ); } 00332 00334 DataType getType() const { return _type; } 00335 00338 TupleDescription::Field getField(string name = string()) const throw (ExprException); 00339 00341 virtual void dump( string& s, unsigned int indent = 0 ) const 00342 { 00343 for ( unsigned int i = 0; i < indent; ++i ) 00344 { s += " "; 00345 } 00346 00347 s << typeid( *this ); 00348 00349 string val = value(); 00350 if ( !val.empty() ) 00351 { s << " - " << val; 00352 } 00353 00354 s << "\n"; 00355 00356 dump_children( s, indent + 1 ); 00357 } 00358 00360 string as_string() const 00361 { 00362 return( ::to_string( typeid( *this ))); 00363 } 00364 00366 static ptr<Expression> parse( string expr, const ExprContext &ctxt ) 00367 throw( ExprException ); 00368 00373 static void evalVectorInto( const vector<ptr<Expression> > &exprs, 00374 char *buf, const EvalContext &ctxt ) 00375 throw( EvalException ); 00376 00381 static ptr<Expression> makeFieldExpresssion( string tuple_name, 00382 string field_name, 00383 const ExprContext &ctxt 00384 ) 00385 throw( ExprException ); 00386 00388 TupleDescription::Field toField( string name ) const 00389 throw( AuroraException ); 00390 00391 protected: 00392 Expression( DataType type ) : _type(type) {} 00393 00394 protected: 00396 virtual bool evalImpl( EvalAs<bool>, const EvalContext& ) 00397 throw( EvalException ) 00398 { 00399 throw EvalException( "Cannot coerce result of " 00400 + ::to_string( typeid( *this )) + " to bool" ); 00401 } 00402 00404 virtual bool isImpl( EvalAs<bool> ) const { return( false ); } 00405 00406 00408 virtual int32 evalImpl( EvalAs<int32>, const EvalContext& ) 00409 throw( EvalException ) 00410 { 00411 throw EvalException( "Cannot coerce result of " 00412 + ::to_string( typeid( *this )) + " to int" ); 00413 } 00414 00416 virtual bool isImpl( EvalAs<int32> ) const { return( false ); } 00417 00418 00420 virtual int64 evalImpl( EvalAs<int64>, const EvalContext& ) 00421 throw( EvalException ) 00422 { 00423 throw EvalException( "Cannot coerce result of " 00424 + ::to_string( typeid( *this )) + " to long" ); 00425 } 00426 00428 virtual bool isImpl( EvalAs<int64> ) const { return( false ); } 00429 00430 00432 virtual single evalImpl( EvalAs<single>, const EvalContext& ) 00433 throw( EvalException ) 00434 { 00435 throw EvalException( "Cannot coerce result of " 00436 + ::to_string( typeid( *this )) + " to single" ); 00437 } 00438 00440 virtual bool isImpl( EvalAs<single> ) const { return( false ); } 00441 00442 00444 virtual double evalImpl( EvalAs<double>, const EvalContext& ) 00445 throw( EvalException ) 00446 { 00447 throw EvalException( "Cannot coerce result of " 00448 + ::to_string( typeid( *this )) + " to double" ); 00449 } 00450 00452 virtual bool isImpl( EvalAs<double> ) const { return( false ); } 00453 00454 00456 virtual EString evalImpl( EvalAs<EString>, const EvalContext& ) 00457 throw( EvalException ) 00458 { 00459 throw EvalException( "Cannot coerce result of " 00460 + ::to_string( typeid( *this )) + " to EString" ); 00461 } 00462 00464 virtual bool isImpl( EvalAs<EString> ) const { return false; } 00465 00469 virtual string evalImpl( EvalAs<string>, const EvalContext& ctxt ) 00470 throw( EvalException ) 00471 { 00472 return( ::to_string( eval<EString>( ctxt ))); 00473 } 00474 00477 virtual bool isImpl( EvalAs<string> ) const { return is<EString>(); } 00478 00479 00481 virtual Timestamp evalImpl( EvalAs<Timestamp>, const EvalContext& ) 00482 throw( EvalException ) 00483 { 00484 throw EvalException( "Cannot coerce result of " 00485 + ::to_string( typeid( *this )) + " to Timestamp" ); 00486 } 00487 00489 virtual bool isImpl( EvalAs<Timestamp> ) const { return( false ); } 00490 00491 00492 00493 virtual void dump_children( string& s, unsigned int indent ) const {} 00494 virtual string value() const { return string(); } 00495 00496 //#ifdef ENABLE_SERIALIZATION 00497 //NMSTL_SERIAL_BASE(Expression, long, << _type); 00498 //#endif 00499 00500 private: 00501 DataType _type; 00502 }; 00503 00504 00505 template<typename T> class TypedExpression; 00506 00511 template<> 00512 class TypedExpression<bool> : public Expression 00513 { 00514 public: 00515 TypedExpression() : Expression( DataType::BOOL ) {} 00516 00517 virtual bool evalImpl( EvalAs<bool>, const EvalContext &ctxt ) 00518 throw( EvalException ) = 0; 00519 00520 bool isImpl( EvalAs<bool> ) const { return true; } 00521 00522 00523 int32 evalImpl( EvalAs<int32>, const EvalContext &ctxt) 00524 throw( EvalException ) { return eval<bool>(ctxt); } 00525 00526 bool isImpl( EvalAs<int32> ) const { return true; } 00527 00528 00529 int64 evalImpl( EvalAs<int64>, const EvalContext &ctxt) 00530 throw( EvalException ) { return eval<bool>(ctxt); } 00531 00532 bool isImpl( EvalAs<int64> ) const { return true; } 00533 00534 00535 single evalImpl( EvalAs<single>, const EvalContext &ctxt ) 00536 throw( EvalException ) { return eval<bool>(ctxt); } 00537 00538 bool isImpl( EvalAs<single> ) const { return true; } 00539 00540 00541 double evalImpl( EvalAs<double>, const EvalContext &ctxt ) 00542 throw( EvalException ) { return eval<bool>(ctxt); } 00543 00544 bool isImpl( EvalAs<double> ) const { return true; } 00545 00546 00547 EString evalImpl( EvalAs<EString>, const EvalContext &ctxt ) 00548 throw( EvalException ) 00549 { 00550 return( EString::coerce( eval<bool>(ctxt), ctxt.getPool() )); 00551 } 00552 00553 bool isImpl( EvalAs<EString> ) const { return true; } 00554 00555 // Do we want to convert timestamps into bool? Maybe? 00556 //Timestamp evalImpl( EvalAs<Timestamp>, const EvalContext &ctxt) 00557 // throw( EvalException ) { return eval<bool>(ctxt); } 00558 //bool isImpl( EvalAs<Timestamp> ) const { return true; } 00559 00560 }; 00561 00562 00567 template<> 00568 class TypedExpression<int32> : public Expression 00569 { 00570 public: 00571 TypedExpression() : Expression( DataType::INT ) {} 00572 00573 virtual int32 evalImpl( EvalAs<int32>, const EvalContext &ctxt ) 00574 throw( EvalException ) = 0; 00575 00576 bool isImpl( EvalAs<int32> ) const { return( true ); } 00577 00578 00579 int64 evalImpl( EvalAs<int64>, const EvalContext &ctxt ) 00580 throw( EvalException ) { return eval<int32>(ctxt); } 00581 00582 bool isImpl( EvalAs<int64> ) const { return( true ); } 00583 00584 00585 single evalImpl( EvalAs<single>, const EvalContext &ctxt ) 00586 throw( EvalException ) { return eval<int32>(ctxt); } 00587 00588 bool isImpl( EvalAs<single> ) const { return( true ); } 00589 00590 00591 double evalImpl( EvalAs<double>, const EvalContext &ctxt ) 00592 throw( EvalException ) { return eval<int32>(ctxt); } 00593 00594 bool isImpl( EvalAs<double> ) const { return( true ); } 00595 00596 00597 EString evalImpl( EvalAs<EString>, const EvalContext &ctxt ) 00598 throw( EvalException ) 00599 { 00600 return( EString::coerce( eval<int32>(ctxt), ctxt.getPool() )); 00601 } 00602 00603 bool isImpl(EvalAs<EString>) const { return( true ); } 00604 00605 //Timestamp evalImpl( EvalAs<Timestamp>, const EvalContext &ctxt) 00606 // throw( EvalException ) { return eval<int32>(ctxt); } 00607 //bool isImpl( EvalAs<Timestamp> ) const { return true; } 00608 00609 }; 00610 00611 00616 template<> 00617 class TypedExpression<int64> : public Expression 00618 { 00619 public: 00620 TypedExpression() : Expression( DataType::LONG ) {} 00621 00622 virtual int64 evalImpl( EvalAs<int64>, const EvalContext &ctxt ) 00623 throw( EvalException ) = 0; 00624 00625 bool isImpl( EvalAs<int64> ) const { return( true ); } 00626 00627 00628 int32 evalImpl( EvalAs<int32>, const EvalContext &ctxt ) 00629 throw( EvalException ) { return eval<int64>(ctxt); } 00630 00631 bool isImpl( EvalAs<int32> ) const { return( true ); } 00632 00633 00634 single evalImpl( EvalAs<single>, const EvalContext &ctxt ) 00635 throw( EvalException ) { return eval<int64>(ctxt); } 00636 00637 bool isImpl( EvalAs<single> ) const { return( true ); } 00638 00639 00640 double evalImpl( EvalAs<double>, const EvalContext &ctxt ) 00641 throw( EvalException ) { return eval<int64>(ctxt); } 00642 00643 bool isImpl( EvalAs<double> ) const { return( true ); } 00644 00645 00646 EString evalImpl( EvalAs<EString>, const EvalContext &ctxt ) 00647 throw( EvalException ) 00648 { 00649 return( EString::coerce( eval<int64>(ctxt), ctxt.getPool() )); 00650 } 00651 00652 bool isImpl(EvalAs<EString>) const { return( true ); } 00653 00654 //Timestamp evalImpl( EvalAs<Timestamp>, const EvalContext &ctxt) 00655 // throw( EvalException ) { return eval<int64>(ctxt); } 00656 //bool isImpl( EvalAs<Timestamp> ) const { return true; } 00657 }; 00658 00659 00660 00665 template<> 00666 class TypedExpression<single> : public Expression 00667 { 00668 public: 00669 TypedExpression() : Expression( DataType::SINGLE ) {} 00670 00671 virtual single evalImpl( EvalAs<single>, const EvalContext &ctxt ) 00672 throw( EvalException ) = 0; 00673 00674 bool isImpl( EvalAs<single> ) const { return( true ); } 00675 00676 EString evalImpl( EvalAs<EString>, const EvalContext &ctxt ) 00677 throw( EvalException ) 00678 { 00679 return( EString::coerce( eval<single>(ctxt), ctxt.getPool() )); 00680 } 00681 00682 bool isImpl(EvalAs<EString>) const { return( true ); } 00683 00684 //Timestamp evalImpl( EvalAs<Timestamp>, const EvalContext &ctxt) 00685 // throw( EvalException ) { return eval<single>(ctxt); } 00686 //bool isImpl( EvalAs<Timestamp> ) const { return true; } 00687 }; 00688 00689 00694 template<> 00695 class TypedExpression<double> : public Expression 00696 { 00697 public: 00698 TypedExpression() : Expression( DataType::DOUBLE ) {} 00699 00700 virtual double evalImpl( EvalAs<double>, const EvalContext &ctxt ) 00701 throw( EvalException ) = 0; 00702 00703 bool isImpl( EvalAs<double> ) const { return( true ); } 00704 00705 EString evalImpl( EvalAs<EString>, const EvalContext &ctxt ) 00706 throw( EvalException ) 00707 { 00708 return( EString::coerce(eval<double>(ctxt), ctxt.getPool() )); 00709 } 00710 00711 bool isImpl(EvalAs<EString>) const { return( true ); } 00712 00713 //Timestamp evalImpl( EvalAs<Timestamp>, const EvalContext &ctxt) 00714 // throw( EvalException ) { return eval<double>(ctxt); } 00715 //bool isImpl( EvalAs<Timestamp> ) const { return true; } 00716 }; 00717 00718 00719 00724 template<> 00725 class TypedExpression<EString> : public Expression 00726 { 00727 public: 00728 virtual EString evalImpl( EvalAs<EString>, const EvalContext &ctxt ) 00729 throw( EvalException ) = 0; 00730 00731 bool isImpl( EvalAs<EString> ) const { return( true ); } 00732 00733 TypedExpression() : Expression( DataType::STRING ) {} 00734 }; 00735 00740 template<> 00741 class TypedExpression<Timestamp> : public Expression 00742 { 00743 public: 00744 TypedExpression() : Expression ( DataType::TIMESTAMP ) {} 00745 00746 virtual Timestamp evalImpl( EvalAs<Timestamp>, const EvalContext &ctxt) 00747 throw( EvalException ) = 0; 00748 00749 bool isImpl( EvalAs<Timestamp> ) const { return true; } 00750 }; 00751 00752 BOREALIS_NAMESPACE_END 00753 #endif // EXPRESSION_H

Generated on Fri Nov 12 15:15:21 2004 for Borealis by doxygen 1.3.8