/// \file row.h /// \brief Declares the classes for holding row data from a result set. /*********************************************************************** Copyright (c) 1998 by Kevin Atkinson, (c) 1999, 2000 and 2001 by MySQL AB, and (c) 2004, 2005 by Educational Technology Resources, Inc. Others may also hold copyrights on code in this file. See the CREDITS file in the top directory of the distribution for details. This file is part of MySQL++. MySQL++ is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. MySQL++ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with MySQL++; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ***********************************************************************/ #ifndef MYSQLPP_ROW_H #define MYSQLPP_ROW_H #include "coldata.h" #include "exceptions.h" #include "noexceptions.h" #include "resiter.h" #include "vallist.h" #include #include #include namespace mysqlpp { #if !defined(DOXYGEN_IGNORE) // Make Doxygen ignore this class FieldNames; class MYSQLPP_EXPORT ResUse; #endif /// \brief Manages rows from a result set. class MYSQLPP_EXPORT Row : public const_subscript_container, public OptionalExceptions { public: /// \brief Default constructor Row() : res_(0), initialized_(false) { } /// \brief Create a row object /// /// \param d MySQL C API row data /// \param r result set that the row comes from /// \param jj length of each item in d /// \param te if true, throw exceptions on errors Row(const MYSQL_ROW& d, const ResUse* r, unsigned long* jj, bool te = true); /// \brief Destroy object ~Row(); /// \brief Get a reference to our parent class. const ResUse& parent() const { return *res_; } /// \brief Get the number of fields in the row. size_type size() const; /// \brief Get the value of a field given its name. /// /// If the field does not exist in this row, we throw a BadFieldName /// exception. /// /// For this operator to work, the Result or ResUse object that /// created this object must still exist. In other words, you /// cannot re-use or destroy the result object until you are done /// retrieving data from this row object. /// /// Note that we return the /// \link mysqlpp::ColData_Tmpl ColData \endlink object by value. /// The purpose of ColData is to make it easy to convert the string /// data returned by the MySQL server to some more appropriate type, /// so you're almost certain to use this operator in a construct /// like this: /// /// \code /// string s = row["myfield"]; /// \endcode /// /// That accesses myfield within the row, returns a temporary /// ColData object, which is then automatically converted to a /// \c std::string and copied into \c s. That works fine, but /// beware of this similar but incorrect construct: /// /// \code /// const char* pc = row["myfield"]; /// \endcode /// /// This one line of code does what you expect, but \c pc is then a /// dangling pointer: it points to memory owned by the temporary /// ColData object, which will have been destroyed by the time you /// get around to actually \e using the pointer. /// /// This function is rather inefficient. If that is a concern for /// you, use at(), operator[](size_type) or the SSQLS mechanism' /// instead. const ColData operator [](const char* field) const; /// \brief Get the value of a field given its index. /// /// This function is just syntactic sugar, wrapping the at() method. /// The at() method is the only way to get at the first field in a /// result set by index, as \c row[0] is ambiguous: it could call /// either \c operator[] overload. /// /// \sa at() for the full documentation for this operator, and /// operator[](const char*) for further caveats about using this /// operator. const ColData operator [](size_type i) const { return at(i); } /// \brief Get the value of a field given its index. /// /// If the index value is bad, the underlying std::vector is /// supposed to throw an exception, according to the Standard. /// /// For this function to work, the Result or ResUse object that /// created this object must still exist. In other words, you /// cannot re-use or destroy the result object until you are done /// retrieving data from this row object. /// /// See operator[](const char*) for more caveats. const ColData at(size_type i) const; /// \brief Return the value of a field as a C string given its /// index, in raw form. /// /// This is the same thing as operator[], except that the data isn't /// converted to a ColData object first. Also, this method does not /// check for out-of-bounds array indices. const char* raw_data(int i) const { return data_[i].data(); } /// \brief Return the size of a field's raw data given its index. std::string::size_type raw_size(int i) const { return data_[i].length(); } /// \brief Return the value of a field as a C++ string given its /// index, in raw form. /// /// This is the same thing as operator[], except that the data isn't /// converted to a ColData object first. const std::string& raw_string(int i) const { return data_.at(i); } /// \brief Returns true if there is data in the row. operator bool() const { return data_.size(); } /// \brief Get a list of the values in this row /// /// When inserted into a C++ stream, the delimiter 'd' will be used /// between the items, and the quoting and escaping rules will be /// set by the manipulator 'm' you choose. /// /// \param d delimiter to use between values /// \param m manipulator to use when inserting values into a stream template value_list_ba value_list(const char* d = ",", Manip m = quote) const { return value_list_ba(*this, d, m); } /// \brief Get a list of the values in this row /// /// \param d delimiter to use between values /// \param vb for each true item in this list, add that value to the /// returned list; ignore the others /// \param m manipulator to use when inserting values into a stream template value_list_b value_list(const char *d, const std::vector& vb, Manip m = quote) const { return value_list_b(*this, vb, d, m); } /// \brief Get a list of the values in this row /// /// \param vb for each true item in this list, add that value to the /// returned list; ignore the others /// /// Items will be quoted and escaped when inserted into a C++ stream, /// and a comma will be used as a delimiter between the items. value_list_b value_list( const std::vector &vb) const { return value_list_b(*this, vb, ",", quote); } /// \brief Get a list of the values in this row /// /// For each true parameter, the value in that position within the /// row is added to the returned list. When the list is inserted /// into a C++ stream, the delimiter 'd' will be placed between the /// items, and the manipulator 'm' used before each item. template value_list_b value_list(const char *d, Manip m, bool t0, bool t1 = false, bool t2 = false, bool t3 = false, bool t4 = false, bool t5 = false, bool t6 = false, bool t7 = false, bool t8 = false, bool t9 = false, bool ta = false, bool tb = false, bool tc = false) const { std::vector vb; create_vector(size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, ta, tb, tc); return value_list_b(*this, vb, d, m); } /// \brief Get a list of the values in this row /// /// For each true parameter, the value in that position within the /// row is added to the returned list. When the list is inserted /// into a C++ stream, the delimiter 'd' will be placed between the /// items, and items will be quoted and escaped. value_list_b value_list(const char *d, bool t0, bool t1 = false, bool t2 = false, bool t3 = false, bool t4 = false, bool t5 = false, bool t6 = false, bool t7 = false, bool t8 = false, bool t9 = false, bool ta = false, bool tb = false, bool tc = false) const { std::vector vb; create_vector(size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, ta, tb, tc); return value_list_b(*this, vb, d, quote); } /// \brief Get a list of the values in this row /// /// For each true parameter, the value in that position within the /// row is added to the returned list. When the list is inserted /// into a C++ stream, the a comma will be placed between the items, /// as a delimiter, and items will be quoted and escaped. value_list_b value_list(bool t0, bool t1 = false, bool t2 = false, bool t3 = false, bool t4 = false, bool t5 = false, bool t6 = false, bool t7 = false, bool t8 = false, bool t9 = false, bool ta = false, bool tb = false, bool tc = false) const { std::vector vb; create_vector(size(), vb, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, ta, tb, tc); return value_list_b(*this, vb, ",", quote); } /// \brief Get a list of the values in this row /// /// The 's' parameters name the fields that will be added to the /// returned list. When inserted into a C++ stream, the delimiter /// 'd' will be placed between the items, and the manipulator 'm' /// will be inserted before each item. template value_list_b value_list(const char *d, Manip m, std::string s0, std::string s1 = "", std::string s2 = "", std::string s3 = "", std::string s4 = "", std::string s5 = "", std::string s6 = "", std::string s7 = "", std::string s8 = "", std::string s9 = "", std::string sa = "", std::string sb = "", std::string sc = "") const { std::vector vb; create_vector(*this, vb, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sa, sb, sc); return value_list_b(*this, vb, d, m); } /// \brief Get a list of the values in this row /// /// The 's' parameters name the fields that will be added to the /// returned list. When inserted into a C++ stream, the delimiter /// 'd' will be placed between the items, and items will be quoted /// and escaped. value_list_b value_list( const char *d, std::string s0, std::string s1 = "", std::string s2 = "", std::string s3 = "", std::string s4 = "", std::string s5 = "", std::string s6 = "", std::string s7 = "", std::string s8 = "", std::string s9 = "", std::string sa = "", std::string sb = "", std::string sc = "") const { std::vector vb; create_vector(*this, vb, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sa, sb, sc); return value_list_b(*this, vb, d, quote); } /// \brief Get a list of the values in this row /// /// The 's' parameters name the fields that will be added to the /// returned list. When inserted into a C++ stream, a comma will be /// placed between the items as a delimiter, and items will be /// quoted and escaped. value_list_b value_list( std::string s0, std::string s1 = "", std::string s2 = "", std::string s3 = "", std::string s4 = "", std::string s5 = "", std::string s6 = "", std::string s7 = "", std::string s8 = "", std::string s9 = "", std::string sa = "", std::string sb = "", std::string sc = "") const { std::vector vb; create_vector(*this, vb, s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, sa, sb, sc); return value_list_b(*this, vb, ",", quote); } /// \brief Get a list of the field names in this row /// /// When inserted into a C++ stream, the delimiter 'd' will be used /// between the items, and no manipulator will be used on the items. value_list_ba field_list(const char* d = ",") const; /// \brief Get a list of the field names in this row /// /// \param d delimiter to place between the items when the list is /// inserted into a C++ stream /// \param m manipulator to use before each item when the list is /// inserted into a C++ stream template value_list_ba field_list(const char* d, Manip m) const; /// \brief Get a list of the field names in this row /// /// \param d delimiter to place between the items when the list is /// inserted into a C++ stream /// \param m manipulator to use before each item when the list is /// inserted into a C++ stream /// \param vb for each true item in this list, add that field name /// to the returned list; ignore the others template value_list_b field_list(const char* d, Manip m, const std::vector& vb) const; /// \brief Get a list of the field names in this row /// /// \param d delimiter to place between the items when the list is /// inserted into a C++ stream /// \param vb for each true item in this list, add that field name /// to the returned list; ignore the others /// /// Field names will be quoted and escaped when inserted into a C++ /// stream. value_list_b field_list( const char* d, const std::vector& vb) const; /// \brief Get a list of the field names in this row /// /// \param vb for each true item in this list, add that field name /// to the returned list; ignore the others /// /// Field names will be quoted and escaped when inserted into a C++ /// stream, and a comma will be placed between them as a delimiter. value_list_b field_list( const std::vector& vb) const; /// \brief Get a list of the field names in this row /// /// For each true parameter, the field name in that position within /// the row is added to the returned list. When the list is /// inserted into a C++ stream, the delimiter 'd' will be placed /// between the items as a delimiter, and the manipulator 'm' used /// before each item. template value_list_b field_list(const char *d, Manip m, bool t0, bool t1 = false, bool t2 = false, bool t3 = false, bool t4 = false, bool t5 = false, bool t6 = false, bool t7 = false, bool t8 = false, bool t9 = false, bool ta = false, bool tb = false, bool tc = false) const; /// \brief Get a list of the field names in this row /// /// For each true parameter, the field name in that position within /// the row is added to the returned list. When the list is /// inserted into a C++ stream, the delimiter 'd' will be placed /// between the items as a delimiter, and the items will be quoted /// and escaped. value_list_b field_list( const char *d, bool t0, bool t1 = false, bool t2 = false, bool t3 = false, bool t4 = false, bool t5 = false, bool t6 = false, bool t7 = false, bool t8 = false, bool t9 = false, bool ta = false, bool tb = false, bool tc = false) const; /// \brief Get a list of the field names in this row /// /// For each true parameter, the field name in that position within /// the row is added to the returned list. When the list is /// inserted into a C++ stream, a comma will be placed between the /// items as a delimiter, and the items will be quoted and escaped. value_list_b field_list( bool t0, bool t1 = false, bool t2 = false, bool t3 = false, bool t4 = false, bool t5 = false, bool t6 = false, bool t7 = false, bool t8 = false, bool t9 = false, bool ta = false, bool tb = false, bool tc = false) const; /// \brief Get an "equal list" of the fields and values in this row /// /// When inserted into a C++ stream, the delimiter 'd' will be used /// between the items, " = " is the relationship operator, and items /// will be quoted and escaped. equal_list_ba equal_list(const char* d = ",", const char* e = " = ") const; /// \brief Get an "equal list" of the fields and values in this row /// /// This method's parameters govern how the returned list will /// behave when you insert it into a C++ stream: /// /// \param d delimiter to use between items /// \param e the operator to use between elements /// \param m the manipulator to use for each element /// /// For example, if d is ",", e is " = ", and m is the quote /// manipulator, then the field and value lists (a, b) (c, d'e) /// will yield an equal list that gives the following when inserted /// into a C++ stream: /// /// \code /// 'a' = 'c', 'b' = 'd''e' /// \endcode /// /// Notice how the single quote was 'escaped' in the SQL way to /// avoid a syntax error. template equal_list_ba equal_list(const char* d, const char* e, Manip m) const; private: std::vector data_; std::vector is_nulls_; const ResUse* res_; bool initialized_; }; } // end namespace mysqlpp #endif