platform/include/pion/platform/Query.hpp

00001 // ------------------------------------------------------------------------
00002 // Pion is a development platform for building Reactors that process Events
00003 // ------------------------------------------------------------------------
00004 // Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
00005 //
00006 // Pion is free software: you can redistribute it and/or modify it under the
00007 // terms of the GNU Affero General Public License as published by the Free
00008 // Software Foundation, either version 3 of the License, or (at your option)
00009 // any later version.
00010 //
00011 // Pion is distributed in the hope that it will be useful, but WITHOUT ANY
00012 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013 // FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for
00014 // more details.
00015 //
00016 // You should have received a copy of the GNU Affero General Public License
00017 // along with Pion.  If not, see <http://www.gnu.org/licenses/>.
00018 //
00019 
00020 #ifndef __PION_QUERY_HEADER__
00021 #define __PION_QUERY_HEADER__
00022 
00023 #ifdef _MSC_VER
00024 // This could be any valid .lib file; its only purpose is to prevent the compiler  
00025 // from trying to link to boost_zlib-*.lib (e.g. boost_zlib-vc80-mt-1_37.lib).  
00026 // Query only uses zlib indirectly, through boost_iostreams-*.dll.
00027 #define BOOST_ZLIB_BINARY "zdll.lib"
00028 #endif
00029 
00030 #include <cstdio>
00031 #include <string>
00032 
00033 // For ZBlob compression
00034 #include <boost/iostreams/copy.hpp>
00035 #include <boost/iostreams/device/back_inserter.hpp>
00036 #include <boost/iostreams/filter/zlib.hpp>
00037 #include <boost/iostreams/filtering_stream.hpp>
00038 
00039 #include <boost/cstdint.hpp>
00040 #include <boost/noncopyable.hpp>
00041 #include <pion/PionConfig.hpp>
00042 #include <pion/platform/Vocabulary.hpp>
00043 #include <pion/platform/Event.hpp>
00044 
00045 
00046 namespace pion {        // begin namespace pion
00047 namespace platform {    // begin namespace platform (Pion Platform Library)
00048 
00049 // forward declarations used by Query
00050 class Database;
00051 
00052 
00056 class Query
00057     : private boost::noncopyable
00058 {
00059 public:
00060 
00062 //  typedef std::pair<std::string, Vocabulary::Term>        FieldData;
00063     typedef std::pair<std::string, Vocabulary::Term>        FieldData;
00064 
00066 //  typedef std::map<Vocabulary::TermRef, FieldData>        FieldMap;
00067     typedef std::vector<FieldData>                          FieldMap;
00068 
00069     typedef std::vector<std::string>                        IndexMap;
00070 
00072     virtual ~Query() {}
00073 
00079     virtual void bindNull(unsigned int param) = 0;
00080 
00088     virtual void bindString(unsigned int param, const std::string& value, bool copy_value = true) = 0;
00089 
00090     virtual void fetchString(unsigned int param, std::string& value) = 0;
00091 
00099     virtual void bindBlob(unsigned int param, const char *value, size_t size, bool copy_value = true) = 0;
00100 
00101     virtual void fetchBlob(unsigned int param, std::string& value) = 0;
00102 
00103     void bindZBlob(unsigned int param, const char *value, size_t size, bool copy_value = true)
00104     {
00105         std::string temp;
00106         if (size == 0 || value == NULL || *value == '\0') {
00107             temp.clear();
00108         } else {
00109             boost::iostreams::filtering_streambuf<boost::iostreams::output> out;
00110             out.push(boost::iostreams::zlib_compressor());
00111             out.push(boost::iostreams::back_inserter(temp));
00112             std::string data(value, size);
00113             boost::iostreams::copy(boost::make_iterator_range(data), out);
00114         }
00115         bindBlob(param, temp.data(), temp.size());
00116     }
00117 
00118     void fetchZBlob(unsigned int param, std::string& value)
00119     {
00120         std::string temp;
00121         fetchBlob(param, temp);
00122         if (temp.size() == 0) {
00123             value = temp;
00124         } else {
00125             boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
00126             in.push(boost::iostreams::zlib_decompressor());
00127             in.push(boost::make_iterator_range(temp));
00128             boost::iostreams::copy(in, boost::iostreams::back_inserter(value));
00129         }
00130     }
00131 
00132 
00140     virtual void bindString(unsigned int param, const char *value, bool copy_value = true) = 0;
00141 
00142 //  virtual char *fetchString(unsigned int param) = 0;
00143 
00150     virtual void bindInt(unsigned int param, const boost::int32_t value) = 0;
00151 
00152     virtual boost::int32_t fetchInt(unsigned int param) = 0;
00153 
00160     virtual void bindUInt(unsigned int param, const boost::uint32_t value) = 0;
00161 
00162     virtual boost::uint32_t fetchUInt(unsigned int param) = 0;
00163 
00170     virtual void bindBigInt(unsigned int param, const boost::int64_t value) = 0;
00171 
00172     virtual boost::int64_t fetchBigInt(unsigned int param) = 0;
00173 
00180     virtual void bindUBigInt(unsigned int param, const boost::uint64_t value) = 0;
00181 
00182     virtual boost::uint64_t fetchUBigInt(unsigned int param) = 0;
00183 
00190     virtual void bindFloat(unsigned int param, const float value) = 0;
00191 
00192     virtual float fetchFloat(unsigned int param) = 0;
00193 
00200     virtual void bindDouble(unsigned int param, const double value) = 0;
00201 
00202     virtual double fetchDouble(unsigned int param) = 0;
00203 
00210     virtual void bindLongDouble(unsigned int param, const long double value) = 0;
00211 
00212     virtual long double fetchLongDouble(unsigned int param) = 0;
00213 
00220     virtual void bindDateTime(unsigned int param, const PionDateTime& value) = 0;
00221 
00222     virtual void fetchDateTime(unsigned int param, PionDateTime& val) = 0;
00223 
00230     virtual void bindDate(unsigned int param, const PionDateTime& value) = 0;
00231 
00232     virtual void fetchDate(unsigned int param, PionDateTime& val) = 0;
00233 
00240     virtual void bindTime(unsigned int param, const PionDateTime& value) = 0;
00241 
00242     virtual void fetchTime(unsigned int param, PionDateTime& val) = 0;
00243 
00252     inline void bindEvent(const FieldMap& field_map, const Event& e, bool copy_strings = true);
00253 
00254     inline void fetchEvent(const FieldMap& field_map, EventPtr e);
00255 
00261     virtual bool run(void) = 0;
00262 
00275     virtual bool runFullQuery(const FieldMap& ins, const EventPtr& src,
00276             const FieldMap& outs, EventPtr& dest, unsigned int limit,
00277             const boost::regex& suppress) = 0;
00278 
00280     inline bool runFullQuery(const FieldMap& ins, const EventPtr& src,
00281             const FieldMap& outs, EventPtr& dest, unsigned int limit)
00282     {
00283         static boost::regex no_suppress;
00284         return runFullQuery(ins, src, outs, dest, limit, no_suppress);
00285     }
00286 
00296     virtual bool runFullGetMore(const FieldMap& outs, EventPtr& dest,unsigned int limit) = 0;
00297 
00299     virtual void reset(void) = 0;
00300 
00302     inline const std::string& getSQL(void) const { return m_sql_query; }
00303 
00304 
00305 protected:
00306 
00312     Query(const std::string& sql_query)
00313         : m_sql_query(sql_query)
00314     {}
00315 
00322     static void writeDateString(char *buf, const pion::PionDateTime& t) {
00323         sprintf(buf, "%.2d-%.2d-%.2d",
00324             static_cast<int>( t.date().year() ),
00325             static_cast<int>( t.date().month() ),
00326             static_cast<int>( t.date().day() ));
00327     }
00328 
00335     static void writeTimeString(char *buf, const pion::PionDateTime& t) {
00336         sprintf(buf, "%.2d:%.2d:%.2d",
00337             static_cast<int>( t.time_of_day().hours() ),
00338             static_cast<int>( t.time_of_day().minutes() ),
00339             static_cast<int>( t.time_of_day().seconds() ));
00340     }
00341 
00348     static void writeDateTimeString(char *buf, const pion::PionDateTime& t) {
00349         sprintf(buf, "%.2d-%.2d-%.2d %.2d:%.2d:%.2d",
00350             static_cast<int>( t.date().year() ),
00351             static_cast<int>( t.date().month() ),
00352             static_cast<int>( t.date().day() ),
00353             static_cast<int>( t.time_of_day().hours() ),
00354             static_cast<int>( t.time_of_day().minutes() ),
00355             static_cast<int>( t.time_of_day().seconds() ));
00356     }
00357     
00365     inline char *getDateString(const pion::PionDateTime& t) const {
00366         writeDateString(m_time_buf, t);
00367         return m_time_buf;
00368     }
00369 
00377     inline char *getTimeString(const pion::PionDateTime& t) const {
00378         writeTimeString(m_time_buf, t);
00379         return m_time_buf;
00380     }
00381 
00389     inline char *getDateTimeString(const pion::PionDateTime& t) const {
00390         writeDateTimeString(m_time_buf, t);
00391         return m_time_buf;
00392     }
00393 
00394 
00395 private:
00396 
00398     const std::string                   m_sql_query;
00399 
00401     mutable char                        m_time_buf[25];
00402 };
00403 
00404 
00405 // inline member functions for Query
00406 
00407 inline void Query::bindEvent(const FieldMap& field_map, const Event& e, bool copy_strings)
00408 {
00409     for (unsigned int param = 0; param < field_map.size(); param++) {
00410         const Event::ParameterValue *value_ptr = e.getPointer(field_map[param].second.term_ref);
00411         if (value_ptr == NULL) {
00412             bindNull(param);
00413         } else {
00414             switch(field_map[param].second.term_type) {
00415                 case Vocabulary::TYPE_NULL:
00416                 case Vocabulary::TYPE_OBJECT:
00417                     bindNull(param);
00418                     break;
00419                 case Vocabulary::TYPE_INT8:
00420                 case Vocabulary::TYPE_INT16:
00421                 case Vocabulary::TYPE_INT32:
00422                     bindInt(param, boost::get<boost::int32_t>(*value_ptr));
00423                     break;
00424                 case Vocabulary::TYPE_INT64:
00425                     bindBigInt(param, boost::get<boost::int64_t>(*value_ptr));
00426                     break;
00427                 case Vocabulary::TYPE_UINT8:
00428                 case Vocabulary::TYPE_UINT16:
00429                 case Vocabulary::TYPE_UINT32:
00430                     bindUInt(param, boost::get<boost::uint32_t>(*value_ptr));
00431                     break;
00432                 case Vocabulary::TYPE_UINT64:
00433                     bindUBigInt(param, boost::get<boost::uint64_t>(*value_ptr));
00434                     break;
00435                 case Vocabulary::TYPE_FLOAT:
00436                     bindFloat(param, boost::get<float>(*value_ptr));
00437                     break;
00438                 case Vocabulary::TYPE_DOUBLE:
00439                     bindDouble(param, boost::get<double>(*value_ptr));
00440                     break;
00441                 case Vocabulary::TYPE_LONG_DOUBLE:
00442                     bindLongDouble(param, boost::get<long double>(*value_ptr));
00443                     break;
00444                 case Vocabulary::TYPE_SHORT_STRING:
00445                 case Vocabulary::TYPE_STRING:
00446                 case Vocabulary::TYPE_LONG_STRING:
00447                 case Vocabulary::TYPE_CHAR:
00448                     bindString(param,
00449                         boost::get<const Event::BlobType&>(*value_ptr).get(),
00450                         copy_strings);
00451                     break;
00452                 case Vocabulary::TYPE_BLOB:
00453                     bindBlob(param,
00454                         boost::get<const Event::BlobType&>(*value_ptr).get(),
00455                         boost::get<const Event::BlobType&>(*value_ptr).size(),
00456                         copy_strings);
00457                     break;
00458                 case Vocabulary::TYPE_ZBLOB:
00459                     bindZBlob(param,
00460                         boost::get<const Event::BlobType&>(*value_ptr).get(),
00461                         boost::get<const Event::BlobType&>(*value_ptr).size(),
00462                         copy_strings);
00463                     break;
00464                 case Vocabulary::TYPE_DATE_TIME:
00465                     bindDateTime(param, boost::get<const PionDateTime&>(*value_ptr));
00466                     break;
00467                 case Vocabulary::TYPE_DATE:
00468                     bindDate(param, boost::get<const PionDateTime&>(*value_ptr));
00469                     break;
00470                 case Vocabulary::TYPE_TIME:
00471                     bindTime(param, boost::get<const PionDateTime&>(*value_ptr));
00472                     break;
00473             }
00474         }
00475     }
00476 }
00477 
00478 inline void Query::fetchEvent(const FieldMap& field_map, EventPtr e)
00479 {
00480     for (unsigned int param = 0; param < field_map.size(); param++) {
00481         switch(field_map[param].second.term_type) {
00482             case Vocabulary::TYPE_NULL:
00483             case Vocabulary::TYPE_OBJECT:
00484                 break;
00485             case Vocabulary::TYPE_INT8:
00486             case Vocabulary::TYPE_INT16:
00487             case Vocabulary::TYPE_INT32:
00488                 e->setInt(field_map[param].second.term_ref, fetchInt(param));
00489                 break;
00490             case Vocabulary::TYPE_INT64:
00491                 e->setBigInt(field_map[param].second.term_ref, fetchBigInt(param));
00492                 break;
00493             case Vocabulary::TYPE_UINT8:
00494             case Vocabulary::TYPE_UINT16:
00495             case Vocabulary::TYPE_UINT32:
00496                 e->setUInt(field_map[param].second.term_ref, fetchUInt(param));
00497                 break;
00498             case Vocabulary::TYPE_UINT64:
00499                 e->setUBigInt(field_map[param].second.term_ref, fetchUBigInt(param));
00500                 break;
00501             case Vocabulary::TYPE_FLOAT:
00502                 e->setFloat(field_map[param].second.term_ref, fetchFloat(param));
00503                 break;
00504             case Vocabulary::TYPE_DOUBLE:
00505                 e->setDouble(field_map[param].second.term_ref, fetchDouble(param));
00506                 break;
00507             case Vocabulary::TYPE_LONG_DOUBLE:
00508                 e->setLongDouble(field_map[param].second.term_ref, fetchLongDouble(param));
00509                 break;
00510             case Vocabulary::TYPE_SHORT_STRING:
00511             case Vocabulary::TYPE_STRING:
00512             case Vocabulary::TYPE_LONG_STRING:
00513             case Vocabulary::TYPE_CHAR:
00514                 {
00515                     std::string val;
00516                     fetchString(param, val);
00517                     e->setString(field_map[param].second.term_ref, val);
00518                 }
00519                 break;
00520             case Vocabulary::TYPE_BLOB:
00521                 {
00522                     std::string val;
00523                     fetchBlob(param, val);
00524                     e->setString(field_map[param].second.term_ref, val.c_str(), val.size());
00525                 }
00526                 break;
00527             case Vocabulary::TYPE_ZBLOB:
00528                 {
00529                     std::string val;
00530                     fetchZBlob(param, val);
00531                     e->setString(field_map[param].second.term_ref, val.c_str(), val.size());
00532                 }
00533                 break;
00534             case Vocabulary::TYPE_DATE_TIME:
00535                 {
00536                     PionDateTime val;
00537                     fetchDateTime(param, val);
00538                     e->setDateTime(field_map[param].second.term_ref, val);
00539                 }
00540                 break;
00541             case Vocabulary::TYPE_DATE:
00542                 {
00543                     PionDateTime val;
00544                     fetchDate(param, val);
00545                     e->setDateTime(field_map[param].second.term_ref, val);
00546                 }
00547                 break;
00548             case Vocabulary::TYPE_TIME:
00549                 {
00550                     PionDateTime val;
00551                     fetchTime(param, val);
00552                     e->setDateTime(field_map[param].second.term_ref, val);
00553                 }
00554                 break;
00555         }
00556     }
00557 }
00558 
00559 
00561 typedef std::string                     QueryID;
00562 
00563 
00565 typedef boost::shared_ptr<Query>        QueryPtr;
00566 
00567 
00568 }   // end namespace platform
00569 }   // end namespace pion
00570 
00571 #endif

Generated on Wed Apr 13 16:38:34 2011 for pion-platform by  doxygen 1.4.7