# query.h

Go to the documentation of this file.

    00001
    00002
    00003
    00004 /***********************************************************************
    00005  Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by
    00006  MySQL AB, and (c) 2004-2006 by Educational Technology Resources, Inc.
    00007  Others may also hold copyrights on code in this file.  See the CREDITS
    00008  file 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 #ifndef MYSQLPP_QUERY_H
    00029 #define MYSQLPP_QUERY_H
    00030
    00031 #include "common.h"
    00032
    00033 #include "lockable.h"
    00034 #include "noexceptions.h"
    00035 #include "qparms.h"
    00036 #include "querydef.h"
    00037 #include "result.h"
    00038 #include "row.h"
    00039 #include "sql_string.h"
    00040
    00041 #include <deque>
    00042 #include <iomanip>
    00043 #include <list>
    00044 #include <map>
    00045 #include <set>
    00046 #include <sstream>
    00047 #include <vector>
    00048
    00049 #ifdef HAVE_EXT_SLIST
    00050 #  include <ext/slist>
    00051 #else
    00052 #  if defined(HAVE_STD_SLIST) || defined(HAVE_GLOBAL_SLIST)
    00053 #      include <slist>
    00054 #  endif
    00055 #endif
    00056
    00064 #if defined(_MSC_VER) && (_MSC_VER < 1400)
    00065 #       define MYSQLPP_QUERY_THISPTR dynamic_cast<std::ostream&>(*this)
    00066 #else
    00067 #       define MYSQLPP_QUERY_THISPTR *this
    00068 #endif
    00069
    00070 namespace mysqlpp {
    00071
    00072 #if !defined(DOXYGEN_IGNORE)
    00073 // Make Doxygen ignore this
    00074 class MYSQLPP_EXPORT Connection;
    00075 #endif
    00076
    00078 enum query_reset { DONT_RESET, RESET_QUERY };
    00079
    00128
    00129 class MYSQLPP_EXPORT Query : public std::ostream,
    00130                 public OptionalExceptions, public Lockable
    00131 {
    00132 public:
    00139         Query(Connection* c, bool te = true);
    00140
    00148         Query(const Query& q);
    00149
    00154         Query& operator=(const Query& rhs);
    00155
    00161         std::string error();
    00162
    00168         bool success();
    00169
    00177         void parse();
    00178
    00183         void reset();
    00184
    00186         std::string preview() { return str(def); }
    00187
    00193         std::string preview(const SQLString& arg0)
    00194                         { return preview(SQLQueryParms() << arg0); }
    00195
    00197         std::string preview(SQLQueryParms& p) { return str(p); }
    00198
    00200         std::string str() { return str(def); }
    00201
    00207         std::string str(const SQLString& arg0)
    00208                         { return preview(SQLQueryParms() << arg0); }
    00209
    00214         std::string str(query_reset r) { return str(def, r); }
    00215
    00220         std::string str(SQLQueryParms& p);
    00221
    00228         std::string str(SQLQueryParms& p, query_reset r);
    00229
    00241         bool exec(const std::string& str);
    00242
    00259         ResNSel execute() { return execute(def); }
    00260
    00267         ResNSel execute(const SQLString& str);
    00268
    00272         ResNSel execute(const char* str);
    00273
    00278         ResNSel execute(const char* str, size_t len);
    00279
    00304         ResUse use() { return use(def); }
    00305
    00311         ResUse use(const SQLString& str);
    00312
    00318         ResUse use(const char* str);
    00319
    00325         ResUse use(const char* str, size_t len);
    00326
    00348         Result store() { return store(def); }
    00349
    00355         Result store(const SQLString& str);
    00356
    00362         Result store(const char* str);
    00363
    00369         Result store(const char* str, size_t len);
    00370
    00381         template <typename Function>
    00382         Function for_each(const SQLString& query, Function fn)
    00383         {
    00384                 mysqlpp::ResUse res = use(query);
    00385                 if (res) {
    00386                         mysqlpp::NoExceptions ne(res);
    00387                         while (mysqlpp::Row row = res.fetch_row()) {
    00388                                 fn(row);
    00389                         }
    00390                 }
    00391
    00392                 return fn;
    00393         }
    00394
    00402         template <typename Function>
    00403         Function for_each(Function fn)
    00404         {
    00405                 mysqlpp::ResUse res = use();
    00406                 if (res) {
    00407                         mysqlpp::NoExceptions ne(res);
    00408                         while (mysqlpp::Row row = res.fetch_row()) {
    00409                                 fn(row);
    00410                         }
    00411                 }
    00412
    00413                 return fn;
    00414         }
    00415
    00426         template <class SSQLS, typename Function>
    00427         Function for_each(const SSQLS& ssqls, Function fn)
    00428         {
    00429                 SQLString query("select * from ");
    00430                 query += ssqls._table;
    00431                 mysqlpp::ResUse res = use(query);
    00432                 if (res) {
    00433                         mysqlpp::NoExceptions ne(res);
    00434                         while (mysqlpp::Row row = res.fetch_row()) {
    00435                                 fn(row);
    00436                         }
    00437                 }
    00438
    00439                 return fn;
    00440         }
    00441
    00461         template <class Sequence, typename Function>
    00462         Function store_if(Sequence& seq, const SQLString& query, Function fn)
    00463         {
    00464                 mysqlpp::ResUse res = use(query);
    00465                 if (res) {
    00466                         mysqlpp::NoExceptions ne(res);
    00467                         while (mysqlpp::Row row = res.fetch_row()) {
    00468                                 if (fn(row)) {
    00469                                         seq.push_back(row);
    00470                                 }
    00471                         }
    00472                 }
    00473
    00474                 return fn;
    00475         }
    00476
    00488         template <class Sequence, class SSQLS, typename Function>
    00489         Function store_if(Sequence& seq, const SSQLS& ssqls, Function fn)
    00490         {
    00491                 SQLString query("select * from ");
    00492                 query += ssqls._table;
    00493                 mysqlpp::ResUse res = use(query);
    00494                 if (res) {
    00495                         mysqlpp::NoExceptions ne(res);
    00496                         while (mysqlpp::Row row = res.fetch_row()) {
    00497                                 if (fn(row)) {
    00498                                         seq.push_back(row);
    00499                                 }
    00500                         }
    00501                 }
    00502
    00503                 return fn;
    00504         }
    00505
    00515         template <class Sequence, typename Function>
    00516         Function store_if(Sequence& seq, Function fn)
    00517         {
    00518                 mysqlpp::ResUse res = use();
    00519                 if (res) {
    00520                         mysqlpp::NoExceptions ne(res);
    00521                         while (mysqlpp::Row row = res.fetch_row()) {
    00522                                 if (fn(row)) {
    00523                                         seq.push_back(row);
    00524                                 }
    00525                         }
    00526                 }
    00527
    00528                 return fn;
    00529         }
    00530
    00557         Result store_next();
    00558
    00570         bool more_results();
    00571
    00589         template <class Sequence>
    00590         void storein_sequence(Sequence& con, query_reset r = RESET_QUERY)
    00591         {
    00592                 storein_sequence(con, def, r);
    00593         }
    00594
    00602         template <class Set>
    00603         void storein_set(Set& con, query_reset r = RESET_QUERY)
    00604         {
    00605                 storein_set(con, def, r);
    00606         }
    00607
    00626         template <class Container>
    00627         void storein(Container& con, query_reset r = RESET_QUERY)
    00628         {
    00629                 storein(con, def, r);
    00630         }
    00631
    00633         template <class T>
    00634         void storein(std::vector<T>& con, const char* s)
    00635         {
    00636                 storein_sequence(con, s);
    00637         }
    00638
    00640         template <class T>
    00641         void storein(std::deque<T>& con, const char* s)
    00642         {
    00643                 storein_sequence(con, s);
    00644         }
    00645
    00647         template <class T>
    00648         void storein(std::list<T>& con, const char* s)
    00649         {
    00650                 storein_sequence(con, s);
    00651         }
    00652
    00653 #if defined(HAVE_EXT_SLIST)
    00656         template <class T>
    00657         void storein(__gnu_cxx::slist<T>& con, const char* s)
    00658         {
    00659                 storein_sequence(con, s);
    00660         }
    00661 #elif defined(HAVE_GLOBAL_SLIST)
    00668         template <class T>
    00669         void storein(slist<T>& con, const char* s)
    00670         {
    00671                 storein_sequence(con, s);
    00672         }
    00673 #elif defined(HAVE_STD_SLIST)
    00679         template <class T>
    00680         void storein(std::slist<T>& con, const char* s)
    00681         {
    00682                 storein_sequence(con, s);
    00683         }
    00684 #endif
    00685
    00687         template <class T>
    00688         void storein(std::set<T>& con, const char* s)
    00689         {
    00690                 storein_set(con, s);
    00691         }
    00692
    00694         template <class T>
    00695         void storein(std::multiset<T>& con, const char* s)
    00696         {
    00697                 storein_set(con, s);
    00698         }
    00699
    00710         template <class T>
    00711         Query& update(const T& o, const T& n)
    00712         {
    00713                 reset();
    00714
    00715                 // Cast required for VC++ 2003 due to error in overloaded operator
    00716                 // lookup logic.  For an explanation of the problem, see:
    00717                 // http://groups-beta.google.com/group/microsoft.public.vc.stl/browse_thread/thread/9a68d84644e64f15
    00718                 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    00719                                 "UPDATE " << o.table() << " SET " << n.equal_list() <<
    00720                                 " WHERE " << o.equal_list(" AND ", sql_use_compare);
    00721                 return *this;
    00722         }
    00723
    00732         template <class T>
    00733         Query& insert(const T& v)
    00734         {
    00735                 reset();
    00736
    00737                 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    00738                                 "INSERT INTO " << v.table() << " (" <<
    00739                                 v.field_list() << ") VALUES (" <<
    00740                                 v.value_list() << ')';
    00741                 return *this;
    00742         }
    00743
    00757         template <class Iter>
    00758         Query& insert(Iter first, Iter last)
    00759         {
    00760                 reset();
    00761                 if (first == last) {
    00762                         return *this;   // empty set!
    00763                 }
    00764
    00765                 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    00766                                 "INSERT INTO " << first->table() << " (" <<
    00767                                 first->field_list() << ") VALUES (" <<
    00768                                 first->value_list() << ')';
    00769
    00770                 Iter it = first + 1;
    00771                 while (it != last) {
    00772                         MYSQLPP_QUERY_THISPTR << ",(" << it->value_list() << ')';
    00773                         ++it;
    00774                 }
    00775
    00776                 return *this;
    00777         }
    00778
    00788         template <class T>
    00789         Query& replace(const T& v)
    00790         {
    00791                 reset();
    00792
    00793                 MYSQLPP_QUERY_THISPTR << std::setprecision(16) <<
    00794                                 "REPLACE INTO " << v.table() << " (" <<
    00795                                 v.field_list() << ") VALUES (" << v.value_list() << ')';
    00796                 return *this;
    00797         }
    00798
    00800         operator bool() { return success(); }
    00801
    00803         bool operator !() { return !success(); }
    00804
    00805 #if !defined(DOXYGEN_IGNORE)
    00806         // Declare the remaining overloads.  These are hidden down here partly
    00807         // to keep the above code clear, but also so that we may hide them
    00808         // from Doxygen, which gets confused by macro instantiations that look
    00809         // like method declarations.
    00810         mysql_query_define0(std::string, preview)
    00811         mysql_query_define0(std::string, str)
    00812         mysql_query_define1(ResNSel, execute)
    00813         mysql_query_define1(Result, store)
    00814         mysql_query_define1(ResUse, use)
    00815         mysql_query_define2(storein_sequence)
    00816         mysql_query_define2(storein_set)
    00817         mysql_query_define2(storein)
    00818 #endif // !defined(DOXYGEN_IGNORE)
    00819
    00823         SQLQueryParms def;
    00824
    00825 private:
    00826         friend class SQLQueryParms;
    00827
    00829         Connection* conn_;
    00830
    00832         bool success_;
    00833
    00835         std::vector<SQLParseElement> parse_elems_;
    00836
    00839         std::vector<std::string> parsed_names_;
    00840
    00842         std::map<std::string, short int> parsed_nums_;
    00843
    00845         std::stringbuf sbuffer_;
    00846
    00848         my_ulonglong affected_rows() const;
    00849         my_ulonglong insert_id();
    00850         std::string info();
    00851         char* preview_char();
    00852
    00854         void proc(SQLQueryParms& p);
    00855
    00856         // Locking mechanism
    00857         bool lock();
    00858         void unlock();
    00859
    00860         SQLString* pprepare(char option, SQLString& S, bool replace = true);
    00861 };
    00862
    00863
    00864 #if !defined(DOXYGEN_IGNORE)
    00865 // Doxygen will not generate documentation for this section.
    00866
    00867 template <class Seq>
    00868 void Query::storein_sequence(Seq& seq, SQLQueryParms& p, query_reset r)
    00869 {
    00870         r = parse_elems_.size() ? DONT_RESET : RESET_QUERY;
    00871         storein_sequence(seq, str(p, r).c_str());
    00872 }
    00873
    00874
    00875 template <class Sequence>
    00876 void Query::storein_sequence(Sequence& con, const char* s)
    00877 {
    00878         ResUse result = use(s);
    00879         while (1) {
    00880                 MYSQL_ROW d = mysql_fetch_row(result.raw_result());
    00881                 if (!d)
    00882                         break;
    00883                 Row row(d, &result, mysql_fetch_lengths(result.raw_result()),
    00884                                 true);
    00885                 if (!row)
    00886                         break;
    00887                 con.push_back(typename Sequence::value_type(row));
    00888         }
    00889 }
    00890
    00891
    00892 template <class Set>
    00893 void Query::storein_set(Set& sett, SQLQueryParms& p, query_reset r)
    00894 {
    00895         r = parse_elems_.size() ? DONT_RESET : RESET_QUERY;
    00896         storein_set(sett, str(p, r).c_str());
    00897 }
    00898
    00899
    00900 template <class Set>
    00901 void Query::storein_set(Set& con, const char* s)
    00902 {
    00903         ResUse result = use(s);
    00904         while (1) {
    00905                 MYSQL_ROW d = mysql_fetch_row(result.raw_result());
    00906                 if (!d)
    00907                         return;
    00908                 Row row(d, &result, mysql_fetch_lengths(result.raw_result()),
    00909                                 true);
    00910                 if (!row)
    00911                         break;
    00912                 con.insert(typename Set::value_type(row));
    00913         }
    00914 }
    00915
    00916
    00917 template <class T>
    00918 void Query::storein(T& con, SQLQueryParms& p, query_reset r)
    00919 {
    00920         r = parse_elems_.size() ? DONT_RESET : RESET_QUERY;
    00921         storein(con, str(p, r).c_str());
    00922 }
    00923
    00924
    00925 #endif // !defined(DOXYGEN_IGNORE)
    00926
    00927 } // end namespace mysqlpp
    00928
    00929 #endif
    00930