Author: wyoung
Date: Thu Nov 29 11:09:30 2007
New Revision: 1924
URL: http://svn.gna.org/viewcvs/mysqlpp?rev=1924&view=rev
Log:
- Replaced operator bool() in Connection, Query, Row and ResUse with
a "safe bool" implementation based on bits in Jonathan Wakely's
proposed RefCountedPointer replacement. It's essentially the same
code, which we didn't use in RefCountedPointer, but did find a use for
here.
- ResUse similarly changed, but instead of having an operator that
converts itself into "pointer to private data member", it just returns
the MYSQL_RES*. One could argue that it's an exposure of internal
implmementation details, but it was only days ago that we removed
ResUse::raw_result(), so.... Lacking anything better to return, and
being unwilling to create something just for information hiding sake,
we did it this way.
- Bonus of previous item: was able to remove ResUse::operator ==() and
operator !=(). We get those for free when there's a convert-to-ptr
operator.
- Changed examples/simple?.cpp to make clearer use of these bool
context conversions.
Modified:
trunk/Wishlist
trunk/examples/simple1.cpp
trunk/examples/simple2.cpp
trunk/examples/simple3.cpp
trunk/lib/connection.h
trunk/lib/query.h
trunk/lib/result.h
trunk/lib/row.h
Modified: trunk/Wishlist
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/Wishlist?rev=1924&r1=1923&r2=1924&view=diff
==============================================================================
--- trunk/Wishlist (original)
+++ trunk/Wishlist Thu Nov 29 11:09:30 2007
@@ -16,10 +16,6 @@
o The manipulator changes sometime during 2.3 broke the column
formatting of the examples that dump tables. A setw(x) call
results in x spaces, not x - strlen(whatevercamebefore).
-
- o Classes Connection, Query, String, Result and Row all have
- operator bool() as well. Use Jonathan Wakely's "safe bool"
- instead?
o Atomic inc/dec of reference counts in RefCounted*?
@@ -111,6 +107,8 @@
o Add operator<< for Query, syntactic sugar for str(ostream&).
+ o Is Row::size_ not redundant w.r.t. Row::data_.size()?
+
v3.0 "Maybe" Stuff
------------------
Modified: trunk/examples/simple1.cpp
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/simple1.cpp?rev=1924&r1=1923&r2=1924&view=diff
==============================================================================
--- trunk/examples/simple1.cpp (original)
+++ trunk/examples/simple1.cpp Thu Nov 29 11:09:30 2007
@@ -45,27 +45,26 @@
}
// Connect to the sample database.
- mysqlpp::Connection con(false);
- if (!con.connect(db, server, user, pass)) {
+ mysqlpp::Connection conn(false);
+ if (conn.connect(db, server, user, pass)) {
+ // Retrieve a subset of the sample stock table set up by resetdb
+ // and display it.
+ mysqlpp::Query query = conn.query("select item from stock");
+ if (mysqlpp::Result res = query.store()) {
+ cout << "We have:" << endl;
+ for (int i = 0; mysqlpp::Row row = res[i]; ++i) {
+ cout << '\t' << row[0] << endl;
+ }
+ }
+ else {
+ cerr << "Failed to get item list: " << query.error() <<
endl;
+ return 1;
+ }
+
+ return 0;
+ }
+ else {
+ cerr << "DB connection failed: " << conn.error() << endl;
return 1;
}
-
- // Retrieve a subset of the sample stock table set up by resetdb
- mysqlpp::Query query = con.query("select item from stock");
- mysqlpp::Result res = query.store();
-
- // Display the result set
- cout << "We have:" << endl;
- if (res) {
- mysqlpp::Row row;
- for (int i = 0; row = res[i]; ++i) {
- cout << '\t' << row[0] << endl;
- }
- }
- else {
- cerr << "Failed to get item list: " << query.error() << endl;
- return 1;
- }
-
- return 0;
}
Modified: trunk/examples/simple2.cpp
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/simple2.cpp?rev=1924&r1=1923&r2=1924&view=diff
==============================================================================
--- trunk/examples/simple2.cpp (original)
+++ trunk/examples/simple2.cpp Thu Nov 29 11:09:30 2007
@@ -45,40 +45,41 @@
}
// Connect to the sample database.
- mysqlpp::Connection con(false);
- if (!con.connect(db, server, user, pass)) {
+ mysqlpp::Connection conn(false);
+ if (conn.connect(db, server, user, pass)) {
+ // Retrieve the sample stock table set up by resetdb
+ mysqlpp::Query query = conn.query("select * from stock");
+ mysqlpp::Result res = query.store();
+
+ // Display results
+ if (res) {
+ // Display header
+ cout.setf(ios::left);
+ cout << setw(31) << "Item" <<
+ setw(10) << "Num" <<
+ setw(10) << "Weight" <<
+ setw(10) << "Price" <<
+ "Date" << endl << endl;
+
+ // Get each row in result set, and print its contents
+ for (int i = 0; mysqlpp::Row row = res[i]; ++i) {
+ cout << setw(30) << row["item"] << ' ' <<
+ setw(9) << row["num"] << ' ' <<
+ setw(9) << row["weight"] << ' '
<<
+ setw(9) << row["price"] << ' '
<<
+ setw(9) << row["sdate"] <<
+ endl;
+ }
+ }
+ else {
+ cerr << "Failed to get stock table: " << query.error()
<< endl;
+ return 1;
+ }
+
+ return 0;
+ }
+ else {
+ cerr << "DB connection failed: " << conn.error() << endl;
return 1;
}
-
- // Retrieve the sample stock table set up by resetdb
- mysqlpp::Query query = con.query("select * from stock");
- mysqlpp::Result res = query.store();
-
- // Display results
- if (res) {
- // Display header
- cout.setf(ios::left);
- cout << setw(31) << "Item" <<
- setw(10) << "Num" <<
- setw(10) << "Weight" <<
- setw(10) << "Price" <<
- "Date" << endl << endl;
-
- // Get each row in result set, and print its contents
- mysqlpp::Row row;
- for (int i = 0; row = res[i]; ++i) {
- cout << setw(30) << row["item"] << ' ' <<
- setw(9) << row["num"] << ' ' <<
- setw(9) << row["weight"] << ' ' <<
- setw(9) << row["price"] << ' ' <<
- setw(9) << row["sdate"] <<
- endl;
- }
- }
- else {
- cerr << "Failed to get stock table: " << query.error() << endl;
- return 1;
- }
-
- return 0;
}
Modified: trunk/examples/simple3.cpp
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/examples/simple3.cpp?rev=1924&r1=1923&r2=1924&view=diff
==============================================================================
--- trunk/examples/simple3.cpp (original)
+++ trunk/examples/simple3.cpp Thu Nov 29 11:09:30 2007
@@ -45,41 +45,41 @@
}
// Connect to the sample database.
- mysqlpp::Connection con(false);
- if (!con.connect(db, server, user, pass)) {
- return 1;
- }
+ mysqlpp::Connection conn(false);
+ if (conn.connect(db, server, user, pass)) {
+ // Ask for all rows from the sample stock table and display
+ // them. Unlike simple2 example, we retreive each row one at
+ // a time instead of storing the entire result set in memory
+ // and then iterating over it.
+ mysqlpp::Query query = conn.query("select * from stock");
+ if (mysqlpp::ResUse res = query.use()) {
+ // Display header
+ cout.setf(ios::left);
+ cout << setw(31) << "Item" <<
+ setw(10) << "Num" <<
+ setw(10) << "Weight" <<
+ setw(10) << "Price" <<
+ "Date" << endl << endl;
- // Ask for all rows from the sample stock table set up by resetdb.
- // Unlike simple2 example, we don't store result set in memory.
- mysqlpp::Query query = con.query("select * from stock");
- mysqlpp::ResUse res = query.use();
+ // Get each row in result set, and print its contents
+ while (mysqlpp::Row row = res.fetch_row()) {
+ cout << setw(30) << row["item"] << ' ' <<
+ setw(9) << row["num"] << ' ' <<
+ setw(9) << row["weight"] << ' '
<<
+ setw(9) << row["price"] << ' '
<<
+ setw(9) << row["sdate"] <<
+ endl;
+ }
- // Retreive result rows one by one, and display them.
- if (res) {
- // Display header
- cout.setf(ios::left);
- cout << setw(31) << "Item" <<
- setw(10) << "Num" <<
- setw(10) << "Weight" <<
- setw(10) << "Price" <<
- "Date" << endl << endl;
-
- // Get each row in result set, and print its contents
- mysqlpp::Row row;
- while (row = res.fetch_row()) {
- cout << setw(30) << row["item"] << ' ' <<
- setw(9) << row["num"] << ' ' <<
- setw(9) << row["weight"] << ' ' <<
- setw(9) << row["price"] << ' ' <<
- setw(9) << row["sdate"] <<
- endl;
+ return 0;
}
-
- return 0;
+ else {
+ cerr << "Failed to get stock item: " << query.error()
<< endl;
+ return 1;
+ }
}
else {
- cerr << "Failed to get stock item: " << query.error() << endl;
+ cerr << "DB connection failed: " << conn.error() << endl;
return 1;
}
}
Modified: trunk/lib/connection.h
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/connection.h?rev=1924&r1=1923&r2=1924&view=diff
==============================================================================
--- trunk/lib/connection.h (original)
+++ trunk/lib/connection.h Thu Nov 29 11:09:30 2007
@@ -53,6 +53,13 @@
class MYSQLPP_EXPORT Connection : public OptionalExceptions
{
+private:
+ /// \brief Pointer to bool data member, for use by safe bool
+ /// conversion operator.
+ ///
+ /// \see http://www.artima.com/cppsource/safebool.html
+ typedef bool Connection::*private_bool_type;
+
public:
/// \brief Legal types of option arguments
enum OptionArgType {
@@ -308,27 +315,29 @@
return mysql_kill(&mysql_, tid);
}
- /// \brief Test whether the connection has experienced an error
- /// condition.
- ///
- /// Allows for code constructs like this:
+ /// \brief Test whether any error has occurred within the object.
+ ///
+ /// Allows the object to be used in bool context, like this:
///
/// \code
/// Connection conn;
/// .... use conn
/// if (conn) {
- /// ... last SQL query was successful
+ /// ... nothing bad has happened since last successful use
/// }
/// else {
- /// ... error occurred in SQL query
+ /// ... some error has occurred
/// }
/// \endcode
///
- /// Prior to version 3, this function could never return true if
- /// we weren't connected. As of version 3, a true return simply
- /// indicates a lack of errors; call connected() to test whether
- /// the connection is established.
- operator bool() const { return copacetic_; }
+ /// Prior to MySQL++ v3, the object was always falsy when we
+ /// weren't connected. Now a true return simply indicates a lack of
+ /// errors. If you've been using this to test for whether the
+ /// connection is still up, you need to call connected() instead.
+ operator private_bool_type() const
+ {
+ return copacetic_ ? &Connection::copacetic_ : 0;
+ }
/// \brief Copy an existing Connection object's state into this
/// object.
Modified: trunk/lib/query.h
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/query.h?rev=1924&r1=1923&r2=1924&view=diff
==============================================================================
--- trunk/lib/query.h (original)
+++ trunk/lib/query.h Thu Nov 29 11:09:30 2007
@@ -121,6 +121,13 @@
public std::ostream,
public OptionalExceptions
{
+private:
+ /// \brief Pointer to bool data member, for use by safe bool
+ /// conversion operator.
+ ///
+ /// \see http://www.artima.com/cppsource/safebool.html
+ typedef bool Query::*private_bool_type;
+
public:
/// \brief Create a new query object attached to a connection.
///
@@ -164,7 +171,10 @@
/// This method returns false if either the Query object or its
/// associated Connection object has seen an error condition since
/// the last operation.
- operator bool() const { return *conn_ && copacetic_; }
+ operator private_bool_type() const
+ {
+ return *conn_ && copacetic_ ? &Query::copacetic_ : 0;
+ }
/// \brief Return true if the object has experienced an error
bool operator !() { return !copacetic_; }
Modified: trunk/lib/result.h
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/result.h?rev=1924&r1=1923&r2=1924&view=diff
==============================================================================
--- trunk/lib/result.h (original)
+++ trunk/lib/result.h Thu Nov 29 11:09:30 2007
@@ -158,20 +158,32 @@
int num_fields() const
{ return mysql_num_fields(result_.raw()); }
- /// \brief Return true if we have a valid result set
- ///
- /// This operator is primarily used to determine if a query was
+ /// \brief Return the pointer to the underlying MySQL C API
+ /// result set object.
+ ///
+ /// While this has obvious inherent value for those times you need
+ /// to dig beneath the MySQL++ interface, it has subtler value.
+ /// It effectively stands in for operator bool(), operator !(),
+ /// operator ==(), and operator !=(), because the C++ compiler can
+ /// implement all of these with a MYSQL_RES*.
+ ///
+ /// Of these uses, the most valuable is using the ResUse object in
+ /// bool context to determine if the query that created it was
/// successful:
///
/// \code
/// Query q("....");
- /// if (q.use()) {
- /// ...
+ /// if (ResUse res = q.use()) {
+ /// // Can use 'res', query succeeded
+ /// }
+ /// else {
+ /// // Query failed, call Query::error() or ::errnum() for why
+ /// }
/// \endcode
- ///
- /// Query::use() returns a ResUse object, and it won't contain a
- /// valid result set if the query failed.
- operator bool() const { return result_; }
+ operator MYSQL_RES*() const
+ {
+ return result_.raw();
+ }
/// \brief Return the name of the table the result set comes from
const char* table() const
@@ -204,19 +216,6 @@
/// \brief Get the underlying Field structure given its index.
const Field& field(unsigned int i) const { return fields_.at(i); }
-
- /// \brief Returns true if the other ResUse object shares the same
- /// underlying C API result set as this one.
- ///
- /// This works because the underlying result set is stored as a
- /// pointer, and thus can be copied and then compared.
- bool operator ==(const ResUse& other) const
- { return result_ == other.result_; }
-
- /// \brief Returns true if the other ResUse object has a different
- /// underlying C API result set from this one.
- bool operator !=(const ResUse& other) const
- { return result_ != other.result_; }
protected:
bool initialized_; ///< if true, object is fully
initted
@@ -382,6 +381,13 @@
/// \brief Holds information on queries that don't return data.
class MYSQLPP_EXPORT ResNSel
{
+private:
+ /// \brief Pointer to bool data member, for use by safe bool
+ /// conversion operator.
+ ///
+ /// \see http://www.artima.com/cppsource/safebool.html
+ typedef bool ResNSel::*private_bool_type;
+
public:
/// \brief Default ctor
ResNSel() :
@@ -401,8 +407,16 @@
{
}
- /// \brief Test whether the query was successful
- operator bool() const { return copacetic_; }
+ /// \brief Test whether the query that created this result succeeded
+ ///
+ /// If you test this object in bool context and it's false, it's a
+ /// signal that the query this was created from failed in some way.
+ /// Call Query::error() or Query::errnum() to find out what exactly
+ /// happened.
+ operator private_bool_type() const
+ {
+ return copacetic_ ? &ResNSel::copacetic_ : 0;
+ }
/// \brief Get the last value used for an AUTO_INCREMENT field
my_ulonglong insert_id() const { return insert_id_; }
Modified: trunk/lib/row.h
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/lib/row.h?rev=1924&r1=1923&r2=1924&view=diff
==============================================================================
--- trunk/lib/row.h (original)
+++ trunk/lib/row.h Thu Nov 29 11:09:30 2007
@@ -50,6 +50,13 @@
/// \brief Manages rows from a result set.
class MYSQLPP_EXPORT Row : public OptionalExceptions
{
+private:
+ /// \brief Pointer to bool data member, for use by safe bool
+ /// conversion operator.
+ ///
+ /// \see http://www.artima.com/cppsource/safebool.html
+ typedef bool Row::*private_bool_type;
+
public:
typedef int difference_type; ///< type for index
differences
typedef unsigned int size_type; ///< type of returned
sizes
@@ -152,8 +159,27 @@
/// supposed to throw an exception, according to the Standard.
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(); }
+ /// \brief Returns true if row object was fully initialized and
+ /// has data.
+ ///
+ /// This operator lets you use Row in bool context, which lets you
+ /// do things like tell when you've run off the end of a "use"
+ /// query's result set:
+ ///
+ /// \code
+ /// Query q("....");
+ /// if (ResUse res = q.use()) {
+ /// // Can use 'res', query succeeded
+ /// while (Row row = res.fetch_row()) {
+ /// // Retreived another row in the result set, can use 'row'
+ /// }
+ /// }
+ /// \endcode
+ ///
+ operator private_bool_type() const
+ {
+ return data_.size() && initialized_ ? &Row::initialized_ : 0;
+ }
/// \brief Returns a field's index given its name
size_type field_num(const char* name) const;
_______________________________________________
Mysqlpp-commits mailing list
[email protected]
https://mail.gna.org/listinfo/mysqlpp-commits