Lightweight 0.20260921.0
Loading...
Searching...
No Matches
Select.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "../DataMapper/Record.hpp"
6#include "../SqlQueryFormatter.hpp"
7#include "../Utils.hpp"
8#include "Core.hpp"
9
10#include <reflection-cpp/reflection.hpp>
11
12#include <span>
13#include <utility>
14
15namespace Lightweight
16{
17
18struct [[nodiscard]] SqlFieldExpression final
19{
20 std::string expression;
21};
22
23namespace Aggregate
24{
25
26 inline SqlFieldExpression Count(std::string_view field = "*") noexcept
27 {
28 if (field == "*")
29 return SqlFieldExpression { .expression = "COUNT(*)" };
30 return SqlFieldExpression { .expression = std::format("COUNT(\"{}\")", field) };
31 }
32
33 inline SqlFieldExpression Count(SqlQualifiedTableColumnName const& field) noexcept
34 {
35 if (field.columnName == "*")
36 return SqlFieldExpression { .expression = std::format(R"(COUNT("{}".*))", field.tableName) };
37 return SqlFieldExpression { .expression = std::format(R"(COUNT("{}"."{}"))", field.tableName, field.columnName) };
38 }
39
40 inline SqlFieldExpression Sum(std::string_view field) noexcept
41 {
42 return SqlFieldExpression { .expression = std::format("SUM(\"{}\")", field) };
43 }
44
45 inline SqlFieldExpression Sum(SqlQualifiedTableColumnName const& field) noexcept
46 {
47 return SqlFieldExpression { .expression = std::format(R"(SUM("{}"."{}"))", field.tableName, field.columnName) };
48 }
49
50 inline SqlFieldExpression Avg(std::string_view field) noexcept
51 {
52 return SqlFieldExpression { .expression = std::format("AVG(\"{}\")", field) };
53 }
54
55 inline SqlFieldExpression Avg(SqlQualifiedTableColumnName const& field) noexcept
56 {
57 return SqlFieldExpression { .expression = std::format(R"(AVG("{}"."{}"))", field.tableName, field.columnName) };
58 }
59
60 inline SqlFieldExpression Min(std::string_view field) noexcept
61 {
62 return SqlFieldExpression { .expression = std::format("MIN(\"{}\")", field) };
63 }
64
65 inline SqlFieldExpression Min(SqlQualifiedTableColumnName const& field) noexcept
66 {
67 return SqlFieldExpression { .expression = std::format(R"(MIN("{}"."{}"))", field.tableName, field.columnName) };
68 }
69
70 inline SqlFieldExpression Max(std::string_view field) noexcept
71 {
72 return SqlFieldExpression { .expression = std::format("MAX(\"{}\")", field) };
73 }
74
75 inline SqlFieldExpression Max(SqlQualifiedTableColumnName const& field) noexcept
76 {
77 return SqlFieldExpression { .expression = std::format(R"(MAX("{}"."{}"))", field.tableName, field.columnName) };
78 }
79
80} // namespace Aggregate
81
82/// @brief Query builder for building SELECT ... queries.
83///
84/// Not constructed directly by user code; obtained by adding a projection
85/// (`Field` / `Fields` / `FieldAs` / `Build`) to a @ref SqlSelectQueryStarter — the
86/// type returned by `SqlQueryBuilder::Select()`. The starter intentionally hides
87/// the finalizers @ref All, @ref First, and @ref Range so that an empty
88/// `Select().All()` (which would emit malformed `SELECT FROM "T"` SQL) fails at
89/// compile time; the gate is in the starter, not here.
90///
91/// @see SqlQueryBuilder
92/// @see SqlSelectQueryStarter
93class [[nodiscard]] SqlSelectQueryBuilder: public SqlBasicSelectQueryBuilder<SqlSelectQueryBuilder>
94{
95 public:
96 /// The select query type alias.
97 using SelectType = detail::SelectType;
98
99 /// Constructs a SELECT query builder.
100 ///
101 /// @param formatter Dialect the query is written in.
102 /// @param table Table to select from.
103 /// @param tableAlias Alias for that table, empty for none.
104 /// @param inputBindings Receives the WHERE values as bound parameters instead of having them
105 /// written into the query text; null keeps them inline. Values are
106 /// appended, never cleared. Execute the result with
107 /// SqlStatement::ExecuteWithVariants(), not ExecuteDirect(), which would
108 /// leave the markers unbound. Both the vector and anything a stored
109 /// std::string_view / std::u16string_view points at must outlive the
110 /// execution, because the binder hands the driver that pointer directly.
111 /// @note An explicit SqlWildcard emits its marker without recording a value here, and a
112 /// WhereIn() set larger than SqlMaxBoundSetSize falls back to inline literals; either
113 /// makes the marker count differ from the vector size. A finalizer (All(), First(),
114 /// Count(), Range()) moves the query out of the builder, so keep building only until the
115 /// first one: a Where() issued afterwards still appends here while its marker is gone.
116 explicit SqlSelectQueryBuilder(SqlQueryFormatter const& formatter,
117 std::string table,
118 std::string tableAlias,
119 std::vector<SqlVariant>* inputBindings = nullptr) noexcept:
120 SqlBasicSelectQueryBuilder<SqlSelectQueryBuilder> {},
121 _formatter { formatter }
122 {
123 _query.formatter = &formatter;
124 _query.searchCondition.tableName = std::move(table);
125 _query.searchCondition.tableAlias = std::move(tableAlias);
126 _query.searchCondition.inputBindings = inputBindings;
127 _query.fields.reserve(256);
128 }
129
130 /// Adds a sequence of columns to the SELECT clause.
131 template <typename... MoreFields>
132 SqlSelectQueryBuilder& Fields(std::string_view const& firstField, MoreFields&&... moreFields);
133
134 /// Adds a single column to the SELECT clause.
135 LIGHTWEIGHT_API SqlSelectQueryBuilder& Field(std::string_view const& fieldName);
136
137 /// @copydoc Field(std::string_view const&)
138 /// Const overload: delegates via const_cast — see @ref Count() const.
139 [[nodiscard]] LIGHTWEIGHT_API SqlSelectQueryBuilder const& Field(std::string_view const& fieldName) const;
140
141 /// Adds a single column to the SELECT clause.
142 LIGHTWEIGHT_API SqlSelectQueryBuilder& Field(SqlQualifiedTableColumnName const& fieldName);
143
144 /// @copydoc Field(SqlQualifiedTableColumnName const&)
145 /// Const overload: delegates via const_cast — see @ref Count() const.
146 [[nodiscard]] LIGHTWEIGHT_API SqlSelectQueryBuilder const& Field(SqlQualifiedTableColumnName const& fieldName) const;
147
148 /// Adds an aggregate function call to the SELECT clause.
149 LIGHTWEIGHT_API SqlSelectQueryBuilder& Field(SqlFieldExpression const& fieldExpression);
150
151 /// @copydoc Field(SqlFieldExpression const&)
152 /// Const overload: delegates via const_cast — see @ref Count() const.
153 [[nodiscard]] LIGHTWEIGHT_API SqlSelectQueryBuilder const& Field(SqlFieldExpression const& fieldExpression) const;
154
155 /// Aliases the last added field (a column or an aggregate call) in the SELECT clause.
156 LIGHTWEIGHT_API SqlSelectQueryBuilder& As(std::string_view alias);
157
158 /// @copydoc As
159 /// Const overload: delegates via const_cast — see @ref Count() const.
160 [[nodiscard]] LIGHTWEIGHT_API SqlSelectQueryBuilder const& As(std::string_view alias) const;
161
162 /// Adds a sequence of columns to the SELECT clause.
163 LIGHTWEIGHT_API SqlSelectQueryBuilder& Fields(std::vector<std::string_view> const& fieldNames);
164
165 /// @copydoc Fields(std::vector<std::string_view> const&)
166 /// Const overload: delegates via const_cast — see @ref Count() const.
167 [[nodiscard]] LIGHTWEIGHT_API SqlSelectQueryBuilder const& Fields(std::vector<std::string_view> const& fieldNames) const;
168
169 /// Adds a sequence of columns from the given table to the SELECT clause.
170 LIGHTWEIGHT_API SqlSelectQueryBuilder& Fields(std::vector<std::string_view> const& fieldNames,
171 std::string_view tableName);
172
173 /// @copydoc Fields(std::vector<std::string_view> const&, std::string_view)
174 /// Const overload: delegates via const_cast — see @ref Count() const.
175 [[nodiscard]] LIGHTWEIGHT_API SqlSelectQueryBuilder const& Fields(std::vector<std::string_view> const& fieldNames,
176 std::string_view tableName) const;
177
178 /// Adds a sequence of columns from the given table to the SELECT clause.
179 LIGHTWEIGHT_API SqlSelectQueryBuilder& Fields(std::initializer_list<std::string_view> const& fieldNames,
180 std::string_view tableName);
181
182 /// @copydoc Fields(std::initializer_list<std::string_view> const&, std::string_view)
183 /// Const overload: delegates via const_cast — see @ref Count() const.
184 [[nodiscard]] LIGHTWEIGHT_API SqlSelectQueryBuilder const& Fields(
185 std::initializer_list<std::string_view> const& fieldNames, std::string_view tableName) const;
186
187 /// Adds a sequence of qualified table column names to the SELECT clause.
188 LIGHTWEIGHT_API SqlSelectQueryBuilder& Fields(std::span<SqlQualifiedTableColumnName const> fieldNames);
189
190 /// @copydoc Fields(std::span<SqlQualifiedTableColumnName const>)
191 /// Const overload: delegates via const_cast — see @ref Count() const.
192 [[nodiscard]] LIGHTWEIGHT_API SqlSelectQueryBuilder const& Fields(
193 std::span<SqlQualifiedTableColumnName const> fieldNames) const;
194
195 /// Adds a sequence of qualified table column names to the SELECT clause.
196 LIGHTWEIGHT_API SqlSelectQueryBuilder& Fields(std::initializer_list<SqlQualifiedTableColumnName const> fieldNames);
197
198 /// @copydoc Fields(std::initializer_list<SqlQualifiedTableColumnName const>)
199 /// Const overload: delegates via const_cast — see @ref Count() const.
200 [[nodiscard]] LIGHTWEIGHT_API SqlSelectQueryBuilder const& Fields(
201 std::initializer_list<SqlQualifiedTableColumnName const> fieldNames) const;
202
203 /// Adds a sequence of columns from the given tables to the SELECT clause.
204 template <typename FirstRecord, typename... MoreRecords>
206
207 /// Adds a single column with an alias to the SELECT clause.
208 [[deprecated("Use Field(...).As(\"alias\") instead.")]]
209 LIGHTWEIGHT_API SqlSelectQueryBuilder& FieldAs(std::string_view const& fieldName, std::string_view const& alias);
210
211 /// Adds a single column with an alias to the SELECT clause.
212 [[deprecated("Use Field(...).As(\"alias\") instead.")]]
214 std::string_view const& alias);
215
216 /// Builds the query using a callable.
217 template <typename Callable>
218 SqlSelectQueryBuilder& Build(Callable const& callable);
219
220 /// Finalizes building the query as SELECT COUNT(*) ... query.
221 ///
222 /// A preceding @c GroupBy is honored: the query then counts the rows of each group and
223 /// yields one row per group, rather than a single total over the whole result set.
224 LIGHTWEIGHT_API ComposedQuery Count();
225
226 /// @copydoc Count
227 /// Const overload: doesn't mutate @c *this — returns a snapshot ComposedQuery
228 /// so the finalizer can be reached through a `const SqlSelectQueryBuilder`.
229 [[nodiscard]] LIGHTWEIGHT_API ComposedQuery Count() const;
230
231 /// Finalizes building the query as SELECT field names FROM ... query.
232 LIGHTWEIGHT_API ComposedQuery All();
233
234 /// @copydoc All
235 /// Const overload: doesn't mutate @c *this — see @ref Count() const.
236 [[nodiscard]] LIGHTWEIGHT_API ComposedQuery All() const;
237
238 /// Finalizes building the query as SELECT TOP n field names FROM ... query.
239 LIGHTWEIGHT_API ComposedQuery First(size_t count = 1);
240
241 /// @copydoc First
242 /// Const overload: doesn't mutate @c *this — see @ref Count() const.
243 [[nodiscard]] LIGHTWEIGHT_API ComposedQuery First(size_t count = 1) const;
244
245 /// Finalizes building the query as SELECT field names FROM ... query with a range.
246 LIGHTWEIGHT_API ComposedQuery Range(std::size_t offset, std::size_t limit);
247
248 /// @copydoc Range
249 /// Const overload: doesn't mutate @c *this — see @ref Count() const.
250 [[nodiscard]] LIGHTWEIGHT_API ComposedQuery Range(std::size_t offset, std::size_t limit) const;
251
252 // clang-format off
253 /// Returns the search condition for the query.
254 LIGHTWEIGHT_FORCE_INLINE SqlSearchCondition& SearchCondition() noexcept // NOLINT(bugprone-derived-method-shadowing-base-method)
255 {
256 // clang-format on
257 return _query.searchCondition;
258 }
259
260 // clang-format off
261 /// Returns the SQL query formatter.
262 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE SqlQueryFormatter const& Formatter() const noexcept // NOLINT(bugprone-derived-method-shadowing-base-method)
263 {
264 // clang-format on
265 return _formatter;
266 }
267
268 private:
269 /// @brief Records @p name as the caller-given name of the projection just appended.
270 ///
271 /// Pass an empty @p name for a projection the caller did not name (an un-aliased aggregate); the
272 /// slot still holds its position so later entries stay aligned with their result columns.
273 /// @param name The column name exactly as the caller spelled it, or empty for an unnamed projection.
274 LIGHTWEIGHT_API void RecordProjectedFieldName(std::string name) const;
275
276 /// @brief Replaces the name of the most recently recorded projection, backing @c As().
277 /// @param alias The alias the caller gave the projection.
278 LIGHTWEIGHT_API void RenameLastProjectedFieldName(std::string_view alias) const;
279
280 /// @brief Marks the projection as containing a wildcard, disabling named column access.
281 LIGHTWEIGHT_API void RecordProjectionWildcard() const;
282
283 SqlQueryFormatter const& _formatter;
284 // mutable: see the note on _query in SqlBasicSelectQueryBuilder — the alias
285 // flag is part of the projection accumulator, so it follows _query's policy.
286 // Marked mutable so the const-qualified Field/Fields/As overloads above can
287 // delegate to their non-const counterparts via const_cast.
288 mutable bool _aliasAllowed = false;
289};
290
291template <typename... MoreFields>
292SqlSelectQueryBuilder& SqlSelectQueryBuilder::Fields(std::string_view const& firstField, MoreFields&&... moreFields)
293{
294 using namespace std::string_view_literals;
295
296 std::ostringstream fragment;
297
298 if (!_query.fields.empty())
299 fragment << ", "sv;
300
301 fragment << '"' << firstField << '"';
302 RecordProjectedFieldName(std::string(firstField));
303
304 if constexpr (sizeof...(MoreFields) > 0)
305 (((fragment << R"(, ")"sv << std::forward<MoreFields>(moreFields) << '"'),
306 RecordProjectedFieldName(std::string(std::string_view(moreFields)))),
307 ...);
308
309 _query.fields += fragment.str();
310 return *this;
311}
312
313/// Builds the query using a callable.
314template <typename Callable>
315inline LIGHTWEIGHT_FORCE_INLINE SqlSelectQueryBuilder& SqlSelectQueryBuilder::Build(Callable const& callable)
316{
317 callable(*this);
318 return *this;
319}
320
321/// Adds fields from one or more record types to the SELECT clause.
322template <typename FirstRecord, typename... MoreRecords>
323inline LIGHTWEIGHT_FORCE_INLINE SqlSelectQueryBuilder& SqlSelectQueryBuilder::Fields()
324{
325 // Relations (HasMany, HasManyThrough, HasOneThrough, ...) have no column of their own and
326 // must not be projected into the SELECT clause.
327 if constexpr (sizeof...(MoreRecords) == 0)
328 {
329 EnumerateRecordMembers<FirstRecord>([&]<size_t FieldIndex, typename FieldType>() {
330 if constexpr (RecordColumnMember<FieldType>)
331 Field(FieldNameAt<FieldIndex, FirstRecord>);
332 });
333 }
334 else
335 {
336 EnumerateRecordMembers<FirstRecord>([&]<size_t FieldIndex, typename FieldType>() {
337 if constexpr (RecordColumnMember<FieldType>)
339 .tableName = RecordTableName<FirstRecord>,
340 .columnName = FieldNameAt<FieldIndex, FirstRecord>,
341 });
342 });
343
344 (EnumerateRecordMembers<MoreRecords>([&]<size_t FieldIndex, typename FieldType>() {
345 if constexpr (RecordColumnMember<FieldType>)
347 .tableName = RecordTableName<MoreRecords>,
348 .columnName = FieldNameAt<FieldIndex, MoreRecords>,
349 });
350 }),
351 ...);
352 }
353 return *this;
354}
355
356namespace detail
357{
358 /// Always-false helper that depends on a template parameter so that a
359 /// @c static_assert in a function-template body only fires on instantiation
360 /// (and stays portable across compilers that have not implemented P2593).
361 template <typename...>
362 inline constexpr bool dependent_false = false;
363} // namespace detail
364
365/// @brief Compile-time gate for SELECT query construction.
366///
367/// Returned by `SqlQueryBuilder::Select()`. The starter inherits @em publicly
368/// from `SqlSelectQueryBuilder` (so every projection / WHERE / JOIN method
369/// resolves directly through inheritance), but defines its own @c All,
370/// @c First, and @c Range as deducing-this member templates whose bodies are
371/// ill-formed via @c static_assert. Those locals shadow the corresponding base
372/// methods at name lookup, so:
373///
374/// - `Select().All()`, `Select().First()`, `Select().Range(...)` — and the
375/// two-step variant `auto q = Select(); q.All();` — fail at compile time
376/// with a diagnostic asking the user to add a projection first. Without a
377/// projection these would emit malformed `SELECT FROM "T"` SQL.
378/// - `Select().Field(...).All()` compiles: `Field(...)` is inherited and
379/// returns `SqlSelectQueryBuilder&`, so the subsequent `All()` resolves
380/// against the base type (no shadowing) and reaches the real finalizer.
381/// - @c Count is intentionally not overridden — `SELECT COUNT(*) FROM ...`
382/// is well-formed without an explicit column list, so the inherited
383/// @c Count remains directly callable.
384/// - @c Distinct is overridden via deducing this so it returns @c Self&& and
385/// the starter identity survives it. That keeps the gate intact for
386/// `Select().Distinct().All()` while still allowing
387/// `Select().Distinct().Fields(...).All()`.
388///
389/// Methods that conceptually follow the column list (@c Where, @c OrderBy,
390/// @c GroupBy, @c InnerJoin, @c LeftOuterJoin, etc.) are reachable on the
391/// starter through public inheritance and return `SqlSelectQueryBuilder&`,
392/// which technically lets `Select().WhereNotNull("x").All()` compile (a known
393/// gate leak the type primarily defends against the empty-`Select().All()`
394/// typo, which is far more common).
395///
396/// For the imperative loop pattern, capture the first projection as a builder
397/// reference and continue from there:
398///
399/// @code
400/// auto starter = qb.Select();
401/// auto& query = starter.Field(columns[0].name);
402/// for (size_t i = 1; i < columns.size(); ++i)
403/// query.Field(columns[i].name);
404/// return query.All();
405/// @endcode
406class [[nodiscard]] SqlSelectQueryStarter final: public SqlSelectQueryBuilder
407{
408 public:
409 /// Constructs a SELECT query starter.
410 ///
411 /// Intentionally not @c explicit so the factory in @ref SqlQueryBuilder::Select
412 /// can return via braced init.
413 ///
414 /// @copydetails SqlSelectQueryBuilder::SqlSelectQueryBuilder
416 std::string table,
417 std::string tableAlias,
418 std::vector<SqlVariant>* inputBindings = nullptr) noexcept:
419 SqlSelectQueryBuilder { formatter, std::move(table), std::move(tableAlias), inputBindings }
420 {
421 }
422
423 /// Empty-projection guard for the @c All finalizer.
424 ///
425 /// Instantiating this template emits a @c static_assert telling the caller
426 /// to add a projection first. Calling `All()` on a `SqlSelectQueryBuilder&`
427 /// returned by `Field(...)` / `Fields(...)` bypasses the shadow and reaches
428 /// the real `SqlSelectQueryBuilder::All()`.
429 template <typename Self>
430 auto All(this Self const& self) -> ComposedQuery
431 {
432 (void) self;
433 static_assert(detail::dependent_false<Self>,
434 "SELECT requires a projection. Call .Field(...) or .Fields(...) "
435 "before .All() — an empty projection produces malformed "
436 "`SELECT FROM \"T\"` SQL.");
437 std::unreachable();
438 }
439
440 /// Empty-projection guard for the @c First finalizer — see @ref All.
441 template <typename Self>
442 auto First(this Self const& self, size_t count = 1) -> ComposedQuery
443 {
444 (void) self;
445 (void) count;
446 static_assert(detail::dependent_false<Self>,
447 "SELECT requires a projection. Call .Field(...) or .Fields(...) "
448 "before .First().");
449 std::unreachable();
450 }
451
452 /// Empty-projection guard for the @c Range finalizer — see @ref All.
453 template <typename Self>
454 auto Range(this Self const& self, std::size_t offset, std::size_t limit) -> ComposedQuery
455 {
456 (void) self;
457 (void) offset;
458 (void) limit;
459 static_assert(detail::dependent_false<Self>,
460 "SELECT requires a projection. Call .Field(...) or .Fields(...) "
461 "before .Range().");
462 std::unreachable();
463 }
464
465 /// State-preserving override: returns @c Self&&, so the starter identity
466 /// survives the call and the @c All / @c First / @c Range guards above
467 /// keep their gate against `Select().Distinct().All()`.
468 template <typename Self>
469 LIGHTWEIGHT_FORCE_INLINE auto&& Distinct(this Self&& self) noexcept
470 {
471 self.SqlSelectQueryBuilder::Distinct();
472 return std::forward<Self>(self);
473 }
474};
475
476} // namespace Lightweight
API to format SQL queries for different SQL dialects.
Query builder for building SELECT ... queries.
Definition Select.hpp:94
LIGHTWEIGHT_API SqlSelectQueryBuilder & FieldAs(std::string_view const &fieldName, std::string_view const &alias)
Adds a single column with an alias to the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder & Fields(std::vector< std::string_view > const &fieldNames, std::string_view tableName)
Adds a sequence of columns from the given table to the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder const & Field(SqlQualifiedTableColumnName const &fieldName) const
Adds a single column to the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder & Field(SqlQualifiedTableColumnName const &fieldName)
Adds a single column to the SELECT clause.
LIGHTWEIGHT_API ComposedQuery First(size_t count=1) const
Finalizes building the query as SELECT TOP n field names FROM ... query.
LIGHTWEIGHT_API SqlSelectQueryBuilder const & Fields(std::vector< std::string_view > const &fieldNames) const
Adds a sequence of columns to the SELECT clause.
SqlSelectQueryBuilder & Fields()
Adds a sequence of columns from the given tables to the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder & Fields(std::vector< std::string_view > const &fieldNames)
Adds a sequence of columns to the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder const & Fields(std::initializer_list< std::string_view > const &fieldNames, std::string_view tableName) const
Adds a sequence of columns from the given table to the SELECT clause.
SqlSelectQueryBuilder & Build(Callable const &callable)
Builds the query using a callable.
LIGHTWEIGHT_API SqlSelectQueryBuilder & Fields(std::initializer_list< SqlQualifiedTableColumnName const > fieldNames)
Adds a sequence of qualified table column names to the SELECT clause.
LIGHTWEIGHT_API ComposedQuery First(size_t count=1)
Finalizes building the query as SELECT TOP n field names FROM ... query.
LIGHTWEIGHT_API ComposedQuery All() const
Finalizes building the query as SELECT field names FROM ... query.
LIGHTWEIGHT_API SqlSelectQueryBuilder const & Field(std::string_view const &fieldName) const
Adds a single column to the SELECT clause.
LIGHTWEIGHT_API ComposedQuery All()
Finalizes building the query as SELECT field names FROM ... query.
LIGHTWEIGHT_API SqlSelectQueryBuilder const & As(std::string_view alias) const
Aliases the last added field (a column or an aggregate call) in the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder & Field(SqlFieldExpression const &fieldExpression)
Adds an aggregate function call to the SELECT clause.
LIGHTWEIGHT_API ComposedQuery Range(std::size_t offset, std::size_t limit) const
Finalizes building the query as SELECT field names FROM ... query with a range.
LIGHTWEIGHT_API SqlSelectQueryBuilder & FieldAs(SqlQualifiedTableColumnName const &fieldName, std::string_view const &alias)
Adds a single column with an alias to the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder const & Fields(std::vector< std::string_view > const &fieldNames, std::string_view tableName) const
Adds a sequence of columns from the given table to the SELECT clause.
LIGHTWEIGHT_FORCE_INLINE SqlQueryFormatter const & Formatter() const noexcept
Returns the SQL query formatter.
Definition Select.hpp:262
LIGHTWEIGHT_API SqlSelectQueryBuilder const & Field(SqlFieldExpression const &fieldExpression) const
Adds an aggregate function call to the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder const & Fields(std::initializer_list< SqlQualifiedTableColumnName const > fieldNames) const
Adds a sequence of qualified table column names to the SELECT clause.
SqlSelectQueryBuilder(SqlQueryFormatter const &formatter, std::string table, std::string tableAlias, std::vector< SqlVariant > *inputBindings=nullptr) noexcept
Definition Select.hpp:116
LIGHTWEIGHT_API ComposedQuery Count()
LIGHTWEIGHT_FORCE_INLINE SqlSearchCondition & SearchCondition() noexcept
Returns the search condition for the query.
Definition Select.hpp:254
LIGHTWEIGHT_API SqlSelectQueryBuilder & Fields(std::span< SqlQualifiedTableColumnName const > fieldNames)
Adds a sequence of qualified table column names to the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder & As(std::string_view alias)
Aliases the last added field (a column or an aggregate call) in the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder const & Fields(std::span< SqlQualifiedTableColumnName const > fieldNames) const
Adds a sequence of qualified table column names to the SELECT clause.
LIGHTWEIGHT_API ComposedQuery Count() const
LIGHTWEIGHT_API SqlSelectQueryBuilder & Field(std::string_view const &fieldName)
Adds a single column to the SELECT clause.
LIGHTWEIGHT_API SqlSelectQueryBuilder & Fields(std::initializer_list< std::string_view > const &fieldNames, std::string_view tableName)
Adds a sequence of columns from the given table to the SELECT clause.
LIGHTWEIGHT_API ComposedQuery Range(std::size_t offset, std::size_t limit)
Finalizes building the query as SELECT field names FROM ... query with a range.
Compile-time gate for SELECT query construction.
Definition Select.hpp:407
auto All(this Self const &self) -> ComposedQuery
Empty-projection guard for the All finalizer.
Definition Select.hpp:430
SqlSelectQueryStarter(SqlQueryFormatter const &formatter, std::string table, std::string tableAlias, std::vector< SqlVariant > *inputBindings=nullptr) noexcept
Constructs a SELECT query starter.
Definition Select.hpp:415
LIGHTWEIGHT_FORCE_INLINE auto && Distinct(this Self &&self) noexcept
State-preserving override: returns Self&&, so the starter identity survives the call and the All / Fi...
Definition Select.hpp:469
auto Range(this Self const &self, std::size_t offset, std::size_t limit) -> ComposedQuery
Empty-projection guard for the Range finalizer — see All.
Definition Select.hpp:454
auto First(this Self const &self, size_t count=1) -> ComposedQuery
Empty-projection guard for the First finalizer — see All.
Definition Select.hpp:442
Requires that T maps onto a column of its record's table.
Definition Record.hpp:400
@ Count
Number of enumerators; not an operation itself.
Represents a single column in a table.
Definition Field.hpp:84
SqlQualifiedTableColumnName represents a column name qualified with a table name.
Definition Utils.hpp:325
std::string_view tableName
The table name.
Definition Utils.hpp:327