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 

Generated on Thu Jun 3 11:59:12 2010 for MySQL++ by  doxygen 1.4.7