345 lines
12 KiB
C++
345 lines
12 KiB
C++
/// \file stadapter.h
|
|
/// \brief Declares the SQLTypeAdapter class
|
|
|
|
/***********************************************************************
|
|
Copyright © 1998 by Kevin Atkinson, © 1999-2001 by MySQL AB, and
|
|
© 2004-2009, 2018 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_SQL_TYPE_ADAPTER_H)
|
|
#define MYSQLPP_SQL_TYPE_ADAPTER_H
|
|
|
|
#include "common.h"
|
|
|
|
#include "datetime.h"
|
|
#include "null.h"
|
|
#include "sql_buffer.h"
|
|
#include "tiny_int.h"
|
|
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
namespace mysqlpp {
|
|
|
|
#if !defined(DOXYGEN_IGNORE)
|
|
class MYSQLPP_EXPORT String;
|
|
#endif
|
|
|
|
/// \brief Converts many different data types to strings suitable for
|
|
/// use in SQL queries.
|
|
///
|
|
/// This class provides implicit conversion between many C++ types and
|
|
/// SQL-formatted string representations of that data without losing
|
|
/// important type information. This class is not for direct use
|
|
/// outside MySQL++ itself. It exists for those interfaces in MySQL++
|
|
/// that need to accept a value of any reasonable data type which it
|
|
/// will use in building a query string.
|
|
///
|
|
/// One major use for this is in the Query class interfaces for building
|
|
/// template queries: they have to be generic with respect to argument
|
|
/// type, but because we know we want the data in some kind of string
|
|
/// form eventually, we don't need to templatize it. The interface can
|
|
/// just use SQLTypeAdapter, which lets callers pass any reasonable data
|
|
/// type. The adapter converts the passed value implicitly.
|
|
///
|
|
/// The other major use for this type is the quoting and escaping logic
|
|
/// in Query's stream interface: rather than overload the << operators
|
|
/// and the manipulators for every single type we know the rules for \e a
|
|
/// \e priori, we just specialize the manipulators for SQLTypeAdapter.
|
|
/// The conversion to SQLTypeAdapter stringizes the data, which we needed
|
|
/// anyway for stream insertion, and holds enough type information so
|
|
/// that the manipulator can decide whether to do automatic quoting
|
|
/// and/or escaping.
|
|
|
|
class MYSQLPP_EXPORT SQLTypeAdapter
|
|
{
|
|
public:
|
|
typedef size_t size_type; ///< size of length values
|
|
|
|
/// \brief Default constructor; empty string
|
|
SQLTypeAdapter();
|
|
|
|
/// \brief Copy ctor
|
|
///
|
|
/// \param other the other SQLTypeAdapter object
|
|
///
|
|
/// This ctor only copies the pointer to the other SQLTypeAdapter's
|
|
/// data buffer and increments its reference counter. If you need a
|
|
/// deep copy, use one of the ctors that takes a string.
|
|
SQLTypeAdapter(const SQLTypeAdapter& other);
|
|
|
|
/// \brief Create a copy of a MySQL++ string
|
|
///
|
|
/// This does reference-counted buffer sharing with the other
|
|
/// object. If you need a deep copy, pass the result of
|
|
/// either String::c_str() or String::conv() instead, which will
|
|
/// call one of the other string ctors.
|
|
SQLTypeAdapter(const String& str, bool processed = false);
|
|
|
|
/// \brief Create a copy of a C++ string
|
|
SQLTypeAdapter(const std::string& str, bool processed = false);
|
|
|
|
/// \brief Create a copy of a null-terminated C string
|
|
SQLTypeAdapter(const char* str, bool processed = false);
|
|
|
|
/// \brief Create a copy of an arbitrary block of data
|
|
SQLTypeAdapter(const char* str, int len, bool processed = false);
|
|
|
|
/// \brief Create a single-character string
|
|
///
|
|
/// If you mean for \c c to be treated as a small integer, you
|
|
/// should be using mysqlpp::tiny_int instead. It avoids the
|
|
/// confusion in C++ between integer and character. See the
|
|
/// documentation for tiny_int.h for details.
|
|
SQLTypeAdapter(char c);
|
|
|
|
/// \brief Create a string representation of SQL \c TINYINT
|
|
SQLTypeAdapter(tiny_int<signed char> i);
|
|
|
|
/// \brief Create a string representation of SQL \c TINYINT
|
|
/// \c UNSIGNED
|
|
SQLTypeAdapter(tiny_int<unsigned char> i);
|
|
|
|
/// \brief Create a string representation of a \c short \c int value
|
|
SQLTypeAdapter(short i);
|
|
|
|
/// \brief Create a string representation of an \c unsigned
|
|
/// \c short \c int value
|
|
SQLTypeAdapter(unsigned short i);
|
|
|
|
/// \brief Create a string representation of an \c int value
|
|
SQLTypeAdapter(int i);
|
|
|
|
/// \brief Create a string representation of an \c unsigned \c int
|
|
/// value
|
|
SQLTypeAdapter(unsigned i);
|
|
|
|
/// \brief Create a string representation of a \c long \c int value
|
|
SQLTypeAdapter(long i);
|
|
|
|
/// \brief Create a string representation of an \c unsigned
|
|
/// \c long \c int value
|
|
SQLTypeAdapter(unsigned long i);
|
|
|
|
/// \brief Create a string representation of a \c longlong value
|
|
SQLTypeAdapter(longlong i);
|
|
|
|
/// \brief Create a string representation of an \c unsigned
|
|
/// \c longlong value
|
|
SQLTypeAdapter(ulonglong i);
|
|
|
|
/// \brief Create a string representation of a \c float value
|
|
SQLTypeAdapter(float i);
|
|
|
|
/// \brief Create a string representation of a \c double value
|
|
SQLTypeAdapter(double i);
|
|
|
|
/// \brief Create a SQL string representation of a date
|
|
SQLTypeAdapter(const Date& d);
|
|
|
|
/// \brief Create a SQL string representation of a date and time
|
|
SQLTypeAdapter(const DateTime& dt);
|
|
|
|
/// \brief Create a SQL string representation of a time
|
|
SQLTypeAdapter(const Time& t);
|
|
|
|
/// \brief Create object representing SQL NULL
|
|
SQLTypeAdapter(const null_type& i);
|
|
|
|
/// \brief Standard assignment operator
|
|
///
|
|
/// \see assign(const SQLTypeAdapter&) for details
|
|
SQLTypeAdapter& operator =(const SQLTypeAdapter& rhs);
|
|
|
|
/// \brief Replace contents of object with a SQL null
|
|
///
|
|
/// \see assign(const null_type&) for details
|
|
SQLTypeAdapter& operator =(const null_type& n);
|
|
|
|
/// \brief Returns a const char pointer to the object's raw data
|
|
operator const char*() const { return data(); }
|
|
|
|
/// \brief Copies another SQLTypeAdapter's data buffer into this
|
|
/// object.
|
|
///
|
|
/// \param sta Other object to copy
|
|
///
|
|
/// \retval *this
|
|
///
|
|
/// Detaches this object from its internal buffer and attaches
|
|
/// itself to the other object's buffer, with reference counting
|
|
/// on each side. If you need a deep copy, call one of the
|
|
/// assign() overloads taking a C or C++ string instead.
|
|
SQLTypeAdapter& assign(const SQLTypeAdapter& sta);
|
|
|
|
/// \brief Copies a C string or a raw buffer into this object.
|
|
///
|
|
/// \param pc Pointer to char buffer to copy
|
|
/// \param len Number of characters to copy; default tells function
|
|
/// to use the return value of strlen() instead.
|
|
///
|
|
/// \retval *this
|
|
///
|
|
/// If you give the len parameter, this function will treat pc as a
|
|
/// pointer to an array of char, not as a C string. It only treats
|
|
/// null characters as special when you leave len at its default.
|
|
SQLTypeAdapter& assign(const char* pc, int len = -1);
|
|
|
|
/// \brief Replaces contents of object with a SQL null
|
|
///
|
|
/// \param n typically, the MySQL++ global object mysqlpp::null
|
|
///
|
|
/// \retval *this
|
|
SQLTypeAdapter& assign(const null_type& n);
|
|
|
|
/// \brief Returns the character at a given position within the
|
|
/// string buffer.
|
|
///
|
|
/// \throw mysqlpp::BadIndex if the internal buffer is not
|
|
/// initialized (default ctor called, and no subsequent assignment)
|
|
/// or if there are not at least i + 1 characters in the buffer.
|
|
///
|
|
/// WARNING: The throw-spec is incorrect, but it's irrelevant since
|
|
/// they're obsolete in modern C++ now anyway, since they were
|
|
/// always unreliable. If we ever get to MySQL++ 4 and can break
|
|
/// the ABI, this throw-spec will just go away.
|
|
#if !defined(DOXYGEN_IGNORE) && __cplusplus >= 201103L
|
|
// Can't use MAY_THROW() here: it confuses Doxygen 1.8.14.
|
|
char at(size_type i) const noexcept(false);
|
|
#else
|
|
char at(size_type i) const throw(std::out_of_range);
|
|
#endif
|
|
|
|
/// \brief Compare the internal buffer to the given string
|
|
///
|
|
/// Works just like string::compare(const std::string&).
|
|
int compare(const SQLTypeAdapter& other) const;
|
|
|
|
/// \brief Compare the internal buffer to the given string
|
|
///
|
|
/// Works just like string::compare(const std::string&).
|
|
int compare(const std::string& other) const;
|
|
|
|
/// \brief Compare the internal buffer to the given string
|
|
///
|
|
/// Works just like string::compare(size_type, size_type,
|
|
/// std::string&).
|
|
int compare(size_type pos, size_type num, std::string& other) const;
|
|
|
|
/// \brief Compare the internal buffer to the given string
|
|
///
|
|
/// Works just like string::compare(const char*).
|
|
int compare(const char* other) const;
|
|
|
|
/// \brief Compare the internal buffer to the given string
|
|
///
|
|
/// Works just like string::compare(size_type, size_type,
|
|
/// const char*).
|
|
int compare(size_type pos, size_type num, const char* other) const;
|
|
|
|
/// \brief Return pointer to raw data buffer
|
|
const char* data() const;
|
|
|
|
/// \brief Returns true if we were initialized with a data type
|
|
/// that must be escaped when used in a SQL query
|
|
bool escape_q() const;
|
|
|
|
/// \brief Return true if buffer's contents represent a SQL
|
|
/// null.
|
|
///
|
|
/// The buffer's actual content will probably be "NULL" or
|
|
/// something like it, but in the SQL data type system, a SQL
|
|
/// null is distinct from a plain string with value "NULL".
|
|
bool is_null() const { return buffer_->is_null(); }
|
|
|
|
/// \brief Returns true if the internal 'processed' flag is set.
|
|
///
|
|
/// This is an implementation detail of template queries, used to
|
|
/// prevent repeated processing of values.
|
|
bool is_processed() const { return is_processed_; }
|
|
|
|
/// \brief Return number of bytes in data buffer
|
|
size_type length() const;
|
|
size_type size() const { return length(); } ///< alias for length()
|
|
|
|
/// \brief Returns true if we were initialized with a data type
|
|
/// that must be quoted when used in a SQL query
|
|
bool quote_q() const;
|
|
|
|
/// \brief Returns the type ID of the buffer's data
|
|
///
|
|
/// Values from type_info.h. At the moment, these are the same as
|
|
/// the underlying MySQL C API type IDs, but it's not a good idea
|
|
/// to count on this remaining the case.
|
|
int type_id() const;
|
|
|
|
/// \brief Turns on the internal 'is_processed_' flag.
|
|
///
|
|
/// This is an implementation detail of template queries, used to
|
|
/// prevent repeated processing of values.
|
|
void set_processed() { is_processed_ = true; }
|
|
|
|
#if !defined(DOXYGEN_IGNORE)
|
|
// Parallel interface for Null<>-wrapped versions of types we
|
|
// support above. No need for parallel documentation.
|
|
SQLTypeAdapter(const Null<std::string>& str, bool processed = false);
|
|
SQLTypeAdapter(const Null<String>& str, bool processed = false);
|
|
SQLTypeAdapter(Null<char> c);
|
|
SQLTypeAdapter(Null< tiny_int<signed char> > i);
|
|
SQLTypeAdapter(Null< tiny_int<unsigned char> > i);
|
|
SQLTypeAdapter(Null<short> i);
|
|
SQLTypeAdapter(Null<unsigned short> i);
|
|
SQLTypeAdapter(Null<int> i);
|
|
SQLTypeAdapter(Null<unsigned> i);
|
|
SQLTypeAdapter(Null<long> i);
|
|
SQLTypeAdapter(Null<unsigned long> i);
|
|
SQLTypeAdapter(Null<longlong> i);
|
|
SQLTypeAdapter(Null<ulonglong> i);
|
|
SQLTypeAdapter(Null<float> i);
|
|
SQLTypeAdapter(Null<double> i);
|
|
SQLTypeAdapter(const Null<Date>& d);
|
|
SQLTypeAdapter(const Null<DateTime>& dt);
|
|
SQLTypeAdapter(const Null<Time>& t);
|
|
SQLTypeAdapter& operator =(const Null<std::string>& str);
|
|
#endif // !defined(DOXYGEN_IGNORE)
|
|
|
|
private:
|
|
/// \brief Our internal string buffer
|
|
RefCountedBuffer buffer_;
|
|
|
|
/// \brief If true, one of the MySQL++ manipulators has processed
|
|
/// the string data.
|
|
///
|
|
/// "Processing" is escaping special SQL characters, and/or adding
|
|
/// quotes. See the documentation for manip.h for details.
|
|
///
|
|
/// This flag is used by the template query mechanism, to prevent a
|
|
/// string from being re-escaped or re-quoted each time that query
|
|
/// is reused. The flag is reset by operator=, to force the new
|
|
/// parameter value to be re-processed.
|
|
bool is_processed_;
|
|
};
|
|
|
|
} // end namespace mysqlpp
|
|
|
|
#endif // !defined(MYSQLPP_SQL_TYPE_ADAPTER_H)
|