00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #if !defined(MYSQLPP_QUERY_H)
00029 #define MYSQLPP_QUERY_H
00030
00031 #include "common.h"
00032
00033 #include "exceptions.h"
00034 #include "noexceptions.h"
00035 #include "qparms.h"
00036 #include "querydef.h"
00037 #include "result.h"
00038 #include "row.h"
00039 #include "sqlstream.h"
00040 #include "stadapter.h"
00041 #include "transaction.h"
00042
00043 #include <deque>
00044 #include <iomanip>
00045 #include <list>
00046 #include <map>
00047 #include <set>
00048 #include <vector>
00049
00050 #ifdef HAVE_EXT_SLIST
00051 # include <ext/slist>
00052 #else
00053 # if defined(HAVE_STD_SLIST) || defined(HAVE_GLOBAL_SLIST)
00054 # include <slist>
00055 # endif
00056 #endif
00057
00058 namespace mysqlpp {
00059
00060 #if !defined(DOXYGEN_IGNORE)
00061
00062 class MYSQLPP_EXPORT Connection;
00063 class MYSQLPP_EXPORT Transaction;
00064 #endif
00065
00120
00121 class MYSQLPP_EXPORT Query :
00122 public std::ostream,
00123 public OptionalExceptions
00124 {
00125 public:
00126 #if !defined(DOXYGEN_IGNORE)
00127
00128
00129 #include "insertpolicy.h"
00130 #endif
00131
00139 Query(Connection* c, bool te = true, const char* qstr = 0);
00140
00148 Query(const Query& q);
00149
00151 ulonglong affected_rows();
00152
00167 size_t escape_string(std::string* ps, const char* original = 0,
00168 size_t length = 0) const;
00169
00191 size_t escape_string(char* escaped, const char* original,
00192 size_t length) const;
00193
00198 int errnum() const;
00199
00204 const char* error() const;
00205
00208 std::string info();
00209
00220 ulonglong insert_id();
00221
00226 Query& operator=(const Query& rhs);
00227
00246 operator void*() const;
00247
00255 bool operator !() const { return !operator void*(); }
00256
00264 void parse();
00265
00275 void reset();
00276
00280 bool result_empty();
00281
00283 std::string str() { return str(template_defaults); }
00284
00298 std::string str(const SQLTypeAdapter& arg0)
00299 { return str(SQLQueryParms() << arg0); }
00300
00305 std::string str(SQLQueryParms& p);
00306
00317 bool exec() { return exec(str(template_defaults)); }
00318
00330 bool exec(const std::string& str);
00331
00348 SimpleResult execute();
00349
00358 SimpleResult execute(SQLQueryParms& p);
00359
00376 SimpleResult execute(const SQLTypeAdapter& str);
00377
00382 SimpleResult execute(const char* str, size_t len);
00383
00409 UseQueryResult use();
00410
00420 UseQueryResult use(SQLQueryParms& p);
00421
00439 UseQueryResult use(const SQLTypeAdapter& str);
00440
00450 UseQueryResult use(const char* str, size_t len);
00451
00473 StoreQueryResult store();
00474
00483 StoreQueryResult store(SQLQueryParms& p);
00484
00502 StoreQueryResult store(const SQLTypeAdapter& str);
00503
00513 StoreQueryResult store(const char* str, size_t len);
00514
00525 template <typename Function>
00526 Function for_each(const SQLTypeAdapter& query, Function fn)
00527 {
00528 mysqlpp::UseQueryResult res = use(query);
00529 if (res) {
00530 mysqlpp::NoExceptions ne(res);
00531 while (mysqlpp::Row row = res.fetch_row()) {
00532 fn(row);
00533 }
00534 }
00535
00536 return fn;
00537 }
00538
00546 template <typename Function>
00547 Function for_each(Function fn)
00548 {
00549 mysqlpp::UseQueryResult res = use();
00550 if (res) {
00551 mysqlpp::NoExceptions ne(res);
00552 while (mysqlpp::Row row = res.fetch_row()) {
00553 fn(row);
00554 }
00555 }
00556
00557 return fn;
00558 }
00559
00570 template <class SSQLS, typename Function>
00571 Function for_each(const SSQLS& ssqls, Function fn)
00572 {
00573 std::string query("select * from `");
00574 query += ssqls.table();
00575 query += '`';
00576 mysqlpp::UseQueryResult res = use(query);
00577 if (res) {
00578 mysqlpp::NoExceptions ne(res);
00579 while (mysqlpp::Row row = res.fetch_row()) {
00580 fn(row);
00581 }
00582 }
00583
00584 return fn;
00585 }
00586
00606 template <class Sequence, typename Function>
00607 Function store_if(Sequence& con, const SQLTypeAdapter& query, Function fn)
00608 {
00609 mysqlpp::UseQueryResult res = use(query);
00610 if (res) {
00611 mysqlpp::NoExceptions ne(res);
00612 while (mysqlpp::Row row = res.fetch_row()) {
00613 if (fn(row)) {
00614 con.push_back(row);
00615 }
00616 }
00617 }
00618
00619 return fn;
00620 }
00621
00633 template <class Sequence, class SSQLS, typename Function>
00634 Function store_if(Sequence& con, const SSQLS& ssqls, Function fn)
00635 {
00636 std::string query("select * from `");
00637 query += ssqls.table();
00638 query += '`';
00639 mysqlpp::UseQueryResult res = use(query);
00640 if (res) {
00641 mysqlpp::NoExceptions ne(res);
00642 while (mysqlpp::Row row = res.fetch_row()) {
00643 if (fn(row)) {
00644 con.push_back(row);
00645 }
00646 }
00647 }
00648
00649 return fn;
00650 }
00651
00661 template <class Sequence, typename Function>
00662 Function store_if(Sequence& con, Function fn)
00663 {
00664 mysqlpp::UseQueryResult res = use();
00665 if (res) {
00666 mysqlpp::NoExceptions ne(res);
00667 while (mysqlpp::Row row = res.fetch_row()) {
00668 if (fn(row)) {
00669 con.push_back(row);
00670 }
00671 }
00672 }
00673
00674 return fn;
00675 }
00676
00703 StoreQueryResult store_next();
00704
00716 bool more_results();
00717
00734 template <class Sequence>
00735 void storein_sequence(Sequence& con)
00736 {
00737 storein_sequence(con, str(template_defaults));
00738 }
00739
00753 template <class Sequence>
00754 void storein_sequence(Sequence& con, const SQLTypeAdapter& s)
00755 {
00756 if (UseQueryResult result = use(s)) {
00757 while (1) {
00758 MYSQL_ROW d = result.fetch_raw_row();
00759 if (!d) break;
00760 Row row(d, &result, result.fetch_lengths(),
00761 throw_exceptions());
00762 if (!row) break;
00763 con.push_back(typename Sequence::value_type(row));
00764 }
00765 }
00766 else if (!result_empty()) {
00767
00768
00769
00770
00771
00772
00773 copacetic_ = false;
00774 if (throw_exceptions()) {
00775 throw UseQueryError("Bogus empty result");
00776 }
00777 }
00778
00779
00780 }
00781
00792 template <class Seq>
00793 void storein_sequence(Seq& con, SQLQueryParms& p)
00794 {
00795 storein_sequence(con, str(p));
00796 }
00797
00805 template <class Set>
00806 void storein_set(Set& con)
00807 {
00808 storein_set(con, str(template_defaults));
00809 }
00810
00824 template <class Set>
00825 void storein_set(Set& con, const SQLTypeAdapter& s)
00826 {
00827 if (UseQueryResult result = use(s)) {
00828 while (1) {
00829 MYSQL_ROW d = result.fetch_raw_row();
00830 if (!d) break;
00831 Row row(d, &result, result.fetch_lengths(),
00832 throw_exceptions());
00833 if (!row) break;
00834 con.insert(typename Set::value_type(row));
00835 }
00836 }
00837 else if (!result_empty()) {
00838
00839
00840
00841
00842
00843
00844 copacetic_ = false;
00845 if (throw_exceptions()) {
00846 throw UseQueryError("Bogus empty result");
00847 }
00848 }
00849
00850
00851 }
00852
00863 template <class Set>
00864 void storein_set(Set& con, SQLQueryParms& p)
00865 {
00866 storein_set(con, str(p));
00867 }
00868
00887 template <class Container>
00888 void storein(Container& con)
00889 {
00890 storein(con, str(template_defaults));
00891 }
00892
00899 template <class T>
00900 void storein(T& con, SQLQueryParms& p)
00901 {
00902 storein(con, str(p));
00903 }
00904
00906 template <class T>
00907 void storein(std::vector<T>& con, const SQLTypeAdapter& s)
00908 {
00909 storein_sequence(con, s);
00910 }
00911
00913 template <class T>
00914 void storein(std::deque<T>& con, const SQLTypeAdapter& s)
00915 {
00916 storein_sequence(con, s);
00917 }
00918
00920 template <class T>
00921 void storein(std::list<T>& con, const SQLTypeAdapter& s)
00922 {
00923 storein_sequence(con, s);
00924 }
00925
00926 #if defined(HAVE_EXT_SLIST)
00929 template <class T>
00930 void storein(__gnu_cxx::slist<T>& con, const SQLTypeAdapter& s)
00931 {
00932 storein_sequence(con, s);
00933 }
00934 #elif defined(HAVE_GLOBAL_SLIST)
00941 template <class T>
00942 void storein(slist<T>& con, const SQLTypeAdapter& s)
00943 {
00944 storein_sequence(con, s);
00945 }
00946 #elif defined(HAVE_STD_SLIST)
00952 template <class T>
00953 void storein(std::slist<T>& con, const SQLTypeAdapter& s)
00954 {
00955 storein_sequence(con, s);
00956 }
00957 #endif
00958
00960 template <class T>
00961 void storein(std::set<T>& con, const SQLTypeAdapter& s)
00962 {
00963 storein_set(con, s);
00964 }
00965
00967 template <class T>
00968 void storein(std::multiset<T>& con, const SQLTypeAdapter& s)
00969 {
00970 storein_set(con, s);
00971 }
00972
00983 template <class T>
00984 Query& update(const T& o, const T& n)
00985 {
00986 reset();
00987
00988
00989
00990
00991 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
00992 "UPDATE `" << o.table() << "` SET " << n.equal_list() <<
00993 " WHERE " << o.equal_list(" AND ", sql_use_compare);
00994 return *this;
00995 }
00996
01005 template <class T>
01006 Query& insert(const T& v)
01007 {
01008 reset();
01009
01010 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
01011 "INSERT INTO `" << v.table() << "` (" <<
01012 v.field_list() << ") VALUES (" <<
01013 v.value_list() << ')';
01014 return *this;
01015 }
01016
01030 template <class Iter>
01031 Query& insert(Iter first, Iter last)
01032 {
01033 reset();
01034
01035 if (first != last) {
01036
01037
01038 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
01039 "INSERT INTO `" << first->table() << "` (" <<
01040 first->field_list() << ") VALUES (" <<
01041 first->value_list() << ')';
01042
01043
01044
01045
01046 Iter it = first;
01047 while (++it != last) {
01048 MYSQLPP_QUERY_THISPTR << ",(" << it->value_list() << ')';
01049 }
01050 }
01051
01052 return *this;
01053 }
01054
01067 template <class Iter, class InsertPolicy>
01068 Query& insertfrom(Iter first, Iter last, InsertPolicy& policy)
01069 {
01070 bool success = true;
01071 bool empty = true;
01072
01073 reset();
01074
01075 if (first == last) {
01076 return *this;
01077 }
01078
01079 typename InsertPolicy::access_controller ac(*conn_);
01080
01081 for (Iter it = first; it != last; ++it) {
01082 if (policy.can_add(int(tellp()), *it)) {
01083 if (empty) {
01084 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
01085 "INSERT INTO `" << it->table() << "` (" <<
01086 it->field_list() << ") VALUES (";
01087 }
01088 else {
01089 MYSQLPP_QUERY_THISPTR << ",(";
01090 }
01091
01092 MYSQLPP_QUERY_THISPTR << it->value_list() << ')';
01093
01094 empty = false;
01095 }
01096 else {
01097
01098 if (!empty) {
01099 if (!exec()) {
01100 success = false;
01101 break;
01102 }
01103
01104 empty = true;
01105 }
01106
01107
01108 if (policy.can_add(int(tellp()), *it)) {
01109 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
01110 "INSERT INTO `" << it->table() << "` (" <<
01111 it->field_list() << ") VALUES (" <<
01112 it->value_list() << ')';
01113
01114 empty = false;
01115 }
01116 else {
01117
01118 if (throw_exceptions()) {
01119 throw BadInsertPolicy("Insert policy is too strict");
01120 }
01121
01122 success = false;
01123 break;
01124 }
01125 }
01126 }
01127
01128
01129 if (success && !empty && !exec()) {
01130 success = false;
01131 }
01132
01133 if (success) {
01134 ac.commit();
01135 }
01136 else {
01137 ac.rollback();
01138 }
01139
01140 return *this;
01141 }
01142
01155 template <class Iter, class InsertPolicy>
01156 Query& replacefrom(Iter first, Iter last, InsertPolicy& policy)
01157 {
01158 bool success = true;
01159 bool empty = true;
01160
01161 reset();
01162
01163 if (first == last) {
01164 return *this;
01165 }
01166
01167 typename InsertPolicy::access_controller ac(*conn_);
01168
01169 for (Iter it = first; it != last; ++it) {
01170 if (policy.can_add(int(tellp()), *it)) {
01171 if (empty) {
01172 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
01173 "REPLACE INTO `" << it->table() << "` (" <<
01174 it->field_list() << ") VALUES (";
01175 }
01176 else {
01177 MYSQLPP_QUERY_THISPTR << ",(";
01178 }
01179
01180 MYSQLPP_QUERY_THISPTR << it->value_list() << ')';
01181
01182 empty = false;
01183 }
01184 else {
01185
01186 if (!empty) {
01187 if (!exec()) {
01188 success = false;
01189 break;
01190 }
01191
01192 empty = true;
01193 }
01194
01195
01196 if (policy.can_add(int(tellp()), *it)) {
01197 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
01198 "REPLACE INTO `" << it->table() << "` (" <<
01199 it->field_list() << ") VALUES (" <<
01200 it->value_list() << ')';
01201
01202 empty = false;
01203 }
01204 else {
01205
01206 if (throw_exceptions()) {
01207 throw BadInsertPolicy("Insert policy is too strict");
01208 }
01209
01210 success = false;
01211 break;
01212 }
01213 }
01214 }
01215
01216
01217 if (success && !empty && !exec()) {
01218 success = false;
01219 }
01220
01221 if (success) {
01222 ac.commit();
01223 }
01224 else {
01225 ac.rollback();
01226 }
01227
01228 return *this;
01229 }
01230
01240 template <class T>
01241 Query& replace(const T& v)
01242 {
01243 reset();
01244
01245 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
01246 "REPLACE INTO `" << v.table() << "` (" <<
01247 v.field_list() << ") VALUES (" << v.value_list() << ')';
01248 return *this;
01249 }
01250
01265 template <class Iter>
01266 Query& replace(Iter first, Iter last)
01267 {
01268 reset();
01269 if (first != last) {
01270
01271
01272 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
01273 "REPLACE INTO " << first->table() << " (" <<
01274 first->field_list() << ") VALUES (" <<
01275 first->value_list() << ')';
01276
01277
01278
01279
01280 Iter it = first;
01281 while (++it != last) {
01282 MYSQLPP_QUERY_THISPTR << ",(" << it->value_list() << ')';
01283 }
01284 }
01285
01286 return *this;
01287 }
01288
01289 #if !defined(DOXYGEN_IGNORE)
01290
01291
01292
01293
01294 mysql_query_define0(std::string, str)
01295 mysql_query_define0(SimpleResult, execute)
01296 mysql_query_define0(StoreQueryResult, store)
01297 mysql_query_define0(UseQueryResult, use)
01298 mysql_query_define1(storein_sequence)
01299 mysql_query_define1(storein_set)
01300 mysql_query_define1(storein)
01301 #endif // !defined(DOXYGEN_IGNORE)
01302
01306 SQLQueryParms template_defaults;
01307
01308 private:
01309 friend class SQLQueryParms;
01310
01312 Connection* conn_;
01313
01315 bool copacetic_;
01316
01318 std::vector<SQLParseElement> parse_elems_;
01319
01322 std::vector<std::string> parsed_names_;
01323
01325 std::map<std::string, short int> parsed_nums_;
01326
01328 std::stringbuf sbuffer_;
01329
01331 void proc(SQLQueryParms& p);
01332
01333 SQLTypeAdapter* pprepare(char option, SQLTypeAdapter& S, bool replace = true);
01334 };
01335
01336
01340 inline std::ostream& operator <<(std::ostream& os, Query& q)
01341 {
01342 return os << q.str();
01343 }
01344
01345
01346 }
01347
01348 #endif // !defined(MYSQLPP_QUERY_H)
01349