312 lines
11 KiB
C++
312 lines
11 KiB
C++
/// \file ssqls2.h
|
|
/// \brief Declares the SsqlsBase class
|
|
|
|
/***********************************************************************
|
|
Copyright (c) 2009 by Educational Technology Resources, Inc.
|
|
Others may also hold copyrights on code in this file. See the
|
|
CREDITS.txt 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
|
|
***********************************************************************/
|
|
|
|
#if !defined(MYSQLPP_SSQLS2_H)
|
|
#define MYSQLPP_SSQLS2_H
|
|
|
|
#include "common.h"
|
|
|
|
#include <iostream>
|
|
|
|
namespace mysqlpp {
|
|
|
|
#if !defined(DOXYGEN_IGNORE)
|
|
// Make Doxygen ignore this
|
|
class MYSQLPP_EXPORT Connection;
|
|
class MYSQLPP_EXPORT Row;
|
|
#endif
|
|
|
|
/// \brief Base class for all SSQLSv2 classes
|
|
///
|
|
/// Classes generated by ssqlsxlat derive from this class. It is not
|
|
/// directly instantiable. It exists only to hold the common interface
|
|
/// to all SSQLSv2 classes.
|
|
class MYSQLPP_EXPORT SsqlsBase
|
|
{
|
|
public:
|
|
/// \brief Supported field subsets
|
|
enum FieldSubset {
|
|
fs_all, ///< all fields
|
|
fs_key, ///< fields with "is key" attribute
|
|
fs_set, ///< fields that have been given a value
|
|
fs_not_autoinc ///< fields without "is autoinc" attribute
|
|
};
|
|
|
|
/// \brief Create table in database matching subclass schema
|
|
///
|
|
/// \param conn If given, use this connection instead of the one we
|
|
/// may have gotten earlier; saves value for future use.
|
|
///
|
|
/// \return true if table was successfully created; on failure,
|
|
/// only returns false if conn->throw_exceptions() is false.
|
|
virtual bool create_table(Connection* conn = 0) const = 0;
|
|
|
|
/// \brief Create record in database from all fields in object
|
|
/// except for any marked as auto-increment.
|
|
///
|
|
/// \param conn If given, use this connection instead of the one we
|
|
/// may have gotten earlier; saves value for future use.
|
|
///
|
|
/// \return true if new record was successfully created; on failure,
|
|
/// only returns false if conn->throw_exceptions() is false.
|
|
bool create(Connection* conn = 0) const;
|
|
|
|
/// \brief Puts stream insertion operator into "equal list" mode
|
|
///
|
|
/// Typical usage:
|
|
///
|
|
/// \code cout << foo.equal_list() << endl;
|
|
///
|
|
/// \see operator<<(std::ostream&, const SsqlsBase&)
|
|
const SsqlsBase& equal_list() const
|
|
{
|
|
output_mode_ = om_equal_list;
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Insert SSQLS's names and values into a stream.
|
|
///
|
|
/// An "equal list" is a set of name/value pairs in SQL assignment
|
|
/// form, suitable for building INSERT queries and such.
|
|
///
|
|
/// \param os output stream to insert equal list into
|
|
/// \param fs with default value, only the fields that have been
|
|
/// given values are included in the output
|
|
virtual std::ostream& equal_list(std::ostream& os,
|
|
FieldSubset fs = fs_set) const = 0;
|
|
|
|
/// \brief Set a per-instance SQL table name
|
|
///
|
|
/// This causes table() to return the passed value instead of the
|
|
/// static per-class value it normally returns. This is useful if
|
|
/// you're using a single SSQLS definition for multiple tables that
|
|
/// happen to share a common schema or schema subset.
|
|
void instance_table(const char* name)
|
|
{ instance_table_name_ = name; }
|
|
|
|
/// \brief Retrieve record from the database matching our key field(s)
|
|
///
|
|
/// \param conn If given, use this connection instead of the one we
|
|
/// may have gotten earlier; saves value for future use.
|
|
///
|
|
/// \return true if record was successfully retrieved; on failure,
|
|
/// only returns false if conn->throw_exceptions() is false.
|
|
bool load(Connection* conn = 0) const;
|
|
|
|
/// \brief Puts stream insertion operator into "name list" mode
|
|
///
|
|
/// Typical usage:
|
|
///
|
|
/// \code cout << foo.name_list() << endl;
|
|
///
|
|
/// \see operator<<(std::ostream&, const SsqlsBase&)
|
|
const SsqlsBase& name_list() const
|
|
{
|
|
output_mode_ = om_name_list;
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Insert the SSQLS's field names into a stream
|
|
///
|
|
/// A "name list" is a comma-separated list of SSQLS field names
|
|
///
|
|
/// \param os output stream to insert name list into
|
|
/// \param fs with default value, only the names of fields that have
|
|
/// been given values are included in the output
|
|
virtual std::ostream& name_list(std::ostream& os,
|
|
FieldSubset fs = fs_set) const = 0;
|
|
|
|
/// \brief Returns truthy value if object's fields have been fully
|
|
/// populated.
|
|
///
|
|
/// Test the Row, result or Query class you used to assign the
|
|
/// value to distinguish a successful subset population from
|
|
/// a complete failure to populate the object. Because of this
|
|
/// ambiguity, this operator is only useful for checking that an
|
|
/// expected full population did in fact fully populate the object.
|
|
/// This can help you to detect schema drift.
|
|
operator const void*() const { return populated() ? this : 0; }
|
|
|
|
/// \brief Returns true if the object has been populated
|
|
///
|
|
/// \param fs field subset to check, defaulting to "all fields"
|
|
///
|
|
/// This can give a different result than testing the object in
|
|
/// bool context if you pass something other than fs_all.
|
|
virtual bool populated(FieldSubset fs = fs_all) const = 0;
|
|
|
|
/// \brief Delete record matching our key field(s) from the database
|
|
///
|
|
/// \param conn If given, use this connection instead of the one we
|
|
/// may have gotten earlier; saves value for future use.
|
|
///
|
|
/// \return true if record was successfully removed; on failure,
|
|
/// only returns false if conn->throw_exceptions() is false.
|
|
bool remove(Connection* conn = 0) const;
|
|
|
|
/// \brief Update record in database matching our key fields, or
|
|
/// insert it if there is no such record.
|
|
///
|
|
/// \param conn If given, use this connection instead of the one we
|
|
/// may have gotten earlier; saves value for future use.
|
|
///
|
|
/// \return true if record was successfully saved; on failure,
|
|
/// only returns false if conn->throw_exceptions() is false.
|
|
bool save(Connection* conn = 0) const;
|
|
|
|
/// \brief Get the object's SQL table name
|
|
///
|
|
/// \r return the value set by instance_table(), if you called it,
|
|
/// or a static per-class value otherwise
|
|
const char* table() const { return instance_table_name_; }
|
|
|
|
/// \brief Puts stream insertion operator into "value list" mode
|
|
///
|
|
/// Typical usage:
|
|
///
|
|
/// \code cout << foo.value_list() << endl;
|
|
///
|
|
/// \see operator<<(std::ostream&, const SsqlsBase&)
|
|
const SsqlsBase& value_list() const
|
|
{
|
|
output_mode_ = om_value_list;
|
|
return *this;
|
|
}
|
|
|
|
/// \brief Insert SSQLS's values into a stream.
|
|
///
|
|
/// A "value list" is a comma-separated list of SSQLS field values.
|
|
/// Whether the values are quoted and/or escaped depends on the
|
|
/// stream type passed for os.
|
|
///
|
|
/// \param os output stream to insert value list into
|
|
/// \param fs with default value, only the fields that have been
|
|
/// given values are included in the output
|
|
virtual std::ostream& value_list(std::ostream& os,
|
|
FieldSubset fs = fs_set) const = 0;
|
|
|
|
protected:
|
|
/// \brief Default constructor
|
|
///
|
|
/// \param conn pointer to connection we should use for Active
|
|
/// Record methods' queries, if no connection is passed for that
|
|
/// particular call.
|
|
SsqlsBase(Connection* conn = 0) :
|
|
output_mode_(om_value_list),
|
|
conn_(conn),
|
|
instance_table_name_(0)
|
|
{
|
|
}
|
|
|
|
/// \brief Full initialization constructor
|
|
///
|
|
/// \param row data to use in initializing SSQLS fields
|
|
/// \param conn pointer to connection we should use for Active
|
|
/// Record methods' queries, if no connection is passed for that
|
|
/// particular call.
|
|
/// \todo do something with row parameter
|
|
SsqlsBase(const Row& row, Connection* conn = 0) :
|
|
output_mode_(om_value_list),
|
|
conn_(conn),
|
|
instance_table_name_(0)
|
|
{
|
|
#if !defined(_MSC_VER)
|
|
// Unused parameter warning squisher. VC++ can't cope without
|
|
// including row.h, which we don't want to do just to squish a
|
|
// warning. It doesn't warn anyway, so...
|
|
(void)row;
|
|
#endif
|
|
}
|
|
|
|
/// \brief Destructor
|
|
virtual ~SsqlsBase() { }
|
|
|
|
/// \brief Flag controlling the behavior of operator<<()
|
|
mutable enum {
|
|
om_equal_list,
|
|
om_name_list,
|
|
om_value_list
|
|
} output_mode_;
|
|
|
|
/// \brief Connection object we were initialized from, if any
|
|
///
|
|
/// This just provides a default for the Active Record methods
|
|
/// above that take Connection*.
|
|
mutable Connection* conn_;
|
|
|
|
private:
|
|
/// \brief Table name override for this particular object
|
|
const char* instance_table_name_;
|
|
|
|
friend std::ostream& operator <<(std::ostream&, const SsqlsBase&);
|
|
};
|
|
|
|
|
|
/// \brief Put contents of an SSQLSv2 derivative into a \c std::ostream
|
|
///
|
|
/// If you use this operator directly, you get a comma-separated list of
|
|
/// field values in the ostream. Whether those values are quoted and/or
|
|
/// escaped depends on the ostream type.
|
|
///
|
|
/// It is also useful to use this operator indirectly, via
|
|
/// SsqlsBase::equal_list() or SsqlsBase::name_list(). (There is also a
|
|
/// SsqlsBase::value_list(), but it's just an alias for calling this operator
|
|
/// directly.) These methods set a flag on the object that causes this
|
|
/// operator to insert an equals list (e.g. "name1 = value1, name2 =
|
|
/// value2...") or a name list into the stream. The flag is immediately
|
|
/// reset to give value lists again on completion of the insert operation.
|
|
/// For example:
|
|
///
|
|
/// \code
|
|
/// stock s = ...; // initialize an SSQLSv2 object of 'stock' class
|
|
/// cout << "Set field names: " << s.name_list() << endl;
|
|
/// \endcode
|
|
///
|
|
/// The \c s.name_list() call sets the output mode to "names", then passes
|
|
/// \c cout and \c *this to this operator, which then calls the version
|
|
/// of s.name_list() taking a stream reference, which is overridden in
|
|
/// the leaf class to know how to insert the names of all fields set on
|
|
/// the \c s object.
|
|
///
|
|
/// \param os IOstream to insert object contents into
|
|
/// \param sb object to insert into the stream
|
|
std::ostream& operator <<(std::ostream& os, const SsqlsBase& sb)
|
|
{
|
|
switch (sb.output_mode_) {
|
|
case SsqlsBase::om_equal_list: sb.equal_list(os); break;
|
|
case SsqlsBase::om_name_list: sb.name_list(os); break;
|
|
case SsqlsBase::om_value_list: sb.value_list(os); break;
|
|
}
|
|
|
|
sb.output_mode_ = SsqlsBase::om_value_list;
|
|
|
|
return os;
|
|
}
|
|
|
|
} // end namespace mysqlpp
|
|
|
|
#endif // !defined(MYSQLPP_SSQLS2_H)
|