5#include "../SqlQueryFormatter.hpp"
9#include <reflection-cpp/reflection.hpp>
14enum class SqlQueryBuilderMode : uint8_t
20struct [[nodiscard]] SqlFieldExpression final
22 std::string expression;
28 inline SqlFieldExpression Count(std::string
const& field =
"*") noexcept
30 return SqlFieldExpression { .expression = std::format(
"COUNT(\"{}\")", field) };
33 inline SqlFieldExpression Count(SqlQualifiedTableColumnName
const& field)
noexcept
35 return SqlFieldExpression { .expression = std::format(R
"(COUNT("{}"."{}"))", field.tableName, field.columnName) };
38 inline SqlFieldExpression Sum(std::string
const& field)
noexcept
40 return SqlFieldExpression { .expression = std::format(
"SUM(\"{}\")", field) };
43 inline SqlFieldExpression Sum(SqlQualifiedTableColumnName
const& field)
noexcept
45 return SqlFieldExpression { .expression = std::format(R
"(SUM("{}"."{}"))", field.tableName, field.columnName) };
48 inline SqlFieldExpression Avg(std::string
const& field)
noexcept
50 return SqlFieldExpression { .expression = std::format(
"AVG(\"{}\")", field) };
53 inline SqlFieldExpression Avg(SqlQualifiedTableColumnName
const& field)
noexcept
55 return SqlFieldExpression { .expression = std::format(R
"(AVG("{}"."{}"))", field.tableName, field.columnName) };
58 inline SqlFieldExpression Min(std::string
const& field)
noexcept
60 return SqlFieldExpression { .expression = std::format(
"MIN(\"{}\")", field) };
63 inline SqlFieldExpression Min(SqlQualifiedTableColumnName
const& field)
noexcept
65 return SqlFieldExpression { .expression = std::format(R
"(MIN("{}"."{}"))", field.tableName, field.columnName) };
68 inline SqlFieldExpression Max(std::string
const& field)
noexcept
70 return SqlFieldExpression { .expression = std::format(
"MAX(\"{}\")", field) };
73 inline SqlFieldExpression Max(SqlQualifiedTableColumnName
const& field)
noexcept
75 return SqlFieldExpression { .expression = std::format(R
"(MAX("{}"."{}"))", field.tableName, field.columnName) };
86 using SelectType = detail::SelectType;
89 SqlBasicSelectQueryBuilder<SqlSelectQueryBuilder> {},
90 _formatter { formatter }
92 _query.formatter = &formatter;
93 _query.searchCondition.tableName = std::move(table);
94 _query.searchCondition.tableAlias = std::move(tableAlias);
95 _query.fields.reserve(256);
101 _mode = SqlQueryBuilderMode::Varying;
106 template <
typename... MoreFields>
126 std::string_view tableName);
128 LIGHTWEIGHT_API
SqlSelectQueryBuilder& Fields(std::initializer_list<std::string_view>
const& fieldNames,
129 std::string_view tableName);
132 template <
typename FirstRecord,
typename... MoreRecords>
136 [[deprecated(
"Use Field(...).As(\"alias\") instead.")]]
140 [[deprecated(
"Use Field(...).As(\"alias\") instead.")]]
142 std::string_view
const& alias);
144 template <
typename Callable>
148 LIGHTWEIGHT_API ComposedQuery
Count();
151 LIGHTWEIGHT_API ComposedQuery
All();
154 LIGHTWEIGHT_API ComposedQuery
First(
size_t count = 1);
157 LIGHTWEIGHT_API ComposedQuery
Range(std::size_t offset, std::size_t limit);
159 LIGHTWEIGHT_FORCE_INLINE SqlSearchCondition& SearchCondition() noexcept
161 return _query.searchCondition;
164 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
SqlQueryFormatter const& Formatter() const noexcept
170 SqlQueryFormatter
const& _formatter;
171 SqlQueryBuilderMode _mode = SqlQueryBuilderMode::Fluent;
172 bool _aliasAllowed =
false;
175template <
typename... MoreFields>
178 using namespace std::string_view_literals;
180 std::ostringstream fragment;
182 if (!_query.fields.empty())
185 fragment <<
'"' << firstField <<
'"';
187 if constexpr (
sizeof...(MoreFields) > 0)
188 ((fragment << R
"(, ")"sv << std::forward<MoreFields>(moreFields) << '"') << ...);
190 _query.fields += fragment.str();
194template <
typename Callable>
195inline LIGHTWEIGHT_FORCE_INLINE
SqlSelectQueryBuilder& SqlSelectQueryBuilder::Build(Callable
const& callable)
201template <
typename FirstRecord,
typename... MoreRecords>
204 if constexpr (
sizeof...(MoreRecords) == 0)
206 Reflection::EnumerateMembers<FirstRecord>(
207 [&]<
size_t FieldIndex,
typename FieldType>() { Field(FieldNameAt<FieldIndex, FirstRecord>); });
211 Reflection::EnumerateMembers<FirstRecord>([&]<
size_t FieldIndex,
typename FieldType>() {
212 Field(SqlQualifiedTableColumnName {
213 .tableName = RecordTableName<FirstRecord>,
214 .columnName = FieldNameAt<FieldIndex, FirstRecord>,
218 (Reflection::EnumerateMembers<MoreRecords>([&]<
size_t FieldIndex,
typename FieldType>() {
219 Field(SqlQualifiedTableColumnName {
220 .tableName = RecordTableName<MoreRecords>,
221 .columnName = FieldNameAt<FieldIndex, MoreRecords>,
Query builder for building SELECT ... queries.
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 & Field(SqlQualifiedTableColumnName const &fieldName)
Adds a single column 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 ComposedQuery First(size_t count=1)
Finalizes building the query as SELECT TOP n field names FROM ... query.
LIGHTWEIGHT_API ComposedQuery All()
Finalizes building the query as SELECT field names FROM ... query.
LIGHTWEIGHT_API SqlSelectQueryBuilder & Field(SqlFieldExpression const &fieldExpression)
Adds an aggregate function call to the SELECT clause.
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 ComposedQuery Count()
Finalizes building the query as SELECT COUNT(*) ... query.
LIGHTWEIGHT_API SqlSelectQueryBuilder & As(std::string_view alias)
Aliases the last added field (a column or an aggregate call) in the SELECT clause.
constexpr LIGHTWEIGHT_FORCE_INLINE SqlSelectQueryBuilder & Varying() noexcept
Sets the builder mode to Varying, allowing varying final query types.
LIGHTWEIGHT_API SqlSelectQueryBuilder & Field(std::string_view const &fieldName)
Adds a single column 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.