MySQL 9.3.0
Source Code Documentation
utils_sqlstring.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2015, 2025, Oracle and/or its affiliates.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2.0,
6 * as published by the Free Software Foundation.
7 *
8 * This program is designed to work with certain software (including
9 * but not limited to OpenSSL) that is licensed under separate terms,
10 * as designated in a particular file or component or in included license
11 * documentation. The authors of MySQL hereby grant you an additional
12 * permission to link the program and your derivative works with the
13 * separately licensed software that they have either included with
14 * the program or referenced in the documentation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#ifndef _UTILS_SQLSTRING_H_
27#define _UTILS_SQLSTRING_H_
28
30
31#ifndef __STDC_FORMAT_MACROS
32#define __STDC_FORMAT_MACROS 1
33#endif
34#include <inttypes.h>
35#include <cstddef>
36#include <set>
37#include <string>
38#include <vector>
39
40#include <stdexcept>
41
42namespace mysqlrouter {
43
46 UseAnsiQuotes = 1 << 1,
47
48 EndOfInput = 1 << 7
49};
50
51std::string ROUTER_MYSQL_EXPORT escape_sql_string(const char *s,
52 bool wildcards = false);
53std::string ROUTER_MYSQL_EXPORT escape_sql_string(const char *s, int len,
54 bool wildcards = false);
55std::string ROUTER_MYSQL_EXPORT
56escape_sql_string(const std::string &string,
57 bool wildcards = false); // "strings" or 'strings'
58std::string ROUTER_MYSQL_EXPORT escape_backticks(const char *s,
59 int length); // `identifier`
60std::string ROUTER_MYSQL_EXPORT
61escape_backticks(const std::string &string); // `identifier`
62std::string ROUTER_MYSQL_EXPORT quote_identifier(const std::string &identifier,
63 const char quote_char);
64std::string ROUTER_MYSQL_EXPORT
65quote_identifier_if_needed(const std::string &ident, const char quote_char);
66
68 public:
70 int _flags;
71 sqlstringformat(const int flags) : _flags(flags) {}
72 };
73
74 /**
75 * Iterator wrapper, for serializing arrays of structures to string.
76 *
77 * This class forwards some operators that are defined in `Iterator` class,
78 * still the class that derives from `CustomContainerIterator`, must define
79 * `operator*` to change the structure to string or other simple type.
80 */
81 template <typename Iterator, typename Derived>
83 public:
84 CustomContainerIterator(const Iterator &it) : it_{it} {}
86 : it_{other.it_} {}
87 CustomContainerIterator(Iterator &&it) : it_{it} {}
88 virtual ~CustomContainerIterator() = default;
89
91 it_ = std::move(other.it_);
92 return *this;
93 }
94
96 it_ = other.it_;
97 return *this;
98 }
99
100 Derived &operator++() {
101 ++it_;
102 return *dynamic_cast<Derived *>(this);
103 }
104
105 bool operator!=(const CustomContainerIterator &other) const {
106 return it_ != other.it_;
107 }
108
109 static std::pair<Derived, Derived> from_iterators(Iterator begin,
110 Iterator end);
111
112 template <typename Container>
113 static std::pair<Derived, Derived> from_container(Container &c);
114
115 protected:
116 Iterator it_;
117 };
118
119 private:
120 std::string _formatted;
123 int _locked_escape{0};
124
125 std::string consume_until_next_escape();
126 int next_escape();
127 void lock_escape(int esc);
128 void unlock_escape();
129
130 sqlstring &append(const std::string &s);
131
132 sqlstring &format(int esc, const char *v, int length) {
133 if (esc == '!') {
134 std::string escaped = escape_backticks(v, length);
135 if ((_format._flags & QuoteOnlyIfNeeded) != 0)
137 else
138 append(quote_identifier(escaped, '`'));
139 } else if (esc == '?') {
140 if (v) {
141 if (_format._flags & UseAnsiQuotes)
142 append("\"").append(escape_sql_string(v, length)).append("\"");
143 else
144 append("'").append(escape_sql_string(v, length)).append("'");
145 } else {
146 append("NULL");
147 }
148 } else // shouldn't happen
149 throw std::invalid_argument(
150 "Error formatting SQL query: internal error, expected ? or ! escape "
151 "got something else");
152
153 return *this;
154 }
155
156 public:
157 static const sqlstring empty;
158 static const sqlstring null;
159 static const sqlstring end;
160
161 sqlstring();
162 sqlstring(const char *format_string, const sqlstringformat format = 0);
164 sqlstring &operator=(const sqlstring &) = default;
165 bool done() const;
166
167 void reset(const char *format_string, const sqlstringformat format = 0);
168
169 operator std::string() const;
170 std::string str() const;
171 bool is_empty() const;
172
173 inline bool operator==(const sqlstring &other) const {
174 return str() == other.str();
175 }
176
177 //! modifies formatting options
178 sqlstring &operator<<(const sqlstringformat);
179 //! replaces a ? in the format string with a float numeric value
180 sqlstring &operator<<(const float val) { return operator<<((double)val); }
181 //! replaces a ? in the format string with a double numeric value
182 sqlstring &operator<<(const double);
183 //! replaces a ? in the format string with a NULL value.
184 sqlstring &operator<<(const std::nullptr_t);
185 //! replaces a ? in the format string with a quoted string value or ! with a
186 //! back-quoted identifier value
187 sqlstring &operator<<(const std::string &);
188 //! replaces a ? in the format string with a quoted string value or ! with a
189 //! back-quoted identifier value is the value is NULL, ? will be replaced with
190 //! a NULL. ! will raise an exception
191 sqlstring &operator<<(const char *);
192 //! replaces a ? or ! with the content of the other string verbatim
194 //! replaces a ? with an array of bytes
195 sqlstring &operator<<(const std::vector<uint8_t> &v);
196
197 //! appends a pre-formatted sqlstring to a pre-formatted sqlstring
198 sqlstring &append_preformatted(const sqlstring &s);
199
200 sqlstring &append_preformatted_sep(const std::string &separator,
201 const sqlstring &s);
202
203 /**
204 * Replace `?` or `!` with multiple values.
205 *
206 * Each element of the container, is going to be applied to parameter type
207 * fetched at the start (either `?` or `!`). Each iteam is going to be
208 * separated by comma.
209 *
210 * Example 1:
211 *
212 * sqlstring s{"First=(?) Second=(!)"};
213 * s << std::vector<std::string>{"1","2","3"} << "a";
214 *
215 * The resulting query: First=("1","2","3") Second=(A)
216 *
217 * Example 2:
218 *
219 * sqlstring s{"First=(!) Second=(?)"};
220 * s << std::vector<std::string>{"1","2","3"} << "a";
221 *
222 * The resulting query: First=(1,2,3) Second=("A")
223 *
224 */
225 template <typename T>
226 sqlstring &operator<<(const std::pair<T, T> &iterators) {
227 auto esc = next_escape();
228 lock_escape(esc);
229 bool first = true;
230
231 T it = iterators.first;
232 T end = iterators.second;
233 for (; it != end; ++it) {
234 if (!first) {
235 append(",");
236 }
237 *this << *it;
238
239 first = false;
240 }
241 unlock_escape();
242 append(consume_until_next_escape());
243
244 return *this;
245 }
246
247 template <typename T>
248 sqlstring &operator<<(const std::vector<T> &values) {
249 using const_iterator = typename std::vector<T>::const_iterator;
250 *this << std::make_pair<const_iterator, const_iterator>(values.begin(),
251 values.end());
252
253 return *this;
254 }
255
256 template <typename T>
257 sqlstring &operator<<(const std::set<T> &values) {
258 using const_iterator = typename std::set<T>::const_iterator;
259 *this << std::make_pair<const_iterator, const_iterator>(values.begin(),
260 values.end());
261
262 return *this;
263 }
264
265 //! replaces a ? in the format string with any integer numeric value
266 template <typename T>
268 /**
269 * Import `to_string` function which enables serialization to string, for
270 * standard types.
271 *
272 * User can define `to_string` function for serialization of custom type.
273 * Both the function and the type must be located in the same `namespace`.
274 * Following this schema enables `argument-dependent-lookup/ADL` in stream
275 * operator of `sqlstring` (which uses the `to_string`).
276 */
277 using std::to_string;
278 int esc = next_escape();
279 if (esc != '?')
280 throw std::invalid_argument(
281 "Error formatting SQL query: invalid escape for numeric argument");
282 // Uses ADL here
283 append(to_string(value));
284 append(consume_until_next_escape());
285 return *this;
286 }
287};
288
289template <typename Iterator, typename Derived>
290template <typename Container>
291std::pair<Derived, Derived>
293 Container &c) {
294 return std::make_pair<Derived, Derived>(c.begin(), c.end());
295}
296
297template <typename Iterator, typename Derived>
298std::pair<Derived, Derived>
300 Iterator begin, Iterator end) {
301 return std::make_pair<Derived, Derived>(begin, end);
302}
303
304} // namespace mysqlrouter
305
306#endif
Iterator wrapper, for serializing arrays of structures to string.
Definition: utils_sqlstring.h:82
CustomContainerIterator & operator=(CustomContainerIterator &&other)
Definition: utils_sqlstring.h:90
CustomContainerIterator(const Iterator &it)
Definition: utils_sqlstring.h:84
Iterator it_
Definition: utils_sqlstring.h:116
CustomContainerIterator(const CustomContainerIterator &other)
Definition: utils_sqlstring.h:85
static std::pair< Derived, Derived > from_iterators(Iterator begin, Iterator end)
Definition: utils_sqlstring.h:299
static std::pair< Derived, Derived > from_container(Container &c)
Definition: utils_sqlstring.h:292
Derived & operator++()
Definition: utils_sqlstring.h:100
bool operator!=(const CustomContainerIterator &other) const
Definition: utils_sqlstring.h:105
CustomContainerIterator(Iterator &&it)
Definition: utils_sqlstring.h:87
CustomContainerIterator & operator=(const CustomContainerIterator &other)
Definition: utils_sqlstring.h:95
Definition: utils_sqlstring.h:67
sqlstringformat _format
Definition: utils_sqlstring.h:122
static const sqlstring empty
Definition: utils_sqlstring.h:157
sqlstring(const sqlstring &copy)
std::string _formatted
Definition: utils_sqlstring.h:120
sqlstring & format(int esc, const char *v, int length)
Definition: utils_sqlstring.h:132
sqlstring & operator<<(const std::set< T > &values)
Definition: utils_sqlstring.h:257
sqlstring & operator=(const sqlstring &)=default
bool operator==(const sqlstring &other) const
Definition: utils_sqlstring.h:173
static const sqlstring end
Definition: utils_sqlstring.h:159
sqlstring & operator<<(const T value)
replaces a ? in the format string with any integer numeric value
Definition: utils_sqlstring.h:267
sqlstring & operator<<(const std::vector< T > &values)
Definition: utils_sqlstring.h:248
std::string str() const
Definition: utils_sqlstring.cc:507
sqlstring & operator<<(const float val)
replaces a ? in the format string with a float numeric value
Definition: utils_sqlstring.h:180
std::string _format_string_left
Definition: utils_sqlstring.h:121
sqlstring & operator<<(const std::pair< T, T > &iterators)
Replace ? or ! with multiple values.
Definition: utils_sqlstring.h:226
static int flags[50]
Definition: hp_test1.cc:40
static const char separator
Definition: item_func.cc:4454
#define T
Definition: jit_executor_value.cc:373
static std::string to_string(const LEX_STRING &str)
Definition: lex_string.h:50
static char * escaped
Definition: mysqldump.cc:152
void copy(Shards< COUNT > &dst, const Shards< COUNT > &src) noexcept
Copy the counters, overwrite destination.
Definition: ut0counter.h:354
std::string HARNESS_EXPORT reset()
get 'reset attributes' ESC sequence.
Definition: vt100.cc:37
std::string str(const mysqlrouter::ConfigGenerator::Options::Endpoint &ep)
Definition: config_generator.cc:1084
std::string format(const routing_guidelines::Session_info &session_info, bool extended_session_info)
Definition: dest_metadata_cache.cc:170
bool length(const dd::Spatial_reference_system *srs, const Geometry *g1, double *length, bool *null) noexcept
Computes the length of linestrings and multilinestrings.
Definition: length.cc:76
bool is_empty(const std::string &str)
Definition: generic.h:34
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
mysqlrouter::sqlstring sqlstring
Definition: query_retry_on_ro.cc:36
Definition: base64.h:43
std::string ROUTER_MYSQL_EXPORT escape_backticks(const char *s, int length)
Definition: utils_sqlstring.cc:341
SqlStringFlags
Definition: utils_sqlstring.h:44
@ UseAnsiQuotes
Definition: utils_sqlstring.h:46
@ EndOfInput
Definition: utils_sqlstring.h:48
@ QuoteOnlyIfNeeded
Definition: utils_sqlstring.h:45
ROUTER_UTILS_EXPORT std::ostream & operator<<(std::ostream &strm, const URI &uri)
Definition: uri.cc:1207
std::string ROUTER_MYSQL_EXPORT quote_identifier(const std::string &identifier, const char quote_char)
Definition: utils_sqlstring.cc:387
const char * begin(const char *const c)
Definition: base64.h:44
std::string ROUTER_MYSQL_EXPORT quote_identifier_if_needed(const std::string &ident, const char quote_char)
Quotes the given identifier, but only if it needs to be quoted.
Definition: utils_sqlstring.cc:400
std::string ROUTER_MYSQL_EXPORT escape_sql_string(const char *s, bool wildcards=false)
Definition: utils_sqlstring.cc:329
const char * end(const char *const c)
Definition: base64.h:45
std::string ROUTER_CLUSTER_EXPORT to_string(const MetadataSchemaVersion &version)
Definition: cluster_metadata.cc:488
#define ROUTER_MYSQL_EXPORT
Definition: router_mysql_export.h:15
Definition: utils_sqlstring.h:69
int _flags
Definition: utils_sqlstring.h:70
sqlstringformat(const int flags)
Definition: utils_sqlstring.h:71