IronQuery
A SQL-first query builder for C++
Loading...
Searching...
No Matches
expr.hpp
1#pragma once
2
3#include <initializer_list>
4#include <iron_query/operator_precedence.hpp>
5#include <memory>
6#include <string>
7#include <string_view>
8#include <type_traits>
9
10namespace iron_query {
11
12class VirtualTable;
13class Condition;
14class Collation;
15class SelectItem;
16
17namespace impl {
18struct Node;
19} // namespace impl
20
21namespace impl {
22
27template <typename T>
28inline constexpr bool kIsSqlInteger =
29 std::is_integral_v<T> && !std::is_same_v<std::remove_cv_t<T>, bool> &&
30 !std::is_same_v<std::remove_cv_t<T>, char> &&
31 !std::is_same_v<std::remove_cv_t<T>, signed char> &&
32 !std::is_same_v<std::remove_cv_t<T>, unsigned char> &&
33 !std::is_same_v<std::remove_cv_t<T>, wchar_t> &&
34 !std::is_same_v<std::remove_cv_t<T>, char16_t> &&
35 !std::is_same_v<std::remove_cv_t<T>, char32_t>;
36
37} // namespace impl
38
46class [[nodiscard]] Expr final {
47public:
49 template <typename T, std::enable_if_t<impl::kIsSqlInteger<T>, int> = 0>
50 Expr(T value)
51 : Expr(FromInteger(
52 static_cast<std::conditional_t<std::is_signed_v<T>, long long,
53 unsigned long long>>(value))) {}
54
59 template <typename T, std::enable_if_t<std::is_floating_point_v<T>, int> = 0>
60 Expr(T value) : Expr(FromDouble(static_cast<double>(value))) {}
61
63 Expr(bool) = delete;
64
67 Expr(char) = delete;
68
71 Expr(const char *) = delete;
72
77 static Expr
78 FromRaw(std::string s,
79 OperatorPrecedence precedence = OperatorPrecedence::kSymbol);
80
85 static Expr Literal(const std::string &value);
86
92 static Expr Ident(const std::string &name);
93
96 static Expr Null();
97
99 static Expr Bool(bool value);
100
107 static Expr Call(const std::string &name, std::initializer_list<Expr> args);
108
116 static Expr CallDistinct(const std::string &name,
117 std::initializer_list<Expr> args);
118
121 static Expr Coalesce(std::initializer_list<Expr> args);
122
124 static Expr NullIf(const Expr &a, const Expr &b);
125
130 static Expr Greatest(std::initializer_list<Expr> args);
131
136 static Expr Least(std::initializer_list<Expr> args);
137
139 static Condition Exists(const VirtualTable &subquery);
140
142 static Condition NotExists(const VirtualTable &subquery);
143
154 static Expr
155 PrefixOp(const std::string &op, const Expr &operand,
156 OperatorPrecedence precedence = OperatorPrecedence::kUnaryPlus);
157
159 static Expr Count(const Expr &arg);
160
162 static Expr CountAll();
163
165 static Expr CountDistinct(const Expr &arg);
166
169 static Expr Sum(const Expr &arg);
170
173 static Expr Avg(const Expr &arg);
174
176 static Expr Min(const Expr &arg);
177
179 static Expr Max(const Expr &arg);
180
182 Expr Dot(const Expr &other) const;
183
189 Expr CastRaw(const std::string &type) const;
190
194 Expr Collate(const Collation &collation) const;
195
197 Expr operator[](const Expr &other) const;
198
200 Expr operator^(const Expr &other) const;
201
213 Expr
214 BinaryOp(const std::string &op, const Expr &other,
215 OperatorPrecedence precedence = OperatorPrecedence::kAnyOther) const;
216
220 Condition Between(const Expr &a, const Expr &b) const;
221
225 Condition NotBetween(const Expr &a, const Expr &b) const;
226
229 Condition Like(const Expr &a) const;
230
233 Condition NotLike(const Expr &a) const;
234
237 Condition ILike(const Expr &a) const;
238
241 Condition NotILike(const Expr &a) const;
242
245 Condition SimilarTo(const Expr &a) const;
246
249 Condition NotSimilarTo(const Expr &a) const;
250
256 Condition In(std::initializer_list<Expr> values) const;
257
259 Condition In(const VirtualTable &subquery) const;
260
265 Condition NotIn(std::initializer_list<Expr> values) const;
266
268 Condition NotIn(const VirtualTable &subquery) const;
269
274 Condition EqAny(const Expr &array) const;
275
277 Condition EqAny(const VirtualTable &subquery) const;
278
282 Condition NeAll(const Expr &array) const;
283
285 Condition NeAll(const VirtualTable &subquery) const;
286
289
292
295
298
301 Condition IsDistinctFrom(const Expr &other) const;
302
305 Condition IsNotDistinctFrom(const Expr &other) const;
306
308 Expr operator+(const Expr &other) const;
309
311 Expr operator-(const Expr &other) const;
312
314 Expr operator*(const Expr &other) const;
315
317 Expr operator/(const Expr &other) const;
318
320 Expr operator%(const Expr &other) const;
321
324
331
335 Expr Concat(const Expr &other) const;
336
340 SelectItem As(std::string_view name) const;
341
347 std::string Extract(OperatorPrecedence precedence) const;
348
351 std::string ToString() const;
352
353private:
354 friend class Condition;
355 friend Condition operator<(const Expr &a, const Expr &b);
356 friend Condition operator<=(const Expr &a, const Expr &b);
357 friend Condition operator>(const Expr &a, const Expr &b);
358 friend Condition operator>=(const Expr &a, const Expr &b);
359 friend Condition operator==(const Expr &a, const Expr &b);
360 friend Condition operator!=(const Expr &a, const Expr &b);
361
362 Expr(std::string s);
363 Expr(std::string expr, OperatorPrecedence precedence);
364 explicit Expr(std::shared_ptr<const impl::Node> node);
365
366 static Expr FromInteger(long long value);
367 static Expr FromInteger(unsigned long long value);
368 static Expr FromDouble(double value);
369
370 static Condition CompareOp(const Expr &a, const char *op, const Expr &b);
371
372 static std::shared_ptr<const impl::Node>
373 BuildCallNode(const std::string &name, const char *args_prefix,
374 std::initializer_list<Expr> args);
375 static std::shared_ptr<const impl::Node>
376 BuildInListNode(const Expr &self, const char *connector,
377 std::initializer_list<Expr> values);
378
379 std::shared_ptr<const impl::Node> node_;
380};
381
383Condition operator<(const Expr &a, const Expr &b);
384
386Condition operator<=(const Expr &a, const Expr &b);
387
389Condition operator>(const Expr &a, const Expr &b);
390
392Condition operator>=(const Expr &a, const Expr &b);
393
395Condition operator==(const Expr &a, const Expr &b);
396
398Condition operator!=(const Expr &a, const Expr &b);
399
400} // namespace iron_query
A collation name for use with Expr::Collate.
Definition collation.hpp:10
A boolean-valued SQL predicate, e.g. the result of a comparison, LIKE/IN/BETWEEN/IS [NOT] NULL,...
Definition condition.hpp:25
Arbitrary SQL expression.
Definition expr.hpp:46
Condition NotIn(std::initializer_list< Expr > values) const
this NOT IN (a, b, c).
static Expr Greatest(std::initializer_list< Expr > args)
GREATEST(args...).
Expr operator[](const Expr &other) const
Array/index access: this[other].
static Expr Count(const Expr &arg)
COUNT(arg).
Condition IsTrue() const
this IS TRUE.
Expr BinaryOp(const std::string &op, const Expr &other, OperatorPrecedence precedence=OperatorPrecedence::kAnyOther) const
Arbitrary infix operator not otherwise named by IronQuery, e.g. BinaryOp("~", pattern) -> "this ~ pat...
Condition IsNotDistinctFrom(const Expr &other) const
this IS NOT DISTINCT FROM other, the NULL-safe equality comparison.
Condition NotSimilarTo(const Expr &a) const
this NOT SIMILAR TO a.
static Expr Bool(bool value)
The SQL boolean literal TRUE or FALSE.
static Expr Ident(const std::string &name)
Builds a properly escaped and quoted SQL identifier out of an arbitrary (possibly untrusted/dynamic) ...
Condition Between(const Expr &a, const Expr &b) const
this BETWEEN a AND b.
static Expr CallDistinct(const std::string &name, std::initializer_list< Expr > args)
Generalizes CountDistinct to any aggregate, e.g. CallDistinct("string_agg", {x, sep}) -> "string_agg(...
Condition NeAll(const VirtualTable &subquery) const
this <> ALL (subquery).
Expr operator-() const
Unary minus: -this.
friend Condition operator>=(const Expr &a, const Expr &b)
a >= b.
Expr operator/(const Expr &other) const
this / other.
Condition NotBetween(const Expr &a, const Expr &b) const
this NOT BETWEEN a AND b.
Expr operator*(const Expr &other) const
this * other.
static Expr Max(const Expr &arg)
MAX(arg).
Expr Collate(const Collation &collation) const
this COLLATE collation.
Expr(const char *)=delete
Deleted: a string literal would decay to bool. Use Literal for a value or FromRaw for a trusted SQL f...
Condition NeAll(const Expr &array) const
this <> ALL (array), the negation of EqAny.
Condition IsNull() const
this IS NULL.
static Expr CountDistinct(const Expr &arg)
COUNT(DISTINCT arg).
Expr Concat(const Expr &other) const
String concatenation: this || other. Named rather than operator|| because that operator is already Co...
static Expr FromRaw(std::string s, OperatorPrecedence precedence=OperatorPrecedence::kSymbol)
Wraps a trusted, developer-written SQL fragment verbatim, together with the precedence of its top-lev...
static Expr Sum(const Expr &arg)
SUM(arg).
Expr operator-(const Expr &other) const
this - other.
Expr operator+(const Expr &other) const
this + other.
friend Condition operator==(const Expr &a, const Expr &b)
a = b.
static Condition Exists(const VirtualTable &subquery)
EXISTS (subquery).
Condition IsDistinctFrom(const Expr &other) const
this IS DISTINCT FROM other, the NULL-safe inequality comparison: unlike !=, it is never NULL,...
static Expr NullIf(const Expr &a, const Expr &b)
NULLIF(a, b): NULL if a equals b, else a.
Condition SimilarTo(const Expr &a) const
this SIMILAR TO a.
Expr operator!() const
Value-level negation: NOT this. Distinct from Condition::operator!, which negates a predicate; this n...
Condition EqAny(const VirtualTable &subquery) const
this = ANY (subquery).
friend Condition operator<(const Expr &a, const Expr &b)
a < b.
Condition ILike(const Expr &a) const
this ILIKE a, a case-insensitive LIKE.
static Expr Null()
The SQL NULL literal. Note that comparing with it is never true: use IsNull / IsNotNull to test for i...
std::string Extract(OperatorPrecedence precedence) const
Renders the expression as SQL text, parenthesizing it if its top-level operator does not bind at leas...
std::string ToString() const
Renders the expression as a standalone, unparenthesized SQL fragment.
Condition IsNotNull() const
this IS NOT NULL.
Condition In(std::initializer_list< Expr > values) const
this IN (a, b, c).
Condition NotLike(const Expr &a) const
this NOT LIKE a.
friend Condition operator!=(const Expr &a, const Expr &b)
a != b.
static Expr Literal(const std::string &value)
Builds a properly escaped and quoted SQL string literal out of an arbitrary (possibly untrusted) valu...
static Expr Avg(const Expr &arg)
AVG(arg).
static Expr Least(std::initializer_list< Expr > args)
LEAST(args...).
static Expr Min(const Expr &arg)
MIN(arg).
SelectItem As(std::string_view name) const
Names this expression in a SELECT list: this AS name. name must be a plain (undotted) SQL identifier.
Expr operator^(const Expr &other) const
Exponentiation: this ^ other.
Expr operator%(const Expr &other) const
this % other.
static Expr PrefixOp(const std::string &op, const Expr &operand, OperatorPrecedence precedence=OperatorPrecedence::kUnaryPlus)
Arbitrary prefix operator not otherwise named by IronQuery, e.g. PrefixOp("@", x) -> "@ x"....
Expr Dot(const Expr &other) const
Member/field access: this.other.
static Expr CountAll()
COUNT(*), since "*" is not a valid Expr argument.
Expr CastRaw(const std::string &type) const
SQL type cast: CAST (this AS type). type is a trusted, developer-written SQL fragment inserted verbat...
Condition IsFalse() const
this IS FALSE.
Condition NotILike(const Expr &a) const
this NOT ILIKE a.
Condition EqAny(const Expr &array) const
this = ANY (array). The idiomatic way to test membership in a list that arrives as a single bind para...
Expr(char)=delete
Deleted: a character would render as its numeric code. Use Literal for a one-character string.
Condition In(const VirtualTable &subquery) const
this IN (subquery).
Condition NotIn(const VirtualTable &subquery) const
this NOT IN (subquery).
static Expr Call(const std::string &name, std::initializer_list< Expr > args)
Builds a function call expression, e.g. Expr::Call("COALESCE", {a, b}) -> "COALESCE(a,...
Condition Like(const Expr &a) const
this LIKE a.
friend Condition operator<=(const Expr &a, const Expr &b)
a <= b.
Expr(T value)
Wraps an integer literal of any width and signedness.
Definition expr.hpp:50
Expr(bool)=delete
Deleted: a bool would render as a number. Use Bool.
static Condition NotExists(const VirtualTable &subquery)
NOT EXISTS (subquery).
static Expr Coalesce(std::initializer_list< Expr > args)
COALESCE(args...): the first non-NULL argument.
friend Condition operator>(const Expr &a, const Expr &b)
a > b.
A single entry of a SELECT list: an expression, optionally renamed with Expr::As. Kept distinct from ...
Definition select_item.hpp:15
Any table value, including physical table, table result, materialized view, etc.
Definition virtual_table.hpp:14
OperatorPrecedence
Relative binding strength of SQL operators, used by iron_query::Expr::Extract to decide whether a sub...
Definition operator_precedence.hpp:10