00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __PION_QUERY_HEADER__
00021 #define __PION_QUERY_HEADER__
00022
00023 #ifdef _MSC_VER
00024
00025
00026
00027 #define BOOST_ZLIB_BINARY "zdll.lib"
00028 #endif
00029
00030 #include <cstdio>
00031 #include <string>
00032
00033
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 {
00047 namespace platform {
00048
00049
00050 class Database;
00051
00052
00056 class Query
00057 : private boost::noncopyable
00058 {
00059 public:
00060
00062
00063 typedef std::pair<std::string, Vocabulary::Term> FieldData;
00064
00066
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
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
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 }
00569 }
00570
00571 #endif