Author: wyoung
Date: Sat Aug 11 00:00:50 2007
New Revision: 1746
URL: http://svn.gna.org/viewcvs/mysqlpp?rev=1746&view=rev
Log:
- Row::operator[]() and Row::at() overloads used to return ColData by
value because they constructed these objects on the fly; you can't
return a reference to a temporary. This is because the internal
representation of the data in Row was two parallel vectors, one
holding std::string for the data, and the other a bool for the SQL
null flag. Now we keep it all in a vector<ColData>, so these accessor
methods just wrap those in the vector. Reference semantics fall out
of this for free.
- Removed Row::raw_*(). The above change makes these methods pointless.
- Added copy ctor and assignment operator to Row. These probably don't
have any real advantage over the default versions right now, but if
we go to reference counting for the internal data representation, we
will need to have these.
- Changed examples/multiquery.cpp to use Row::operator[]() instead of
Row::raw_data()
Modified:
trunk/Wishlist
trunk/examples/multiquery.cpp
trunk/lib/row.cpp
trunk/lib/row.h
Modified: trunk/Wishlist
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/Wishlist?rev=1746&r1=1745&r2=1746&view=diff
==============================================================================
--- trunk/Wishlist (original)
+++ trunk/Wishlist Sat Aug 11 00:00:50 2007
@@ -77,7 +77,9 @@
- Change operator[] from value to reference semantics every
place this is possible.
- - Add operator->() whereever reference semantics are possible
+ - If we can get reference semantics everywhere, we can add
+ operator->() to subscript_iterator. It can't work with
+ value semantics.
o Sort out the ResUse::fetch_row() vs. Result::fetch_row() mess.
Probably ResUse can't really justify having this.
Modified: trunk/examples/multiquery.cpp
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/multiquery.cpp?rev=1746&r1=1745&r2=1746&view=diff
==============================================================================
--- trunk/examples/multiquery.cpp (original)
+++ trunk/examples/multiquery.cpp Sat Aug 11 00:00:50 2007
@@ -59,8 +59,8 @@
print_row(IntVectorType& widths, Row& row)
{
cout << " |" << setfill(' ');
- for (size_t i = 0; i < row.size(); i++) {
- cout << " " << setw(widths.at(i)) << row.raw_data(i) << " |";
+ for (size_t i = 0; i < row.size(); ++i) {
+ cout << " " << setw(widths.at(i)) << row[i] << " |";
}
cout << endl;
}
Modified: trunk/lib/row.cpp
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/row.cpp?rev=1746&r1=1745&r2=1746&view=diff
==============================================================================
--- trunk/lib/row.cpp (original)
+++ trunk/lib/row.cpp Sat Aug 11 00:00:50 2007
@@ -30,38 +30,29 @@
namespace mysqlpp {
-Row::Row(const MYSQL_ROW& d, const ResUse* r,
- unsigned long* jj, bool te) :
-OptionalExceptions(te),
+Row::Row(const MYSQL_ROW& d, const ResUse* r, unsigned long* lengths,
+ bool throw_exceptions) :
+OptionalExceptions(throw_exceptions),
res_(r),
initialized_(false)
{
- if (!d || !r) {
- if (throw_exceptions()) {
- throw BadQuery("ROW or RES is NULL");
+ if (d && r) {
+ size_type fields = res_->num_fields();
+ data_.reserve(fields);
+ for (size_type i = 0; i < fields; ++i) {
+ bool is_null = d[i] == 0;
+ data_.push_back(value_type(
+ is_null ? "NULL" : d[i],
+ is_null ? 4 : lengths[i],
+ res_->types(i),
+ is_null));
}
- else {
- return;
- }
+
+ initialized_ = true;
}
-
- data_.clear();
- is_nulls_.clear();
- initialized_ = true;
-
- for (size_type i = 0; i < size(); ++i) {
- data_.insert(data_.end(),
- (d[i] ? std::string(d[i], jj[i]) :
std::string("NULL")));
- is_nulls_.insert(is_nulls_.end(), d[i] ? false : true);
+ else if (throw_exceptions) {
+ throw BadQuery("ROW or RES is NULL");
}
-}
-
-
-Row::~Row()
-{
- data_.clear();
- is_nulls_.clear();
- initialized_ = false;
}
@@ -70,24 +61,9 @@
return res_->num_fields();
}
-const ColData Row::at(int i) const
-{
- if (initialized_) {
- const std::string& s = data_.at(i);
- return ColData(s.data(), s.length(), res_->types(i),
- is_nulls_[i]);
- }
- else {
- if (throw_exceptions()) {
- throw std::out_of_range("Row not initialized");
- }
- else {
- return ColData();
- }
- }
-}
-const ColData Row::operator [](const char* field) const
+const Row::value_type&
+Row::operator [](const char* field) const
{
size_type si = res_->field_num(std::string(field));
if (si < size()) {
Modified: trunk/lib/row.h
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/row.h?rev=1746&r1=1745&r2=1746&view=diff
==============================================================================
--- trunk/lib/row.h (original)
+++ trunk/lib/row.h Sat Aug 11 00:00:50 2007
@@ -52,12 +52,7 @@
public:
typedef int difference_type; ///< type for index
differences
typedef unsigned int size_type; ///< type of returned
sizes
-
typedef ColData value_type; ///< type of
data in container
- typedef value_type& reference; ///< reference to
value_type
- typedef const value_type& const_reference;///< const ref to value_type
- typedef value_type* pointer; ///< pointer to
value_type
- typedef const value_type* const_pointer;///< const pointer to value_type
/// \brief regular iterator type
///
@@ -103,17 +98,25 @@
{
}
+ /// \brief Copy constructor
+ Row(const Row& r) :
+ data_(r.data_.begin(), r.data_.end()),
+ res_(r.res_),
+ initialized_(r.initialized_)
+ {
+ }
+
/// \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 lengths 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);
+ unsigned long* lengths, bool te = true);
/// \brief Destroy object
- ~Row();
+ ~Row() { }
/// \brief Get a reference to our parent class.
const ResUse& parent() const
@@ -123,6 +126,15 @@
/// \brief Get the number of fields in the row.
size_type size() const;
+
+ /// \brief Assignment operator
+ Row& operator=(const Row& rhs)
+ {
+ data_.assign(rhs.data_.begin(), rhs.data_.end());
+ res_ = rhs.res_;
+ initialized_ = rhs.initialized_;
+ return *this;
+ }
/// \brief Get the value of a field given its name.
///
@@ -132,37 +144,16 @@
/// 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 value_type operator [](const char* field) const;
+ /// retrieving data from this row object if you look fields up
+ /// in the result by name. Note that it is the lookup-by-name
+ /// aspect of things that matters here, not the row indexing
+ /// operation itself; this means you can avoid this restriction by
+ /// using \c operator[](int) instead.
+ ///
+ /// Another reason to use operator[](int) or at(int) instead is
+ /// efficiency: looking up a field by name is slower than looking
+ /// it up by position within the row.
+ const value_type& operator [](const char* field) const;
/// \brief Get the value of a field given its index.
///
@@ -171,10 +162,7 @@
/// \sa at() for the full documentation for this operator, and
/// operator[](const char*) for further caveats about using this
/// operator.
- const value_type operator [](int i) const
- {
- return at(i);
- }
+ const value_type& operator [](int i) const { return at(i); }
/// \brief Get the value of a field given its index.
///
@@ -187,40 +175,10 @@
/// retrieving data from this row object.
///
/// See operator[](const char*) for more caveats.
- const value_type at(int 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);
- }
+ const value_type& at(int i) const { return data_.at(i); }
/// \brief Returns true if there is data in the row.
- operator bool() const
- {
- return data_.size();
- }
+ operator bool() const { return data_.size(); }
/// \brief Get a list of the values in this row
///
@@ -508,8 +466,7 @@
const char* e, Manip m) const;
private:
- std::vector<std::string> data_;
- std::vector<bool> is_nulls_;
+ std::vector<value_type> data_;
const ResUse* res_;
bool initialized_;
};
_______________________________________________
Mysqlpp-commits mailing list
[email protected]
https://mail.gna.org/listinfo/mysqlpp-commits