1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
|
/// \file insertpolicy.h
/// \brief Declares the InsertPolicy classes.
///
/// One creates an insert policy object to control how
/// Query::insertfrom() builds queries from collections of SSQLS
/// objects. Policy objects are what cause Query::insertfrom() to
/// have different insertion behavior than Query::insert(iter, iter)
///
/// These templates use a class called the AccessController, which
/// is a stand-in for the mysqlpp::Transaction class and defaults to
/// the Transaction class. Since some of the InsertPolicy objects
/// (SizeThresholdInsertPolicy and MaxPacketInsertPolicy) may cause
/// Query::insertfrom() to issue multiple SQL statements to perform
/// the insertion of all the objects in the container, and a failure in
/// one of these statements would leave the table in an indeterminate
/// state, the whole operation is wrapped in a transaction.
///
/// However, a transaction may not be desired if the calling code
/// is managing transactions, or transactions are not being used for
/// some other reason. In this case, the template can be instantiated
/// with the NoTransaction class. It provides the complete Transaction
/// class interface, while doing nothing.
///
/// Where possible, you should use one of the provided insert
/// policy classes, but you can define your own if you need a behavior
/// that the provided set doesn't include.
///
/// This file is not meant to be included in end-user code. It's
/// included in Query's public interface, since it is only used with
/// Query::insertfrom(). You access it as Query::InsertPolicy<T>
/***********************************************************************
Copyright (c) 2008-2009 by AboveNet, Inc., and (c) 2009 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
***********************************************************************/
#if !defined(MYSQLPP_INSERTPOLICY_H)
#define MYSQLPP_INSERTPOLICY_H
/// \brief An insert policy object that triggers a new INSERT
/// statement after a given number of rows have been inserted.
///
/// This policy is very lightweight, but is only reliable when you
/// can predict the size of each INSERT in advance. The others do
/// more processing to reduce the risk of unpredictable row sizes.
template <class AccessController = Transaction>
class MYSQLPP_EXPORT RowCountInsertPolicy
{
public:
/// \brief Constructor
RowCountInsertPolicy(unsigned int rows) :
cur_rows_(0),
max_rows_(rows)
{
}
/// \brief Destructor
~RowCountInsertPolicy() { }
/// \brief Can we add another object to the query?
///
/// \retval true if the object is allowed to be added to the
/// INSERT statement
template <class RowT>
bool can_add(int, const RowT&)
{
if (++cur_rows_ > max_rows_) {
cur_rows_ = 0;
return false;
}
else {
return true;
}
}
/// \brief Alias for our access controller type
typedef AccessController access_controller;
private:
unsigned int cur_rows_;
unsigned const int max_rows_;
};
/// \brief An insert policy object that triggers a new INSERT statement
/// after a size threshold for the length of the INSERT statement
/// is exceeded.
///
/// Although this insert policy isn't completely deterministic, it
/// avoids building the VALUES expression for the SSQLS object
/// passed in.
template <class AccessController = Transaction>
class MYSQLPP_EXPORT SizeThresholdInsertPolicy
{
public:
/// \brief Constructor
SizeThresholdInsertPolicy(int size) :
size_(size)
{
}
/// \brief Destructor
~SizeThresholdInsertPolicy() { }
/// \brief Can we add another object to the query?
///
/// \param size current length of the INSERT statement
/// \param object the SSQLS object to be added
///
/// \retval true if the object is allowed to be added to the
/// INSERT statement
template <class RowT>
bool can_add(int size, const RowT& object) const
{
return (size < size_);
}
/// \brief Alias for our access controller type
typedef AccessController access_controller;
private:
int size_;
};
/// \brief An insert policy object that triggers a new INSERT statement
/// if the object to be added would cause the statement to exceed
/// a maximum size.
///
/// This differs from the SizeThresholdInsertPolicy in that it builds
/// the VALUES expression and checks whether it would cause the
/// length of the INSERT statement to exceed the maximum size.
template <class AccessController = Transaction>
class MYSQLPP_EXPORT MaxPacketInsertPolicy
{
public:
/// \brief Constructor
///
/// \param con connection object used for escaping text
/// \param size the maximum allowed size for an INSERT
/// statement
MaxPacketInsertPolicy(Connection* con, int size) :
conn_(con), size_(size)
{
}
/// \brief Constructor
///
/// This version does not use a Connection* so it will not be
/// able to take the character set into account when escaping
/// the text.
///
/// \param size the maximum allowed size for an INSERT
/// statement
MaxPacketInsertPolicy(int size) :
conn_(0), size_(size)
{
}
/// \brief Destructor
~MaxPacketInsertPolicy() { }
/// \brief Can we add another object to the query?
///
/// \param size current length of the INSERT statement
/// \param object the SSQLS object to be added
///
/// \retval true if the object is allowed to be added to the
/// INSERT statement
template <class RowT>
bool can_add(int size, const RowT& object) const
{
if (size < size_) {
// Haven't hit size threshold yet, so see if this next
// item pushes it over the line.
SQLStream s(conn_);
s << ",(" << object.value_list() << ")";
return (size_ - size) >= static_cast<int>(s.str().size());
}
else {
// Already too much in query buffer!
return false;
}
}
/// \brief Alias for our access controller type
typedef AccessController access_controller;
private:
Connection* conn_;
int size_;
};
#endif // !defined(MYSQLPP_INSERTPOLICY_H)
|