# query.h

Go to the documentation of this file.

    00001
    00002
    00003
    00004 /***********************************************************************
    00005  Copyright (c) 1998 by Kevin Atkinson, (c) 1999-2001 by MySQL AB, and
    00006  (c) 2004-2009 by Educational Technology Resources, Inc.  Others may
    00007  also hold copyrights on code in this file.  See the CREDITS.txt file
    00008  in the top directory of the distribution for details.
    00009
    00010  This file is part of MySQL++.
    00011
    00012  MySQL++ is free software; you can redistribute it and/or modify it
    00013  under the terms of the GNU Lesser General Public License as published
    00014  by the Free Software Foundation; either version 2.1 of the License, or
    00015  (at your option) any later version.
    00016
    00017  MySQL++ is distributed in the hope that it will be useful, but WITHOUT
    00018  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    00019  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
    00020  License for more details.
    00021
    00022  You should have received a copy of the GNU Lesser General Public
    00023  License along with MySQL++; if not, write to the Free Software
    00024  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
    00025  USA
    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 // Make Doxygen ignore this
    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         // Bring in InsertPolicy template as part of this class's interface,
    00128         // separate only in the sense that it's a self-contained concept.
    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
    00278         std::string str() { return str(template_defaults); }
    00279
    00293         std::string str(const SQLTypeAdapter& arg0)
    00294                         { return str(SQLQueryParms() << arg0); }
    00295
    00300         std::string str(SQLQueryParms& p);
    00301
    00312         bool exec() { return exec(str(template_defaults)); }
    00313
    00325         bool exec(const std::string& str);
    00326
    00343         SimpleResult execute();
    00344
    00353         SimpleResult execute(SQLQueryParms& p);
    00354
    00371         SimpleResult execute(const SQLTypeAdapter& str);
    00372
    00377         SimpleResult execute(const char* str, size_t len);
    00378
    00404         UseQueryResult use();
    00405
    00415         UseQueryResult use(SQLQueryParms& p);
    00416
    00434         UseQueryResult use(const SQLTypeAdapter& str);
    00435
    00445         UseQueryResult use(const char* str, size_t len);
    00446
    00468         StoreQueryResult store();
    00469
    00478         StoreQueryResult store(SQLQueryParms& p);
    00479
    00497         StoreQueryResult store(const SQLTypeAdapter& str);
    00498
    00508         StoreQueryResult store(const char* str, size_t len);
    00509
    00520         template <typename Function>
    00521         Function for_each(const SQLTypeAdapter& query, Function fn)
    00522         {
    00523                 mysqlpp::UseQueryResult res = use(query);
    00524                 if (res) {
    00525                         mysqlpp::NoExceptions ne(res);
    00526                         while (mysqlpp::Row row = res.fetch_row()) {
    00527                                 fn(row);
    00528                         }
    00529                 }
    00530
    00531                 return fn;
    00532         }
    00533
    00541         template <typename Function>
    00542         Function for_each(Function fn)
    00543         {
    00544                 mysqlpp::UseQueryResult res = use();
    00545                 if (res) {
    00546                         mysqlpp::NoExceptions ne(res);
    00547                         while (mysqlpp::Row row = res.fetch_row()) {
    00548                                 fn(row);
    00549                         }
    00550                 }
    00551
    00552                 return fn;
    00553         }
    00554
    00565         template <class SSQLS, typename Function>
    00566         Function for_each(const SSQLS& ssqls, Function fn)
    00567         {
    00568                 std::string query("select * from `");
    00569                 query += ssqls.table();
    00570       query += '`';
    00571                 mysqlpp::UseQueryResult res = use(query);
    00572                 if (res) {
    00573                         mysqlpp::NoExceptions ne(res);
    00574                         while (mysqlpp::Row row = res.fetch_row()) {
    00575                                 fn(row);
    00576                         }
    00577                 }
    00578
    00579                 return fn;
    00580         }
    00581
    00601         template <class Sequence, typename Function>
    00602         Function store_if(Sequence& con, const SQLTypeAdapter& query, Function fn)
    00603         {
    00604                 mysqlpp::UseQueryResult res = use(query);
    00605                 if (res) {
    00606                         mysqlpp::NoExceptions ne(res);
    00607                         while (mysqlpp::Row row = res.fetch_row()) {
    00608                                 if (fn(row)) {
    00609                                         con.push_back(row);
    00610                                 }
    00611                         }
    00612                 }
    00613
    00614                 return fn;
    00615         }
    00616
    00628         template <class Sequence, class SSQLS, typename Function>
    00629         Function store_if(Sequence& con, const SSQLS& ssqls, Function fn)
    00630         {
    00631                 std::string query("select * from `");
    00632                 query += ssqls.table();
    00633       query += '`';
    00634                 mysqlpp::UseQueryResult res = use(query);
    00635                 if (res) {
    00636                         mysqlpp::NoExceptions ne(res);
    00637                         while (mysqlpp::Row row = res.fetch_row()) {
    00638                                 if (fn(row)) {
    00639                                         con.push_back(row);
    00640                                 }
    00641                         }
    00642                 }
    00643
    00644                 return fn;
    00645         }
    00646
    00656         template <class Sequence, typename Function>
    00657         Function store_if(Sequence& con, Function fn)
    00658         {
    00659                 mysqlpp::UseQueryResult res = use();
    00660                 if (res) {
    00661                         mysqlpp::NoExceptions ne(res);
    00662                         while (mysqlpp::Row row = res.fetch_row()) {
    00663                                 if (fn(row)) {
    00664                                         con.push_back(row);
    00665                                 }
    00666                         }
    00667                 }
    00668
    00669                 return fn;
    00670         }
    00671
    00698         StoreQueryResult store_next();
    00699
    00711         bool more_results();
    00712
    00729         template <class Sequence>
    00730         void storein_sequence(Sequence& con)
    00731         {
    00732                 storein_sequence(con, str(template_defaults));
    00733         }
    00734
    00748         template <class Sequence>
    00749         void storein_sequence(Sequence& con, const SQLTypeAdapter& s)
    00750         {
    00751                 UseQueryResult result = use(s);
    00752                 while (1) {
    00753                         MYSQL_ROW d = result.fetch_raw_row();
    00754                         if (!d)
    00755                                 break;
    00756                         Row row(d, &result, result.fetch_lengths(),
    00757                                         throw_exceptions());
    00758                         if (!row)
    00759                                 break;
    00760                         con.push_back(typename Sequence::value_type(row));
    00761                 }
    00762         }
    00763
    00774         template <class Seq>
    00775         void storein_sequence(Seq& con, SQLQueryParms& p)
    00776         {
    00777                 storein_sequence(con, str(p));
    00778         }
    00779
    00787         template <class Set>
    00788         void storein_set(Set& con)
    00789         {
    00790                 storein_set(con, str(template_defaults));
    00791         }
    00792
    00806         template <class Set>
    00807         void storein_set(Set& con, const SQLTypeAdapter& s)
    00808         {
    00809                 UseQueryResult result = use(s);
    00810                 while (1) {
    00811                         MYSQL_ROW d = result.fetch_raw_row();
    00812                         if (!d)
    00813                                 return;
    00814                         Row row(d, &result, result.fetch_lengths(),
    00815                                         throw_exceptions());
    00816                         if (!row)
    00817                                 break;
    00818                         con.insert(typename Set::value_type(row));
    00819                 }
    00820         }
    00821
    00832         template <class Set>
    00833         void storein_set(Set& con, SQLQueryParms& p)
    00834         {
    00835                 storein_set(con, str(p));
    00836         }
    00837
    00856         template <class Container>
    00857         void storein(Container& con)
    00858         {
    00859                 storein(con, str(template_defaults));
    00860         }
    00861
    00868         template <class T>
    00869         void storein(T& con, SQLQueryParms& p)
    00870         {
    00871                 storein(con, str(p));
    00872         }
    00873
    00875         template <class T>
    00876         void storein(std::vector<T>& con, const SQLTypeAdapter& s)
    00877         {
    00878                 storein_sequence(con, s);
    00879         }
    00880
    00882         template <class T>
    00883         void storein(std::deque<T>& con, const SQLTypeAdapter& s)
    00884         {
    00885                 storein_sequence(con, s);
    00886         }
    00887
    00889         template <class T>
    00890         void storein(std::list<T>& con, const SQLTypeAdapter& s)
    00891         {
    00892                 storein_sequence(con, s);
    00893         }
    00894
    00895 #if defined(HAVE_EXT_SLIST)
    00898         template <class T>
    00899         void storein(__gnu_cxx::slist<T>& con, const SQLTypeAdapter& s)
    00900         {
    00901                 storein_sequence(con, s);
    00902         }
    00903 #elif defined(HAVE_GLOBAL_SLIST)
    00910         template <class T>
    00911         void storein(slist<T>& con, const SQLTypeAdapter& s)
    00912         {
    00913                 storein_sequence(con, s);
    00914         }
    00915 #elif defined(HAVE_STD_SLIST)
    00921         template <class T>
    00922         void storein(std::slist<T>& con, const SQLTypeAdapter& s)
    00923         {
    00924                 storein_sequence(con, s);
    00925         }
    00926 #endif
    00927
    00929         template <class T>
    00930         void storein(std::set<T>& con, const SQLTypeAdapter& s)
    00931         {
    00932                 storein_set(con, s);
    00933         }
    00934
    00936         template <class T>
    00937         void storein(std::multiset<T>& con, const SQLTypeAdapter& s)
    00938         {
    00939                 storein_set(con, s);
    00940         }
    00941
    00952         template <class T>
    00953         Query& update(const T& o, const T& n)
    00954         {
    00955                 reset();
    00956
    00957                 // Cast required for VC++ 2003 due to error in overloaded operator
    00958                 // lookup logic.  For an explanation of the problem, see:
    00959                 // http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15
    00960                 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    00961                                 "UPDATE `" << o.table() << "` SET " << n.equal_list() <<
    00962                                 " WHERE " << o.equal_list(" AND ", sql_use_compare);
    00963                 return *this;
    00964         }
    00965
    00974         template <class T>
    00975         Query& insert(const T& v)
    00976         {
    00977                 reset();
    00978
    00979                 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    00980                                 "INSERT INTO `" << v.table() << "` (" <<
    00981                                 v.field_list() << ") VALUES (" <<
    00982                                 v.value_list() << ')';
    00983                 return *this;
    00984         }
    00985
    00999         template <class Iter>
    01000         Query& insert(Iter first, Iter last)
    01001         {
    01002                 reset();
    01003                 if (first == last) {
    01004                         return *this;   // empty set!
    01005                 }
    01006
    01007                 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    01008                                 "INSERT INTO `" << first->table() << "` (" <<
    01009                                 first->field_list() << ") VALUES (" <<
    01010                                 first->value_list() << ')';
    01011
    01012                 Iter it = first + 1;
    01013                 while (it != last) {
    01014                         MYSQLPP_QUERY_THISPTR << ",(" << it->value_list() << ')';
    01015                         ++it;
    01016                 }
    01017
    01018                 return *this;
    01019         }
    01020
    01033         template <class Iter, class InsertPolicy>
    01034         Query& insertfrom(Iter first, Iter last, InsertPolicy& policy)
    01035         {
    01036                 bool success = true;
    01037                 bool empty = true;
    01038
    01039                 reset();
    01040
    01041                 if (first == last) {
    01042                         return *this;   // empty set!
    01043                 }
    01044
    01045                 typename InsertPolicy::access_controller ac(*conn_);
    01046
    01047                 for (Iter it = first; it != last; ++it) {
    01048                         if (policy.can_add(int(tellp()), *it)) {
    01049                                 if (empty) {
    01050                                         MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    01051                                                 "INSERT INTO `" << it->table() << "` (" <<
    01052                                                 it->field_list() << ") VALUES (";
    01053                                 }
    01054                                 else {
    01055                                         MYSQLPP_QUERY_THISPTR << ",(";
    01056                                 }
    01057
    01058                                 MYSQLPP_QUERY_THISPTR << it->value_list() << ')';
    01059
    01060                                 empty = false;
    01061                         }
    01062                         else {
    01063                                 // Execute what we've built up already, if there is anything
    01064                                 if (!empty) {
    01065                                         if (!exec()) {
    01066                                                 success = false;
    01067                                                 break;
    01068                                         }
    01069
    01070                                         empty = true;
    01071                                 }
    01072
    01073                                 // If we _still_ can't add, the policy is too strict
    01074                                 if (policy.can_add(int(tellp()), *it)) {
    01075                                         MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    01076                                                 "INSERT INTO `" << it->table() << "` (" <<
    01077                                                 it->field_list() << ") VALUES (" <<
    01078                                                 it->value_list() << ')';
    01079
    01080                                         empty = false;
    01081                                 }
    01082                                 else {
    01083                                         // At this point all we can do is give up
    01084                                         if (throw_exceptions()) {
    01085                                                 throw BadInsertPolicy("Insert policy is too strict");
    01086                                         }
    01087
    01088                                         success = false;
    01089                                         break;
    01090                                 }
    01091                         }
    01092                 }
    01093
    01094                 // We might need to execute the last query here.
    01095                 if (success && !empty && !exec()) {
    01096                         success = false;
    01097                 }
    01098
    01099                 if (success) {
    01100                         ac.commit();
    01101                 }
    01102                 else {
    01103                         ac.rollback();
    01104                 }
    01105
    01106                 return *this;
    01107         }
    01108
    01118         template <class T>
    01119         Query& replace(const T& v)
    01120         {
    01121                 reset();
    01122
    01123                 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    01124                                 "REPLACE INTO `" << v.table() << "` (" <<
    01125                                 v.field_list() << ") VALUES (" << v.value_list() << ')';
    01126                 return *this;
    01127         }
    01128
    01143         template <class Iter>
    01144         Query& replace(Iter first, Iter last)
    01145         {
    01146                 reset();
    01147                 if (first == last) {
    01148                         return *this;    // empty set!
    01149                 }
    01150
    01151                 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    01152                                 "REPLACE INTO " << first->table() << " (" <<
    01153                                 first->field_list() << ") VALUES (" <<
    01154                                 first->value_list() << ')';
    01155
    01156                 Iter it = first + 1;
    01157                 while (it != last) {
    01158                         MYSQLPP_QUERY_THISPTR << ",(" << it->value_list() << ')';
    01159                         ++it;
    01160                 }
    01161
    01162                 return *this;
    01163         }
    01164
    01165 #if !defined(DOXYGEN_IGNORE)
    01166         // Declare the remaining overloads.  These are hidden down here partly
    01167         // to keep the above code clear, but also so that we may hide them
    01168         // from Doxygen, which gets confused by macro instantiations that look
    01169         // like method declarations.
    01170         mysql_query_define0(std::string, str)
    01171         mysql_query_define0(SimpleResult, execute)
    01172         mysql_query_define0(StoreQueryResult, store)
    01173         mysql_query_define0(UseQueryResult, use)
    01174         mysql_query_define1(storein_sequence)
    01175         mysql_query_define1(storein_set)
    01176         mysql_query_define1(storein)
    01177 #endif // !defined(DOXYGEN_IGNORE)
    01178
    01182         SQLQueryParms template_defaults;
    01183
    01184 private:
    01185         friend class SQLQueryParms;
    01186
    01188         Connection* conn_;
    01189
    01191         bool copacetic_;
    01192
    01194         std::vector<SQLParseElement> parse_elems_;
    01195
    01198         std::vector<std::string> parsed_names_;
    01199
    01201         std::map<std::string, short int> parsed_nums_;
    01202
    01204         std::stringbuf sbuffer_;
    01205
    01207         void proc(SQLQueryParms& p);
    01208
    01209         SQLTypeAdapter* pprepare(char option, SQLTypeAdapter& S, bool replace = true);
    01210 };
    01211
    01212
    01216 inline std::ostream& operator <<(std::ostream& os, Query& q)
    01217 {
    01218         return os << q.str();
    01219 }
    01220
    01221
    01222 } // end namespace mysqlpp
    01223
    01224 #endif // !defined(MYSQLPP_QUERY_H)
    01225