include/sqlon/expression.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /****************************************************************************** | ||
| 2 | ** | ||
| 3 | ** Copyright (C) 2026 Ivan Pinezhaninov <ivan.pinezhaninov@gmail.com> | ||
| 4 | ** | ||
| 5 | ** This file is part of the SQLon - which can be found at | ||
| 6 | ** https://github.com/IvanPinezhaninov/sqlon/. | ||
| 7 | ** | ||
| 8 | ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 9 | ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 10 | ** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||
| 11 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | ||
| 12 | ** DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR | ||
| 13 | ** OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR | ||
| 14 | ** THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
| 15 | ** | ||
| 16 | ******************************************************************************/ | ||
| 17 | |||
| 18 | #ifndef SQLON_EXPRESSION_H | ||
| 19 | #define SQLON_EXPRESSION_H | ||
| 20 | |||
| 21 | #include <sqlon/detail/nodes.h> | ||
| 22 | #include <sqlon/error.h> | ||
| 23 | #include <sqlon/export.h> | ||
| 24 | |||
| 25 | #include <cstddef> | ||
| 26 | #include <initializer_list> | ||
| 27 | #include <memory> | ||
| 28 | #include <string> | ||
| 29 | #include <string_view> | ||
| 30 | #include <type_traits> | ||
| 31 | #include <utility> | ||
| 32 | #include <vector> | ||
| 33 | |||
| 34 | namespace sqlon { | ||
| 35 | |||
| 36 | /** @brief Typed SQL value expression. */ | ||
| 37 | template<typename T> | ||
| 38 | class expression; | ||
| 39 | |||
| 40 | /** @brief Typed reusable parameter slot for prepared queries. */ | ||
| 41 | template<typename T> | ||
| 42 | class parameter_slot; | ||
| 43 | |||
| 44 | class query; | ||
| 45 | class select_query; | ||
| 46 | class ordering; | ||
| 47 | class window_spec; | ||
| 48 | |||
| 49 | namespace detail { | ||
| 50 | |||
| 51 | template<typename T> | ||
| 52 | struct normalized_type { | ||
| 53 | using decayed_type = std::decay_t<T>; | ||
| 54 | using type = std::conditional_t<std::is_same_v<decayed_type, const char*> || std::is_same_v<decayed_type, char*>, | ||
| 55 | std::string, parameter_expression_type_t<decayed_type>>; | ||
| 56 | }; | ||
| 57 | |||
| 58 | template<std::size_t N> | ||
| 59 | struct normalized_type<const char (&)[N]> { | ||
| 60 | using type = std::string; | ||
| 61 | }; | ||
| 62 | |||
| 63 | template<std::size_t N> | ||
| 64 | struct normalized_type<char (&)[N]> { | ||
| 65 | using type = std::string; | ||
| 66 | }; | ||
| 67 | |||
| 68 | template<typename T> | ||
| 69 | using normalized_type_t = typename normalized_type<T>::type; | ||
| 70 | |||
| 71 | template<typename T> | ||
| 72 | struct is_expression : std::false_type {}; | ||
| 73 | |||
| 74 | template<typename T> | ||
| 75 | struct is_expression<expression<T>> : std::true_type {}; | ||
| 76 | |||
| 77 | template<typename T, typename = void> | ||
| 78 | struct is_expression_like : std::false_type {}; | ||
| 79 | |||
| 80 | template<typename T> | ||
| 81 | struct is_expression_like<T, std::void_t<typename std::decay_t<T>::value_type>> | ||
| 82 | : std::is_base_of<expression<typename std::decay_t<T>::value_type>, std::decay_t<T>> {}; | ||
| 83 | |||
| 84 | template<typename T, bool = is_expression_like<T>::value> | ||
| 85 | struct expression_value_type { | ||
| 86 | using type = normalized_type_t<T>; | ||
| 87 | }; | ||
| 88 | |||
| 89 | template<typename T> | ||
| 90 | struct expression_value_type<T, true> { | ||
| 91 | using type = typename std::decay_t<T>::value_type; | ||
| 92 | }; | ||
| 93 | |||
| 94 | template<typename T> | ||
| 95 | using expression_value_type_t = typename expression_value_type<T>::type; | ||
| 96 | |||
| 97 | template<typename... Values> | ||
| 98 | using are_non_query_values = std::conjunction<std::negation<std::is_base_of<query, std::decay_t<Values>>>...>; | ||
| 99 | |||
| 100 | template<typename Left, typename Right> | ||
| 101 | inline constexpr bool compatible_expression_types = | ||
| 102 | std::is_same_v<normalized_type_t<Left>, normalized_type_t<Right>> || | ||
| 103 | (std::is_arithmetic_v<normalized_type_t<Left>> && std::is_arithmetic_v<normalized_type_t<Right>> && | ||
| 104 | !std::is_same_v<normalized_type_t<Left>, bool> && !std::is_same_v<normalized_type_t<Right>, bool>) || | ||
| 105 | std::is_same_v<normalized_type_t<Right>, std::nullptr_t>; | ||
| 106 | |||
| 107 | SQLON_API detail::expression_ptr make_expression_node(detail::expression_kind kind, std::string text = {}, | ||
| 108 | std::vector<detail::expression_ptr> operands = {}); | ||
| 109 | |||
| 110 | SQLON_API detail::expression_ptr make_binary_node(std::string operation, detail::expression_ptr left, | ||
| 111 | detail::expression_ptr right); | ||
| 112 | |||
| 113 | SQLON_API detail::expression_ptr make_raw_expression_node(std::string sql, | ||
| 114 | std::vector<detail::expression_ptr> operands); | ||
| 115 | |||
| 116 | SQLON_API std::size_t next_parameter_identity(); | ||
| 117 | |||
| 118 | SQLON_API bool valid_function_name(std::string_view name) noexcept; | ||
| 119 | |||
| 120 | struct expression_access; | ||
| 121 | |||
| 122 | } // namespace detail | ||
| 123 | |||
| 124 | /** @brief Typed, reusable handle to a SQL expression. */ | ||
| 125 | template<typename T> | ||
| 126 | class expression { | ||
| 127 | public: | ||
| 128 | /** @brief C++ value type represented by the expression. */ | ||
| 129 | using value_type = T; | ||
| 130 | |||
| 131 | protected: | ||
| 132 | /** @brief Creates an expression from an internal node. */ | ||
| 133 | 1101 | explicit expression(detail::expression_ptr node) | |
| 134 | 1101 | : m_node(std::move(node)) | |
| 135 | 1101 | {} | |
| 136 | |||
| 137 | public: | ||
| 138 | /** @brief Returns this expression with a SQL alias. */ | ||
| 139 | 14 | expression<T> as(std::string alias) const | |
| 140 | { | ||
| 141 |
4/9sqlon::expression<int>::as(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) const:
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 time.
sqlon::expression<long>::as(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) const:
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 5 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::as(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) const:
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
|
14 | if (alias.empty()) throw invalid_query{"an expression alias cannot be empty"}; |
| 142 |
8/18sqlon::expression<int>::as(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) const:
✗ Branch 1 not taken.
✗ Branch 6 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
sqlon::expression<long>::as(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) const:
✓ Branch 1 taken 12 times.
✓ Branch 6 taken 12 times.
✓ Branch 12 taken 12 times.
✓ Branch 13 taken 12 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::as(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) const:
✓ Branch 1 taken 1 time.
✓ Branch 6 taken 1 time.
✓ Branch 12 taken 1 time.
✓ Branch 13 taken 1 time.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
39 | return expression<T>{detail::make_expression_node(detail::expression_kind::alias, std::move(alias), {m_node})}; |
| 143 | 13 | } | |
| 144 | |||
| 145 | /** @brief Creates an IS NULL predicate. */ | ||
| 146 | 1 | expression<bool> is_null() const | |
| 147 | { | ||
| 148 |
5/7✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
✓ Branch 13 taken 1 time.
✓ Branch 14 taken 1 time.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
5 | return expression<bool>{detail::make_expression_node(detail::expression_kind::unary, "is_null", {m_node})}; |
| 149 | 1 | } | |
| 150 | |||
| 151 | /** @brief Creates an IS NOT NULL predicate. */ | ||
| 152 | 3 | expression<bool> is_not_null() const | |
| 153 | { | ||
| 154 |
10/14sqlon::expression<long>::is_not_null() const:
✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
✓ Branch 13 taken 1 time.
✓ Branch 14 taken 1 time.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::is_not_null() const:
✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 2 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
15 | return expression<bool>{detail::make_expression_node(detail::expression_kind::unary, "is_not_null", {m_node})}; |
| 155 | 3 | } | |
| 156 | |||
| 157 | /** @brief Creates an IS NULL predicate. */ | ||
| 158 | 1 | expression<bool> operator==(std::nullptr_t) const | |
| 159 | { | ||
| 160 | 1 | return is_null(); | |
| 161 | } | ||
| 162 | |||
| 163 | /** @brief Creates an IS NOT NULL predicate. */ | ||
| 164 | 1 | expression<bool> operator!=(std::nullptr_t) const | |
| 165 | { | ||
| 166 | 1 | return is_not_null(); | |
| 167 | } | ||
| 168 | |||
| 169 | /** @brief Creates an equality predicate with a compatible expression or value. */ | ||
| 170 | template<typename Right> | ||
| 171 | expression<bool> operator==(Right&& right) const; | ||
| 172 | |||
| 173 | /** @brief Creates an inequality predicate with a compatible expression or value. */ | ||
| 174 | template<typename Right> | ||
| 175 | expression<bool> operator!=(Right&& right) const; | ||
| 176 | |||
| 177 | /** @brief Creates a less-than predicate with a compatible expression or value. */ | ||
| 178 | template<typename Right> | ||
| 179 | expression<bool> operator<(Right&& right) const; | ||
| 180 | |||
| 181 | /** @brief Creates a less-than-or-equal predicate with a compatible expression or value. */ | ||
| 182 | template<typename Right> | ||
| 183 | expression<bool> operator<=(Right&& right) const; | ||
| 184 | |||
| 185 | /** @brief Creates a greater-than predicate with a compatible expression or value. */ | ||
| 186 | template<typename Right> | ||
| 187 | expression<bool> operator>(Right&& right) const; | ||
| 188 | |||
| 189 | /** @brief Creates a greater-than-or-equal predicate with a compatible expression or value. */ | ||
| 190 | template<typename Right> | ||
| 191 | expression<bool> operator>=(Right&& right) const; | ||
| 192 | |||
| 193 | /** @brief Named alias for the equality operator. */ | ||
| 194 | template<typename Right> | ||
| 195 | 4 | expression<bool> eq(Right&& right) const | |
| 196 | { | ||
| 197 | 4 | return operator==(std::forward<Right>(right)); | |
| 198 | } | ||
| 199 | |||
| 200 | /** @brief Named alias for the inequality operator. */ | ||
| 201 | template<typename Right> | ||
| 202 | 1 | expression<bool> ne(Right&& right) const | |
| 203 | { | ||
| 204 | 1 | return operator!=(std::forward<Right>(right)); | |
| 205 | } | ||
| 206 | |||
| 207 | /** @brief Named alias for the less-than operator. */ | ||
| 208 | template<typename Right> | ||
| 209 | 1 | expression<bool> lt(Right&& right) const | |
| 210 | { | ||
| 211 | 1 | return operator<(std::forward<Right>(right)); | |
| 212 | } | ||
| 213 | |||
| 214 | /** @brief Named alias for the less-than-or-equal operator. */ | ||
| 215 | template<typename Right> | ||
| 216 | 1 | expression<bool> le(Right&& right) const | |
| 217 | { | ||
| 218 | 1 | return operator<=(std::forward<Right>(right)); | |
| 219 | } | ||
| 220 | |||
| 221 | /** @brief Named alias for the greater-than operator. */ | ||
| 222 | template<typename Right> | ||
| 223 | 1 | expression<bool> gt(Right&& right) const | |
| 224 | { | ||
| 225 | 1 | return operator>(std::forward<Right>(right)); | |
| 226 | } | ||
| 227 | |||
| 228 | /** @brief Named alias for the greater-than-or-equal operator. */ | ||
| 229 | template<typename Right> | ||
| 230 | 1 | expression<bool> ge(Right&& right) const | |
| 231 | { | ||
| 232 | 1 | return operator>=(std::forward<Right>(right)); | |
| 233 | } | ||
| 234 | |||
| 235 | /** @brief Creates a numeric addition expression. */ | ||
| 236 | template<typename Right, typename U = T, std::enable_if_t<std::is_arithmetic_v<U>, int> = 0> | ||
| 237 | expression<std::common_type_t<T, detail::expression_value_type_t<Right>>> operator+(Right&& right) const; | ||
| 238 | |||
| 239 | /** @brief Creates a numeric subtraction expression. */ | ||
| 240 | template<typename Right, typename U = T, std::enable_if_t<std::is_arithmetic_v<U>, int> = 0> | ||
| 241 | expression<std::common_type_t<T, detail::expression_value_type_t<Right>>> operator-(Right&& right) const; | ||
| 242 | |||
| 243 | /** @brief Creates a numeric multiplication expression. */ | ||
| 244 | template<typename Right, typename U = T, std::enable_if_t<std::is_arithmetic_v<U>, int> = 0> | ||
| 245 | expression<std::common_type_t<T, detail::expression_value_type_t<Right>>> operator*(Right&& right) const; | ||
| 246 | |||
| 247 | /** @brief Creates a numeric division expression. */ | ||
| 248 | template<typename Right, typename U = T, std::enable_if_t<std::is_arithmetic_v<U>, int> = 0> | ||
| 249 | expression<std::common_type_t<T, detail::expression_value_type_t<Right>>> operator/(Right&& right) const; | ||
| 250 | |||
| 251 | /** @brief Named alias for numeric addition. */ | ||
| 252 | template<typename Right, typename U = T, std::enable_if_t<std::is_arithmetic_v<U>, int> = 0> | ||
| 253 | 1 | expression<std::common_type_t<T, detail::expression_value_type_t<Right>>> add(Right&& right) const | |
| 254 | { | ||
| 255 | 1 | return operator+(std::forward<Right>(right)); | |
| 256 | } | ||
| 257 | |||
| 258 | /** @brief Named alias for numeric subtraction. */ | ||
| 259 | template<typename Right, typename U = T, std::enable_if_t<std::is_arithmetic_v<U>, int> = 0> | ||
| 260 | 1 | expression<std::common_type_t<T, detail::expression_value_type_t<Right>>> sub(Right&& right) const | |
| 261 | { | ||
| 262 | 1 | return operator-(std::forward<Right>(right)); | |
| 263 | } | ||
| 264 | |||
| 265 | /** @brief Named alias for numeric multiplication. */ | ||
| 266 | template<typename Right, typename U = T, std::enable_if_t<std::is_arithmetic_v<U>, int> = 0> | ||
| 267 | 1 | expression<std::common_type_t<T, detail::expression_value_type_t<Right>>> mul(Right&& right) const | |
| 268 | { | ||
| 269 | 1 | return operator*(std::forward<Right>(right)); | |
| 270 | } | ||
| 271 | |||
| 272 | /** @brief Named alias for numeric division. */ | ||
| 273 | template<typename Right, typename U = T, std::enable_if_t<std::is_arithmetic_v<U>, int> = 0> | ||
| 274 | 1 | expression<std::common_type_t<T, detail::expression_value_type_t<Right>>> div(Right&& right) const | |
| 275 | { | ||
| 276 | 1 | return operator/(std::forward<Right>(right)); | |
| 277 | } | ||
| 278 | |||
| 279 | /** @brief Creates an ascending ordering for this expression. */ | ||
| 280 | ordering asc() const; | ||
| 281 | |||
| 282 | /** @brief Creates a descending ordering for this expression. */ | ||
| 283 | ordering desc() const; | ||
| 284 | |||
| 285 | /** @brief Creates an IN predicate from compatible values. */ | ||
| 286 | template<typename... Values, std::enable_if_t<detail::are_non_query_values<Values...>::value, int> = 0> | ||
| 287 | expression<bool> in(Values&&... values) const; | ||
| 288 | |||
| 289 | /** @brief Creates an IN predicate from a subquery. */ | ||
| 290 | expression<bool> in(const select_query& value) const; | ||
| 291 | |||
| 292 | /** @brief Creates a NOT IN predicate from compatible values. */ | ||
| 293 | template<typename... Values, std::enable_if_t<detail::are_non_query_values<Values...>::value, int> = 0> | ||
| 294 | expression<bool> not_in(Values&&... values) const; | ||
| 295 | |||
| 296 | /** @brief Creates a NOT IN predicate from a subquery. */ | ||
| 297 | expression<bool> not_in(const select_query& value) const; | ||
| 298 | |||
| 299 | /** @brief Creates a BETWEEN predicate with compatible bounds. */ | ||
| 300 | template<typename Lower, typename Upper> | ||
| 301 | expression<bool> between(Lower&& lower, Upper&& upper) const; | ||
| 302 | |||
| 303 | /** @brief Creates a LIKE predicate for a string expression. */ | ||
| 304 | template<typename Pattern> | ||
| 305 | expression<bool> like(Pattern&& pattern) const; | ||
| 306 | |||
| 307 | /** @brief Creates a NOT LIKE predicate for a string expression. */ | ||
| 308 | template<typename Pattern> | ||
| 309 | expression<bool> not_like(Pattern&& pattern) const; | ||
| 310 | |||
| 311 | /** @brief Applies a window specification to this expression. */ | ||
| 312 | expression<T> over(const window_spec& window) const; | ||
| 313 | |||
| 314 | private: | ||
| 315 | template<typename> | ||
| 316 | friend class expression; | ||
| 317 | friend struct detail::expression_access; | ||
| 318 | |||
| 319 | detail::expression_ptr m_node; | ||
| 320 | }; | ||
| 321 | |||
| 322 | namespace detail { | ||
| 323 | |||
| 324 | struct expression_access final { | ||
| 325 | template<typename T> | ||
| 326 | 446 | static expression<T> make(expression_ptr node) | |
| 327 | { | ||
| 328 | 446 | return expression<T>{std::move(node)}; | |
| 329 | } | ||
| 330 | |||
| 331 | template<typename T> | ||
| 332 | 965 | static const expression_ptr& node(const expression<T>& value) noexcept | |
| 333 | { | ||
| 334 | 965 | return value.m_node; | |
| 335 | } | ||
| 336 | }; | ||
| 337 | |||
| 338 | } // namespace detail | ||
| 339 | |||
| 340 | /** @brief Converts an expression-like value to its base expression handle. */ | ||
| 341 | template<typename T, std::enable_if_t<detail::is_expression_like<T>::value, int> = 0> | ||
| 342 | 443 | expression<typename std::decay_t<T>::value_type> to_expression(T&& value) | |
| 343 | { | ||
| 344 | using value_type = typename std::decay_t<T>::value_type; | ||
| 345 | 443 | return static_cast<const expression<value_type>&>(value); | |
| 346 | } | ||
| 347 | |||
| 348 | /** @brief Converts an ordinary C++ value to a bound parameter expression. */ | ||
| 349 | template<typename T, std::enable_if_t<!detail::is_expression_like<T>::value, int> = 0> | ||
| 350 | 262 | expression<detail::normalized_type_t<T>> to_expression(T&& value) | |
| 351 | { | ||
| 352 | using value_type = detail::normalized_type_t<T>; | ||
| 353 |
15/15sqlon::expression<sqlon::detail::normalized_type<ClientId>::type> sqlon::to_expression<ClientId, 0>(ClientId&&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<ClientUuid const&>::type> sqlon::to_expression<ClientUuid const&, 0>(ClientUuid const&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<bool>::type> sqlon::to_expression<bool, 0>(bool&&):
✓ Branch 1 taken 41 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [4]>::type> sqlon::to_expression<char const (&) [4], 0>(char const (&) [4]):
✓ Branch 1 taken 11 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [6]>::type> sqlon::to_expression<char const (&) [6], 0>(char const (&) [6]):
✓ Branch 1 taken 40 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [7]>::type> sqlon::to_expression<char const (&) [7], 0>(char const (&) [7]):
✓ Branch 1 taken 3 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [8]>::type> sqlon::to_expression<char const (&) [8], 0>(char const (&) [8]):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<decltype(nullptr)>::type> sqlon::to_expression<decltype(nullptr), 0>(decltype(nullptr)&&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<double>::type> sqlon::to_expression<double, 0>(double&&):
✓ Branch 1 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::to_expression<int, 0>(int&&):
✓ Branch 1 taken 117 times.
sqlon::expression<sqlon::detail::normalized_type<long>::type> sqlon::to_expression<long, 0>(long&&):
✓ Branch 1 taken 5 times.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type> sqlon::to_expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, 0>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 1 taken 36 times.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type> sqlon::to_expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, 0>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::byte, std::allocator<std::byte> > const&>::type> sqlon::to_expression<std::vector<std::byte, std::allocator<std::byte> > const&, 0>(std::vector<std::byte, std::allocator<std::byte> > const&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<unsigned long>::type> sqlon::to_expression<unsigned long, 0>(unsigned long&&):
✓ Branch 1 taken 1 time.
|
262 | std::shared_ptr<detail::expression_node> node = std::make_shared<detail::expression_node>(); |
| 354 | 262 | node->kind = detail::expression_kind::parameter; | |
| 355 |
22/22sqlon::expression<sqlon::detail::normalized_type<ClientId>::type> sqlon::to_expression<ClientId, 0>(ClientId&&):
✓ Branch 4 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<ClientUuid const&>::type> sqlon::to_expression<ClientUuid const&, 0>(ClientUuid const&):
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<bool>::type> sqlon::to_expression<bool, 0>(bool&&):
✓ Branch 4 taken 41 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [4]>::type> sqlon::to_expression<char const (&) [4], 0>(char const (&) [4]):
✓ Branch 3 taken 11 times.
✓ Branch 6 taken 11 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [6]>::type> sqlon::to_expression<char const (&) [6], 0>(char const (&) [6]):
✓ Branch 3 taken 40 times.
✓ Branch 6 taken 40 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [7]>::type> sqlon::to_expression<char const (&) [7], 0>(char const (&) [7]):
✓ Branch 3 taken 3 times.
✓ Branch 6 taken 3 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [8]>::type> sqlon::to_expression<char const (&) [8], 0>(char const (&) [8]):
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<decltype(nullptr)>::type> sqlon::to_expression<decltype(nullptr), 0>(decltype(nullptr)&&):
✓ Branch 4 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<double>::type> sqlon::to_expression<double, 0>(double&&):
✓ Branch 4 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::to_expression<int, 0>(int&&):
✓ Branch 4 taken 117 times.
sqlon::expression<sqlon::detail::normalized_type<long>::type> sqlon::to_expression<long, 0>(long&&):
✓ Branch 4 taken 5 times.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type> sqlon::to_expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, 0>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 4 taken 36 times.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type> sqlon::to_expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, 0>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::byte, std::allocator<std::byte> > const&>::type> sqlon::to_expression<std::vector<std::byte, std::allocator<std::byte> > const&, 0>(std::vector<std::byte, std::allocator<std::byte> > const&):
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<unsigned long>::type> sqlon::to_expression<unsigned long, 0>(unsigned long&&):
✓ Branch 4 taken 1 time.
|
262 | node->bound_parameter.emplace(detail::make_parameter_value(std::forward<T>(value))); |
| 356 |
5/6sqlon::expression<sqlon::detail::normalized_type<bool>::type> sqlon::to_expression<bool, 0>(bool&&):
✗ Branch 3 not taken.
sqlon::expression<sqlon::detail::normalized_type<decltype(nullptr)>::type> sqlon::to_expression<decltype(nullptr), 0>(decltype(nullptr)&&):
✓ Branch 3 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<double>::type> sqlon::to_expression<double, 0>(double&&):
✓ Branch 3 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::to_expression<int, 0>(int&&):
✓ Branch 3 taken 117 times.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::byte, std::allocator<std::byte> > const&>::type> sqlon::to_expression<std::vector<std::byte, std::allocator<std::byte> > const&, 0>(std::vector<std::byte, std::allocator<std::byte> > const&):
✓ Branch 3 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<unsigned long>::type> sqlon::to_expression<unsigned long, 0>(unsigned long&&):
✓ Branch 3 taken 1 time.
|
524 | return detail::expression_access::make<value_type>(std::move(node)); |
| 357 | 262 | } | |
| 358 | |||
| 359 | /** @brief Creates an explicit SQL literal expression. */ | ||
| 360 | template<typename T> | ||
| 361 | 43 | expression<detail::normalized_type_t<T>> literal(T&& value) | |
| 362 | { | ||
| 363 | using value_type = detail::normalized_type_t<T>; | ||
| 364 |
12/12sqlon::expression<sqlon::detail::normalized_type<PreparedDate>::type> sqlon::literal<PreparedDate>(PreparedDate&&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<bool>::type> sqlon::literal<bool>(bool&&):
✓ Branch 1 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [9]>::type> sqlon::literal<char const (&) [9]>(char const (&) [9]):
✓ Branch 1 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<decltype(nullptr)>::type> sqlon::literal<decltype(nullptr)>(decltype(nullptr)&&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<double>::type> sqlon::literal<double>(double&&):
✓ Branch 1 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::literal<int>(int&&):
✓ Branch 1 taken 28 times.
sqlon::expression<sqlon::detail::normalized_type<long>::type> sqlon::literal<long>(long&&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type> sqlon::literal<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 1 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type> sqlon::literal<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type> sqlon::literal<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::byte, std::allocator<std::byte> > >::type> sqlon::literal<std::vector<std::byte, std::allocator<std::byte> > >(std::vector<std::byte, std::allocator<std::byte> >&&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<unsigned long>::type> sqlon::literal<unsigned long>(unsigned long&&):
✓ Branch 1 taken 1 time.
|
43 | std::shared_ptr<detail::expression_node> node = std::make_shared<detail::expression_node>(); |
| 365 | 43 | node->kind = detail::expression_kind::literal; | |
| 366 |
16/16sqlon::expression<sqlon::detail::normalized_type<PreparedDate>::type> sqlon::literal<PreparedDate>(PreparedDate&&):
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<bool>::type> sqlon::literal<bool>(bool&&):
✓ Branch 4 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<char const (&) [9]>::type> sqlon::literal<char const (&) [9]>(char const (&) [9]):
✓ Branch 3 taken 2 times.
✓ Branch 6 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<decltype(nullptr)>::type> sqlon::literal<decltype(nullptr)>(decltype(nullptr)&&):
✓ Branch 4 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<double>::type> sqlon::literal<double>(double&&):
✓ Branch 4 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::literal<int>(int&&):
✓ Branch 4 taken 28 times.
sqlon::expression<sqlon::detail::normalized_type<long>::type> sqlon::literal<long>(long&&):
✓ Branch 4 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type> sqlon::literal<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 4 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>::type> sqlon::literal<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>::type> sqlon::literal<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&):
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::byte, std::allocator<std::byte> > >::type> sqlon::literal<std::vector<std::byte, std::allocator<std::byte> > >(std::vector<std::byte, std::allocator<std::byte> >&&):
✓ Branch 4 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<unsigned long>::type> sqlon::literal<unsigned long>(unsigned long&&):
✓ Branch 4 taken 1 time.
|
43 | node->bound_parameter.emplace(detail::make_parameter_value(std::forward<T>(value))); |
| 367 |
6/6sqlon::expression<sqlon::detail::normalized_type<PreparedDate>::type> sqlon::literal<PreparedDate>(PreparedDate&&):
✓ Branch 3 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<decltype(nullptr)>::type> sqlon::literal<decltype(nullptr)>(decltype(nullptr)&&):
✓ Branch 3 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<double>::type> sqlon::literal<double>(double&&):
✓ Branch 3 taken 2 times.
sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::literal<int>(int&&):
✓ Branch 3 taken 28 times.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::byte, std::allocator<std::byte> > >::type> sqlon::literal<std::vector<std::byte, std::allocator<std::byte> > >(std::vector<std::byte, std::allocator<std::byte> >&&):
✓ Branch 3 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<unsigned long>::type> sqlon::literal<unsigned long>(unsigned long&&):
✓ Branch 3 taken 1 time.
|
86 | return detail::expression_access::make<value_type>(std::move(node)); |
| 368 | 43 | } | |
| 369 | |||
| 370 | /** @brief Creates a bound parameter with a logical name. */ | ||
| 371 | template<typename T> | ||
| 372 | 19 | expression<detail::normalized_type_t<T>> param(std::string name, T&& value) | |
| 373 | { | ||
| 374 |
7/15sqlon::expression<sqlon::detail::normalized_type<ClientUuid const&>::type> sqlon::param<ClientUuid const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ClientUuid const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 5 not taken.
sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::param<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int&&):
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 5 times.
✓ Branch 5 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<long>::type> sqlon::param<long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long&&):
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 5 not taken.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type> sqlon::param<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&>::type> sqlon::param<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
|
19 | if (name.empty()) throw invalid_query{"a named parameter requires a non-empty name"}; |
| 375 | using value_type = detail::normalized_type_t<T>; | ||
| 376 |
5/5sqlon::expression<sqlon::detail::normalized_type<ClientUuid const&>::type> sqlon::param<ClientUuid const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ClientUuid const&):
✓ Branch 1 taken 3 times.
sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::param<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int&&):
✓ Branch 1 taken 5 times.
sqlon::expression<sqlon::detail::normalized_type<long>::type> sqlon::param<long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long&&):
✓ Branch 1 taken 8 times.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type> sqlon::param<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 1 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&>::type> sqlon::param<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&):
✓ Branch 1 taken 1 time.
|
18 | std::shared_ptr<detail::expression_node> node = std::make_shared<detail::expression_node>(); |
| 377 | 18 | node->kind = detail::expression_kind::parameter; | |
| 378 | 18 | node->text = std::move(name); | |
| 379 |
7/7sqlon::expression<sqlon::detail::normalized_type<ClientUuid const&>::type> sqlon::param<ClientUuid const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, ClientUuid const&):
✓ Branch 3 taken 3 times.
✓ Branch 6 taken 3 times.
sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::param<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int&&):
✓ Branch 4 taken 5 times.
sqlon::expression<sqlon::detail::normalized_type<long>::type> sqlon::param<long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, long&&):
✓ Branch 4 taken 8 times.
sqlon::expression<sqlon::detail::normalized_type<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::type> sqlon::param<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 4 taken 1 time.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&>::type> sqlon::param<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&):
✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
|
18 | node->bound_parameter.emplace(detail::make_parameter_value(std::forward<T>(value))); |
| 380 |
2/2sqlon::expression<sqlon::detail::normalized_type<int>::type> sqlon::param<int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int&&):
✓ Branch 3 taken 5 times.
sqlon::expression<sqlon::detail::normalized_type<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&>::type> sqlon::param<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&):
✓ Branch 3 taken 1 time.
|
36 | return detail::expression_access::make<value_type>(std::move(node)); |
| 381 | 18 | } | |
| 382 | |||
| 383 | /** @brief Typed assignment produced when binding a prepared parameter handle. */ | ||
| 384 | template<typename T> | ||
| 385 | struct parameter_binding final { | ||
| 386 | /** @brief Stable identity of the parameter handle. */ | ||
| 387 | std::size_t identity{}; | ||
| 388 | |||
| 389 | /** @brief Logical parameter name. */ | ||
| 390 | std::string name; | ||
| 391 | |||
| 392 | /** @brief Bound parameter value. */ | ||
| 393 | parameter_value value; | ||
| 394 | }; | ||
| 395 | |||
| 396 | namespace detail { | ||
| 397 | |||
| 398 | template<typename T> | ||
| 399 | struct is_parameter_binding<parameter_binding<T>> : std::true_type {}; | ||
| 400 | |||
| 401 | } // namespace detail | ||
| 402 | |||
| 403 | /** @brief Typed named slot whose value is supplied after preparation. */ | ||
| 404 | template<typename T> | ||
| 405 | class parameter_slot final : public expression<detail::parameter_expression_type_t<T>> { | ||
| 406 | public: | ||
| 407 | /** @brief Creates a prepared parameter slot with a logical name. */ | ||
| 408 | 31 | explicit parameter_slot(std::string name) | |
| 409 | : expression<detail::parameter_expression_type_t<T>>(make_node(name)) | ||
| 410 | 30 | , m_identity(detail::expression_access::node(*this)->parameter_slot->identity) | |
| 411 |
7/7sqlon::parameter_slot<PreparedUuid>::parameter_slot(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✓ Branch 1 taken 2 times.
sqlon::parameter_slot<bool>::parameter_slot(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✓ Branch 1 taken 4 times.
sqlon::parameter_slot<long>::parameter_slot(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✓ Branch 1 taken 12 times.
sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::parameter_slot(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✓ Branch 1 taken 8 times.
sqlon::parameter_slot<std::optional<PreparedUuid> >::parameter_slot(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✓ Branch 1 taken 1 time.
sqlon::parameter_slot<std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::parameter_slot(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✓ Branch 1 taken 2 times.
sqlon::parameter_slot<unsigned long>::parameter_slot(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✓ Branch 1 taken 1 time.
|
61 | , m_name(std::move(name)) |
| 412 | 30 | {} | |
| 413 | |||
| 414 | /** @brief Creates a typed binding for this slot. */ | ||
| 415 | 29 | parameter_binding<T> operator=(T value) const | |
| 416 | { | ||
| 417 | 29 | return {m_identity, m_name, parameter_value{detail::make_parameter_value(std::move(value))}}; | |
| 418 | 29 | } | |
| 419 | |||
| 420 | /** @brief Returns the stable parameter identity. */ | ||
| 421 | 4 | std::size_t identity() const noexcept | |
| 422 | { | ||
| 423 | 4 | return m_identity; | |
| 424 | } | ||
| 425 | |||
| 426 | /** @brief Returns the logical parameter name. */ | ||
| 427 | 3 | const std::string& name() const noexcept | |
| 428 | { | ||
| 429 | 3 | return m_name; | |
| 430 | } | ||
| 431 | |||
| 432 | private: | ||
| 433 | 31 | static detail::expression_ptr make_node(const std::string& name) | |
| 434 | { | ||
| 435 |
9/21sqlon::parameter_slot<PreparedUuid>::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 5 not taken.
sqlon::parameter_slot<bool>::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 5 not taken.
sqlon::parameter_slot<long>::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 12 times.
✓ Branch 5 taken 1 time.
sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 5 not taken.
sqlon::parameter_slot<std::optional<PreparedUuid> >::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
sqlon::parameter_slot<std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 5 not taken.
sqlon::parameter_slot<unsigned long>::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
|
31 | if (name.empty()) throw invalid_query{"a prepared parameter requires a non-empty name"}; |
| 436 |
7/7sqlon::parameter_slot<PreparedUuid>::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 2 times.
sqlon::parameter_slot<bool>::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 4 times.
sqlon::parameter_slot<long>::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 12 times.
sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 8 times.
sqlon::parameter_slot<std::optional<PreparedUuid> >::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 1 time.
sqlon::parameter_slot<std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 2 times.
sqlon::parameter_slot<unsigned long>::make_node(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 1 time.
|
30 | std::shared_ptr<detail::expression_node> node = std::make_shared<detail::expression_node>(); |
| 437 | 30 | node->kind = detail::expression_kind::parameter_slot; | |
| 438 | 30 | node->parameter_slot = | |
| 439 | 60 | detail::parameter_slot_node{detail::next_parameter_identity(), name, detail::parameter_kind_of<T>(), | |
| 440 | 30 | detail::is_nullable_parameter_v<T>, detail::custom_parameter_type_id<T>()}; | |
| 441 | 60 | return node; | |
| 442 | 60 | } | |
| 443 | |||
| 444 | std::size_t m_identity{}; | ||
| 445 | std::string m_name; | ||
| 446 | }; | ||
| 447 | |||
| 448 | template<typename T> | ||
| 449 | template<typename Right> | ||
| 450 | 66 | expression<bool> expression<T>::operator==(Right&& right) const | |
| 451 | { | ||
| 452 |
6/6sqlon::expression<bool> sqlon::expression<ClientUuid>::operator==<ClientUuid const&>(ClientUuid const&) const:
✓ Branch 2 taken 1 time.
sqlon::expression<bool> sqlon::expression<bool>::operator==<bool>(bool&&) const:
✓ Branch 2 taken 15 times.
sqlon::expression<bool> sqlon::expression<long>::operator==<ClientId>(ClientId&&) const:
✓ Branch 2 taken 1 time.
sqlon::expression<bool> sqlon::expression<long>::operator==<int>(int&&) const:
✓ Branch 2 taken 14 times.
sqlon::expression<bool> sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::operator==<char const (&) [4]>(char const (&) [4]) const:
✓ Branch 2 taken 4 times.
sqlon::expression<bool> sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::operator==<char const (&) [6]>(char const (&) [6]) const:
✓ Branch 2 taken 4 times.
|
66 | auto rhs = to_expression(std::forward<Right>(right)); |
| 453 | static_assert(detail::compatible_expression_types<T, typename decltype(rhs)::value_type>, | ||
| 454 | "incompatible SQL comparison types"); | ||
| 455 |
18/18sqlon::expression<bool> sqlon::expression<ClientUuid>::operator==<ClientUuid const&>(ClientUuid const&) const:
✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
sqlon::expression<bool> sqlon::expression<bool>::operator==<bool>(bool&&) const:
✓ Branch 4 taken 15 times.
✓ Branch 7 taken 15 times.
sqlon::expression<bool> sqlon::expression<long>::operator==<ClientId>(ClientId&&) const:
✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
sqlon::expression<bool> sqlon::expression<long>::operator==<int>(int&&) const:
✓ Branch 4 taken 14 times.
✓ Branch 7 taken 14 times.
sqlon::expression<bool> sqlon::expression<long>::operator==<sqlon::column<long> const&>(sqlon::column<long> const&) const:
✓ Branch 4 taken 18 times.
✓ Branch 7 taken 18 times.
sqlon::expression<bool> sqlon::expression<long>::operator==<sqlon::expression<long> const&>(sqlon::expression<long> const&) const:
✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
sqlon::expression<bool> sqlon::expression<long>::operator==<sqlon::parameter_slot<long> const&>(sqlon::parameter_slot<long> const&) const:
✓ Branch 4 taken 8 times.
✓ Branch 7 taken 8 times.
sqlon::expression<bool> sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::operator==<char const (&) [4]>(char const (&) [4]) const:
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 4 times.
sqlon::expression<bool> sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::operator==<char const (&) [6]>(char const (&) [6]) const:
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 4 times.
|
264 | return expression<bool>{detail::make_binary_node("=", m_node, detail::expression_access::node(rhs))}; |
| 456 | 66 | } | |
| 457 | |||
| 458 | template<typename T> | ||
| 459 | template<typename Right> | ||
| 460 | 1 | expression<bool> expression<T>::operator!=(Right&& right) const | |
| 461 | { | ||
| 462 | 1 | auto rhs = to_expression(std::forward<Right>(right)); | |
| 463 | static_assert(detail::compatible_expression_types<T, typename decltype(rhs)::value_type>, | ||
| 464 | "incompatible SQL comparison types"); | ||
| 465 |
2/2✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
|
4 | return expression<bool>{detail::make_binary_node("!=", m_node, detail::expression_access::node(rhs))}; |
| 466 | 1 | } | |
| 467 | |||
| 468 | #define SQLON_DEFINE_COMPARISON_OPERATOR(symbol, operation) \ | ||
| 469 | template<typename T> \ | ||
| 470 | template<typename Right> \ | ||
| 471 | expression<bool> expression<T>::operator symbol(Right && right) const \ | ||
| 472 | { \ | ||
| 473 | auto rhs = to_expression(std::forward<Right>(right)); \ | ||
| 474 | static_assert(detail::compatible_expression_types<T, typename decltype(rhs)::value_type>, \ | ||
| 475 | "incompatible SQL comparison types"); \ | ||
| 476 | return expression<bool>{detail::make_binary_node(operation, m_node, detail::expression_access::node(rhs))}; \ | ||
| 477 | } | ||
| 478 | |||
| 479 |
5/5sqlon::expression<bool> sqlon::expression<long>::operator< <int>(int&&) const:
✓ Branch 2 taken 1 time.
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
sqlon::expression<bool> sqlon::expression<long>::operator< <sqlon::column<long> const&>(sqlon::column<long> const&) const:
✓ Branch 6 taken 1 time.
✓ Branch 9 taken 1 time.
|
8 | SQLON_DEFINE_COMPARISON_OPERATOR(<, "<") |
| 480 |
2/2✓ Branch 6 taken 1 time.
✓ Branch 9 taken 1 time.
|
4 | SQLON_DEFINE_COMPARISON_OPERATOR(<=, "<=") |
| 481 |
8/8sqlon::expression<bool> sqlon::expression<long>::operator><int>(int&&) const:
✓ Branch 2 taken 13 times.
✓ Branch 8 taken 13 times.
✓ Branch 11 taken 13 times.
sqlon::expression<bool> sqlon::expression<long>::operator><long>(long&&) const:
✓ Branch 2 taken 1 time.
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
sqlon::expression<bool> sqlon::expression<long>::operator><sqlon::column<long> const&>(sqlon::column<long> const&) const:
✓ Branch 6 taken 1 time.
✓ Branch 9 taken 1 time.
|
60 | SQLON_DEFINE_COMPARISON_OPERATOR(>, ">") |
| 482 |
5/5sqlon::expression<bool> sqlon::expression<long>::operator>=<int>(int&&) const:
✓ Branch 2 taken 1 time.
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
sqlon::expression<bool> sqlon::expression<long>::operator>=<sqlon::column<long> const&>(sqlon::column<long> const&) const:
✓ Branch 6 taken 1 time.
✓ Branch 9 taken 1 time.
|
8 | SQLON_DEFINE_COMPARISON_OPERATOR(>=, ">=") |
| 483 | |||
| 484 | #undef SQLON_DEFINE_COMPARISON_OPERATOR | ||
| 485 | |||
| 486 | #define SQLON_DEFINE_ARITHMETIC_OPERATOR(symbol, operation) \ | ||
| 487 | template<typename T> \ | ||
| 488 | template<typename Right, typename U, std::enable_if_t<std::is_arithmetic_v<U>, int>> \ | ||
| 489 | expression<std::common_type_t<T, detail::expression_value_type_t<Right>>> expression<T>::operator symbol( \ | ||
| 490 | Right && right) const \ | ||
| 491 | { \ | ||
| 492 | auto rhs = to_expression(std::forward<Right>(right)); \ | ||
| 493 | static_assert(!std::is_same_v<detail::normalized_type_t<T>, bool> && \ | ||
| 494 | !std::is_same_v<typename decltype(rhs)::value_type, bool>, \ | ||
| 495 | "SQL arithmetic does not accept boolean expressions"); \ | ||
| 496 | using result_type = std::common_type_t<T, typename decltype(rhs)::value_type>; \ | ||
| 497 | return expression<result_type>{detail::make_binary_node(operation, m_node, detail::expression_access::node(rhs))}; \ | ||
| 498 | } | ||
| 499 | |||
| 500 |
7/7sqlon::expression<std::common_type<long, sqlon::detail::expression_value_type<int, sqlon::detail::is_expression_like<int, void>::value>::type>::type> sqlon::expression<long>::operator+<int, long, 0>(int&&) const:
✓ Branch 2 taken 3 times.
✓ Branch 8 taken 3 times.
✓ Branch 11 taken 3 times.
sqlon::expression<std::common_type<long, sqlon::detail::expression_value_type<sqlon::expression<int>, sqlon::detail::is_expression_like<sqlon::expression<int>, void>::value>::type>::type> sqlon::expression<long>::operator+<sqlon::expression<int>, long, 0>(sqlon::expression<int>&&) const:
✓ Branch 6 taken 1 time.
✓ Branch 9 taken 1 time.
sqlon::expression<std::common_type<long, sqlon::detail::expression_value_type<sqlon::parameter_slot<long> const&, sqlon::detail::is_expression_like<sqlon::parameter_slot<long> const&, void>::value>::type>::type> sqlon::expression<long>::operator+<sqlon::parameter_slot<long> const&, long, 0>(sqlon::parameter_slot<long> const&) const:
✓ Branch 6 taken 1 time.
✓ Branch 9 taken 1 time.
|
20 | SQLON_DEFINE_ARITHMETIC_OPERATOR(+, "+") |
| 501 |
3/3✓ Branch 2 taken 1 time.
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
|
4 | SQLON_DEFINE_ARITHMETIC_OPERATOR(-, "-") |
| 502 |
6/6sqlon::expression<std::common_type<long, sqlon::detail::expression_value_type<int, sqlon::detail::is_expression_like<int, void>::value>::type>::type> sqlon::expression<long>::operator*<int, long, 0>(int&&) const:
✓ Branch 2 taken 2 times.
✓ Branch 8 taken 2 times.
✓ Branch 11 taken 2 times.
sqlon::expression<std::common_type<long, sqlon::detail::expression_value_type<long, sqlon::detail::is_expression_like<long, void>::value>::type>::type> sqlon::expression<long>::operator*<long, long, 0>(long&&) const:
✓ Branch 2 taken 1 time.
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
|
12 | SQLON_DEFINE_ARITHMETIC_OPERATOR(*, "*") |
| 503 |
3/3✓ Branch 2 taken 1 time.
✓ Branch 8 taken 1 time.
✓ Branch 11 taken 1 time.
|
4 | SQLON_DEFINE_ARITHMETIC_OPERATOR(/, "/") |
| 504 | |||
| 505 | #undef SQLON_DEFINE_ARITHMETIC_OPERATOR | ||
| 506 | |||
| 507 | template<typename T> | ||
| 508 | template<typename... Values, std::enable_if_t<detail::are_non_query_values<Values...>::value, int>> | ||
| 509 | 2 | expression<bool> expression<T>::in(Values&&... values) const | |
| 510 | { | ||
| 511 | static_assert(sizeof...(Values) > 0, "IN requires at least one value"); | ||
| 512 | static_assert( | ||
| 513 | (detail::compatible_expression_types<T, typename decltype(to_expression(std::declval<Values>()))::value_type> && | ||
| 514 | ...), | ||
| 515 | "IN values must be compatible with the tested expression"); | ||
| 516 |
3/5✓ Branch 1 taken 2 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
6 | std::vector<detail::expression_ptr> operands{m_node}; |
| 517 |
6/6✓ Branch 2 taken 2 times.
✓ Branch 6 taken 2 times.
✓ Branch 10 taken 2 times.
✓ Branch 14 taken 2 times.
✓ Branch 18 taken 2 times.
✓ Branch 22 taken 2 times.
|
2 | (operands.push_back(detail::expression_access::node(to_expression(std::forward<Values>(values)))), ...); |
| 518 |
2/2✓ Branch 3 taken 2 times.
✓ Branch 6 taken 2 times.
|
8 | return expression<bool>{detail::make_expression_node(detail::expression_kind::function, "in", std::move(operands))}; |
| 519 | 4 | } | |
| 520 | |||
| 521 | template<typename T> | ||
| 522 | template<typename... Values, std::enable_if_t<detail::are_non_query_values<Values...>::value, int>> | ||
| 523 | 1 | expression<bool> expression<T>::not_in(Values&&... values) const | |
| 524 | { | ||
| 525 | static_assert(sizeof...(Values) > 0, "NOT IN requires at least one value"); | ||
| 526 | static_assert( | ||
| 527 | (detail::compatible_expression_types<T, typename decltype(to_expression(std::declval<Values>()))::value_type> && | ||
| 528 | ...), | ||
| 529 | "NOT IN values must be compatible with the tested expression"); | ||
| 530 |
3/5✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
3 | std::vector<detail::expression_ptr> operands{m_node}; |
| 531 |
6/6✓ Branch 2 taken 1 time.
✓ Branch 6 taken 1 time.
✓ Branch 10 taken 1 time.
✓ Branch 14 taken 1 time.
✓ Branch 18 taken 1 time.
✓ Branch 22 taken 1 time.
|
1 | (operands.push_back(detail::expression_access::node(to_expression(std::forward<Values>(values)))), ...); |
| 532 | return expression<bool>{ | ||
| 533 |
2/2✓ Branch 3 taken 1 time.
✓ Branch 6 taken 1 time.
|
4 | detail::make_expression_node(detail::expression_kind::function, "not_in", std::move(operands))}; |
| 534 | 2 | } | |
| 535 | |||
| 536 | template<typename T> | ||
| 537 | template<typename Lower, typename Upper> | ||
| 538 | 2 | expression<bool> expression<T>::between(Lower&& lower, Upper&& upper) const | |
| 539 | { | ||
| 540 |
1/1✓ Branch 2 taken 2 times.
|
2 | auto lower_expression = to_expression(std::forward<Lower>(lower)); |
| 541 |
1/1✓ Branch 2 taken 2 times.
|
2 | auto upper_expression = to_expression(std::forward<Upper>(upper)); |
| 542 | static_assert(detail::compatible_expression_types<T, typename decltype(lower_expression)::value_type> && | ||
| 543 | detail::compatible_expression_types<T, typename decltype(upper_expression)::value_type>, | ||
| 544 | "BETWEEN bounds must be compatible with the tested expression"); | ||
| 545 | 6 | return expression<bool>{detail::make_expression_node( | |
| 546 | detail::expression_kind::function, "between", | ||
| 547 |
5/7✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 13 taken 6 times.
✓ Branch 14 taken 2 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
16 | {m_node, detail::expression_access::node(lower_expression), detail::expression_access::node(upper_expression)})}; |
| 548 | 4 | } | |
| 549 | |||
| 550 | template<typename T> | ||
| 551 | template<typename Pattern> | ||
| 552 | 1 | expression<bool> expression<T>::like(Pattern&& pattern) const | |
| 553 | { | ||
| 554 | static_assert(std::is_same_v<T, std::string>, "LIKE requires a string expression"); | ||
| 555 |
1/1✓ Branch 2 taken 1 time.
|
1 | auto rhs = to_expression(std::forward<Pattern>(pattern)); |
| 556 | static_assert(std::is_same_v<typename decltype(rhs)::value_type, std::string>, | ||
| 557 | "LIKE patterns must be string expressions"); | ||
| 558 |
2/2✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
|
4 | return expression<bool>{detail::make_binary_node("like", m_node, detail::expression_access::node(rhs))}; |
| 559 | 1 | } | |
| 560 | |||
| 561 | template<typename T> | ||
| 562 | template<typename Pattern> | ||
| 563 | 1 | expression<bool> expression<T>::not_like(Pattern&& pattern) const | |
| 564 | { | ||
| 565 | static_assert(std::is_same_v<T, std::string>, "NOT LIKE requires a string expression"); | ||
| 566 |
1/1✓ Branch 2 taken 1 time.
|
1 | auto rhs = to_expression(std::forward<Pattern>(pattern)); |
| 567 | static_assert(std::is_same_v<typename decltype(rhs)::value_type, std::string>, | ||
| 568 | "NOT LIKE patterns must be string expressions"); | ||
| 569 |
2/2✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
|
4 | return expression<bool>{detail::make_binary_node("not_like", m_node, detail::expression_access::node(rhs))}; |
| 570 | 1 | } | |
| 571 | |||
| 572 | /** @brief Creates a logical AND expression. */ | ||
| 573 | SQLON_API expression<bool> operator&&(const expression<bool>& left, const expression<bool>& right); | ||
| 574 | |||
| 575 | /** @brief Creates a logical OR expression. */ | ||
| 576 | SQLON_API expression<bool> operator||(const expression<bool>& left, const expression<bool>& right); | ||
| 577 | |||
| 578 | /** @brief Creates a logical NOT expression. */ | ||
| 579 | SQLON_API expression<bool> operator!(const expression<bool>& value); | ||
| 580 | |||
| 581 | /** @brief Creates an IS NULL predicate. */ | ||
| 582 | template<typename T> | ||
| 583 | expression<bool> operator==(std::nullptr_t, const expression<T>& value) | ||
| 584 | { | ||
| 585 | return value.is_null(); | ||
| 586 | } | ||
| 587 | |||
| 588 | /** @brief Creates an IS NOT NULL predicate. */ | ||
| 589 | template<typename T> | ||
| 590 | expression<bool> operator!=(std::nullptr_t, const expression<T>& value) | ||
| 591 | { | ||
| 592 | return value.is_not_null(); | ||
| 593 | } | ||
| 594 | |||
| 595 | /** @brief Creates a COUNT aggregate for an expression. */ | ||
| 596 | template<typename T> | ||
| 597 | 6 | expression<std::int64_t> count(const expression<T>& value) | |
| 598 | { | ||
| 599 | 6 | return detail::expression_access::make<std::int64_t>(detail::make_expression_node( | |
| 600 |
5/7✓ Branch 1 taken 6 times.
✓ Branch 4 taken 6 times.
✓ Branch 7 taken 6 times.
✓ Branch 13 taken 6 times.
✓ Branch 14 taken 6 times.
✗ Branch 17 not taken.
✗ Branch 18 not taken.
|
30 | detail::expression_kind::function, "count", {detail::expression_access::node(value)})); |
| 601 | 6 | } | |
| 602 | |||
| 603 | /** @brief Creates a COUNT(*) aggregate. */ | ||
| 604 | SQLON_API expression<std::int64_t> count_all(); | ||
| 605 | |||
| 606 | /** @brief Wraps an expression in DISTINCT. */ | ||
| 607 | template<typename T> | ||
| 608 | 2 | expression<T> distinct(const expression<T>& value) | |
| 609 | { | ||
| 610 | return detail::expression_access::make<T>( | ||
| 611 |
4/6✓ Branch 1 taken 2 times.
✓ Branch 5 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 12 taken 2 times.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
|
6 | detail::make_expression_node(detail::expression_kind::distinct, {}, {detail::expression_access::node(value)})); |
| 612 | 2 | } | |
| 613 | |||
| 614 | /** @brief Creates a COUNT aggregate over distinct values. */ | ||
| 615 | template<typename T> | ||
| 616 | 2 | expression<std::int64_t> count_distinct(const expression<T>& value) | |
| 617 | { | ||
| 618 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
|
2 | return count(distinct(value)); |
| 619 | } | ||
| 620 | |||
| 621 | /** @brief Creates a MIN aggregate. */ | ||
| 622 | template<typename T> | ||
| 623 | 1 | expression<T> min(const expression<T>& value) | |
| 624 | { | ||
| 625 | return detail::expression_access::make<T>( | ||
| 626 |
5/7✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
✓ Branch 13 taken 1 time.
✓ Branch 14 taken 1 time.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
5 | detail::make_expression_node(detail::expression_kind::function, "min", {detail::expression_access::node(value)})); |
| 627 | 1 | } | |
| 628 | |||
| 629 | /** @brief Creates a MAX aggregate. */ | ||
| 630 | template<typename T> | ||
| 631 | 2 | expression<T> max(const expression<T>& value) | |
| 632 | { | ||
| 633 | return detail::expression_access::make<T>( | ||
| 634 |
5/7✓ Branch 1 taken 2 times.
✓ Branch 4 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 2 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
10 | detail::make_expression_node(detail::expression_kind::function, "max", {detail::expression_access::node(value)})); |
| 635 | 2 | } | |
| 636 | |||
| 637 | /** @brief Creates a SUM aggregate for a numeric expression. */ | ||
| 638 | template<typename T> | ||
| 639 | 4 | expression<T> sum(const expression<T>& value) | |
| 640 | { | ||
| 641 | static_assert(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>, "sum requires a numeric expression"); | ||
| 642 | return detail::expression_access::make<T>( | ||
| 643 |
5/7✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 4 times.
✓ Branch 13 taken 4 times.
✓ Branch 14 taken 4 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
|
20 | detail::make_expression_node(detail::expression_kind::function, "sum", {detail::expression_access::node(value)})); |
| 644 | 4 | } | |
| 645 | |||
| 646 | /** @brief Creates an AVG aggregate for a numeric expression. */ | ||
| 647 | template<typename T> | ||
| 648 | 1 | expression<double> avg(const expression<T>& value) | |
| 649 | { | ||
| 650 | static_assert(std::is_arithmetic_v<T> && !std::is_same_v<T, bool>, "avg requires a numeric expression"); | ||
| 651 | return detail::expression_access::make<double>( | ||
| 652 |
6/8✓ Branch 1 taken 1 time.
✓ Branch 4 taken 1 time.
✓ Branch 7 taken 1 time.
✓ Branch 10 taken 1 time.
✓ Branch 15 taken 1 time.
✓ Branch 16 taken 1 time.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
5 | detail::make_expression_node(detail::expression_kind::function, "avg", {detail::expression_access::node(value)})); |
| 653 | 1 | } | |
| 654 | |||
| 655 | /** @brief Tag type for SQL timestamp expressions. */ | ||
| 656 | struct timestamp final {}; | ||
| 657 | |||
| 658 | /** @brief Creates the CURRENT_TIMESTAMP expression. */ | ||
| 659 | SQLON_API expression<timestamp> current_timestamp(); | ||
| 660 | |||
| 661 | /** @brief Creates an explicit SQL NULL expression. */ | ||
| 662 | SQLON_API expression<std::nullptr_t> null(); | ||
| 663 | |||
| 664 | /** @brief Creates a DEFAULT value expression. */ | ||
| 665 | SQLON_API expression<std::nullptr_t> default_value(); | ||
| 666 | |||
| 667 | /** @brief Creates a typed SQL function call. */ | ||
| 668 | template<typename T, typename... Arguments> | ||
| 669 | 17 | expression<T> function(std::string name, Arguments&&... arguments) | |
| 670 | { | ||
| 671 |
8/18sqlon::expression<long> sqlon::function<long, sqlon::column<long> const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<long> const&):
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 6 taken 1 time.
sqlon::expression<long> sqlon::function<long, sqlon::expression<long> const&, int, int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<long> const&, int&&, int&&):
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 6 not taken.
sqlon::expression<long> sqlon::function<long, sqlon::expression<long> const&, sqlon::parameter_slot<unsigned long> const&, sqlon::parameter_slot<long> const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<long> const&, sqlon::parameter_slot<unsigned long> const&, sqlon::parameter_slot<long> const&):
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 6 not taken.
sqlon::expression<long> sqlon::function<long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 6 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::function<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, char const (&) [8]>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, char const (&) [8]):
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 6 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::function<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
✗ Branch 6 not taken.
|
17 | if (!detail::valid_function_name(name)) throw invalid_query{"a SQL function requires an identifier-like name"}; |
| 672 | 12 | return detail::expression_access::make<T>(detail::make_expression_node( | |
| 673 | 16 | detail::expression_kind::function_call, std::move(name), | |
| 674 |
25/35sqlon::expression<long> sqlon::function<long, sqlon::column<long> const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<long> const&):
✓ Branch 3 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 13 taken 2 times.
✓ Branch 14 taken 2 times.
✗ Branch 18 not taken.
✗ Branch 19 not taken.
sqlon::expression<long> sqlon::function<long, sqlon::expression<long> const&, int, int>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<long> const&, int&&, int&&):
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✓ Branch 11 taken 1 time.
✓ Branch 15 taken 1 time.
✓ Branch 21 taken 3 times.
✓ Branch 22 taken 1 time.
✗ Branch 28 not taken.
✗ Branch 29 not taken.
sqlon::expression<long> sqlon::function<long, sqlon::expression<long> const&, sqlon::parameter_slot<unsigned long> const&, sqlon::parameter_slot<long> const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<long> const&, sqlon::parameter_slot<unsigned long> const&, sqlon::parameter_slot<long> const&):
✓ Branch 7 taken 1 time.
✓ Branch 11 taken 1 time.
✓ Branch 17 taken 3 times.
✓ Branch 18 taken 1 time.
✗ Branch 24 not taken.
✗ Branch 25 not taken.
sqlon::expression<long> sqlon::function<long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✓ Branch 3 taken 10 times.
✓ Branch 6 taken 10 times.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::function<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, char const (&) [8]>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, char const (&) [8]):
✓ Branch 3 taken 1 time.
✓ Branch 7 taken 1 time.
✓ Branch 11 taken 1 time.
✓ Branch 17 taken 2 times.
✓ Branch 18 taken 1 time.
✗ Branch 23 not taken.
✗ Branch 24 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::function<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 5 taken 1 time.
✓ Branch 9 taken 1 time.
✓ Branch 15 taken 2 times.
✓ Branch 16 taken 1 time.
✗ Branch 21 not taken.
✗ Branch 22 not taken.
|
62 | {detail::expression_access::node(to_expression(std::forward<Arguments>(arguments)))...})); |
| 675 | 18 | } | |
| 676 | |||
| 677 | /** @brief Creates a COALESCE expression from compatible arguments. */ | ||
| 678 | template<typename First, typename... Rest> | ||
| 679 | 2 | auto coalesce(First&& first, Rest&&... rest) | |
| 680 | { | ||
| 681 | static_assert(sizeof...(Rest) > 0, "COALESCE requires at least two arguments"); | ||
| 682 | 2 | auto first_expression = to_expression(std::forward<First>(first)); | |
| 683 | using value_type = typename decltype(first_expression)::value_type; | ||
| 684 | static_assert((detail::compatible_expression_types<value_type, detail::expression_value_type_t<Rest>> && ...), | ||
| 685 | "COALESCE arguments must have compatible expression types"); | ||
| 686 |
4/4auto sqlon::coalesce<sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, char const (&) [8]>(sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, char const (&) [8]):
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
auto sqlon::coalesce<sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
|
6 | return function<value_type>("coalesce", first_expression, std::forward<Rest>(rest)...); |
| 687 | 2 | } | |
| 688 | |||
| 689 | /** | ||
| 690 | * @brief Creates a grouped raw SQL expression whose operands retain normal SQLon rendering and parameter handling. | ||
| 691 | * | ||
| 692 | * The SQL template is trusted syntax and is not escaped, validated for a database preset, or translated between | ||
| 693 | * dialects. Each `{}` position is replaced by the next operand after that operand passes through `to_expression()`. | ||
| 694 | * Do not put user-controlled text or database placeholders directly in the template. | ||
| 695 | */ | ||
| 696 | template<typename Result, typename... Operands> | ||
| 697 | 23 | expression<Result> raw_expr(std::string sql, Operands&&... operands) | |
| 698 | { | ||
| 699 |
36/60sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<bool> const&, bool>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<bool> const&, bool&&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<bool> const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<bool> const&):
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 5 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 4 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<long> sqlon::raw_expr<long, sqlon::column<long> const&, long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<long> const&, long&&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<long> sqlon::raw_expr<long, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, long&&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
76 | std::vector<detail::expression_ptr> nodes{ |
| 700 |
6/6sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<bool> const&, bool>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<bool> const&, bool&&):
✓ Branch 3 taken 1 time.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 3 taken 4 times.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 3 taken 1 time.
sqlon::expression<long> sqlon::raw_expr<long, sqlon::column<long> const&, long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<long> const&, long&&):
✓ Branch 3 taken 1 time.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, long&&):
✓ Branch 3 taken 1 time.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 1 taken 1 time.
|
53 | detail::expression_access::node(to_expression(std::forward<Operands>(operands)))...}; |
| 701 |
14/20sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<bool> const&, bool>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<bool> const&, bool&&):
✗ Branch 5 not taken.
✗ Branch 8 not taken.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<bool> const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<bool> const&):
✗ Branch 5 not taken.
✗ Branch 8 not taken.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 5 taken 1 time.
✓ Branch 8 taken 1 time.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::parameter_slot<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 5 taken 1 time.
✓ Branch 8 taken 1 time.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 5 taken 4 times.
✓ Branch 8 taken 4 times.
sqlon::expression<bool> sqlon::raw_expr<bool, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&):
✓ Branch 5 taken 1 time.
✓ Branch 8 taken 1 time.
sqlon::expression<bool> sqlon::raw_expr<bool>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >):
✗ Branch 5 not taken.
✗ Branch 8 not taken.
sqlon::expression<long> sqlon::raw_expr<long, sqlon::column<long> const&, long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<long> const&, long&&):
✓ Branch 5 taken 1 time.
sqlon::expression<long> sqlon::raw_expr<long, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 5 taken 1 time.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, sqlon::expression<std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&):
✓ Branch 5 taken 1 time.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::column<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&):
✓ Branch 5 taken 1 time.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, long>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > const&, long&&):
✓ Branch 5 taken 1 time.
sqlon::expression<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > sqlon::raw_expr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&):
✓ Branch 5 taken 1 time.
|
56 | return detail::expression_access::make<Result>(detail::make_raw_expression_node(std::move(sql), std::move(nodes))); |
| 702 | 76 | } | |
| 703 | |||
| 704 | /** | ||
| 705 | * @brief Creates an opaque raw SQL expression from trusted syntax. | ||
| 706 | * | ||
| 707 | * The SQL text is emitted unchanged and receives no escaping or parameterization. Runtime values and SQLon | ||
| 708 | * expressions must be passed through `raw_expr()` operands instead. Database placeholders written here are not | ||
| 709 | * tracked by SQLon. | ||
| 710 | */ | ||
| 711 | template<typename T> | ||
| 712 | 2 | expression<T> raw_sql(std::string sql) | |
| 713 | { | ||
| 714 |
3/3✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
|
2 | if (sql.empty()) throw invalid_query{"a raw SQL expression cannot be empty"}; |
| 715 |
1/1✓ Branch 4 taken 1 time.
|
1 | return detail::expression_access::make<T>(detail::make_expression_node(detail::expression_kind::raw, std::move(sql))); |
| 716 | } | ||
| 717 | |||
| 718 | } // namespace sqlon | ||
| 719 | |||
| 720 | #endif // SQLON_EXPRESSION_H | ||
| 721 |