6#include "../SqlQueryFormatter.hpp"
45 std::convertible_to<T, std::string_view> || std::convertible_to<T, std::string> || std::same_as<T, AliasedTableName>;
50 struct RawSqlCondition
52 std::string condition;
72template <Reflection::StringLiteral columnLiteral>
77 !std::ranges::any_of(columnLiteral,
78 [](
char c)
consteval {
return c ==
'\\' || c ==
'[' || c ==
']' || c ==
'"' || c ==
'\''; }),
79 "QualifiedColumnName should not contain symbols \\ [ ] \" '");
82 static_assert(std::ranges::count(columnLiteral,
'.') == 1,
83 "QualifiedColumnName requires a column name with a single '.' to separate table and column name");
84 constexpr auto column = columnLiteral.sv();
85 auto dotPos = column.find(
'.');
86 return SqlQualifiedTableColumnName { .
tableName = column.substr(0, dotPos), .columnName = column.substr(dotPos + 1) };
92 template <
typename ColumnName>
93 std::string MakeSqlColumnName(ColumnName
const& columnName)
95 using namespace std::string_view_literals;
98 if constexpr (std::is_same_v<ColumnName, SqlQualifiedTableColumnName>)
100 output.reserve(columnName.tableName.size() + columnName.columnName.size() + 5);
102 output += columnName.tableName;
103 output += R
"(".")"sv;
104 output += columnName.columnName;
107 else if constexpr (std::is_same_v<ColumnName, SqlRawColumnNameView>)
109 output += columnName.value;
111 else if constexpr (std::is_same_v<ColumnName, SqlWildcardType>)
118 output += columnName;
124 template <
typename T>
125 std::string MakeEscapedSqlString(T
const& value)
127 std::string escapedValue;
128 escapedValue +=
'\'';
130 for (
auto const ch: value)
134 escapedValue +=
'\'';
137 escapedValue +=
'\'';
143struct [[nodiscard]] SqlSearchCondition
145 std::string tableName;
146 std::string tableAlias;
147 std::string tableJoins;
148 std::string condition;
149 std::vector<SqlVariant>* inputBindings =
nullptr;
159 _referenceTable { referenceTable },
160 _condition { *condition }
167 return Operator(joinColumnName, onOtherColumn,
"AND");
173 return Operator(joinColumnName, onOtherColumn,
"OR");
182 _firstCall = !_firstCall;
184 _condition += std::format(
" {} ", op);
187 _condition += _referenceTable;
188 _condition +=
"\".\"";
189 _condition += joinColumnName;
190 _condition +=
"\" = \"";
192 _condition +=
"\".\"";
200 std::string_view _referenceTable;
201 std::string& _condition;
202 bool _firstCall =
true;
210template <
typename Derived>
215 [[nodiscard]] Derived&
And() noexcept;
218 [[nodiscard]] Derived& Or() noexcept;
221 [[nodiscard]] Derived& Not() noexcept;
224 [[nodiscard]] Derived& WhereRaw(std::string_view sqlConditionExpression);
227 template <typename ColumnName, typename T>
228 [[nodiscard]] Derived& Where(ColumnName const& columnName, std::string_view binaryOp, T const& value);
231 template <typename ColumnName, typename SubSelectQuery>
232 requires(std::is_invocable_r_v<std::
string, decltype(&SubSelectQuery::ToSql), SubSelectQuery const&>)
233 [[nodiscard]] Derived& Where(ColumnName const& columnName, std::string_view binaryOp, SubSelectQuery const& value);
236 template <typename ColumnName, typename T>
237 [[nodiscard]] Derived& OrWhere(ColumnName const& columnName, std::string_view binaryOp, T const& value);
240 template <typename ColumnName, std::
size_t N>
241 Derived& Where(ColumnName const& columnName, std::string_view binaryOp,
char const (&value)[N]);
244 template <typename ColumnName, typename T>
245 [[nodiscard]] Derived& Where(ColumnName const& columnName, T const& value);
248 template <typename ColumnName, typename T>
249 [[nodiscard]] Derived& OrWhere(ColumnName const& columnName, T const& value);
252 template <typename Callable>
254 [[nodiscard]] Derived& Where(Callable const& callable);
257 template <typename Callable>
259 [[nodiscard]] Derived& OrWhere(Callable const& callable);
262 template <typename ColumnName, std::ranges::input_range InputRange>
263 [[nodiscard]] Derived& WhereIn(ColumnName const& columnName, InputRange const& values);
266 template <typename ColumnName, typename T>
267 [[nodiscard]] Derived& WhereIn(ColumnName const& columnName, std::initializer_list<T> const& values);
270 template <typename ColumnName, typename SubSelectQuery>
271 requires(std::is_invocable_r_v<std::
string, decltype(&SubSelectQuery::ToSql), SubSelectQuery const&>)
272 [[nodiscard]] Derived& WhereIn(ColumnName const& columnName, SubSelectQuery const& subSelectQuery);
275 template <typename ColumnName>
276 [[nodiscard]] Derived& WhereNull(ColumnName const& columnName);
279 template <typename ColumnName>
280 [[nodiscard]] Derived& WhereNotNull(ColumnName const& columnName);
283 template <typename ColumnName, typename T>
284 [[nodiscard]] Derived& WhereNotEqual(ColumnName const& columnName, T const& value);
287 template <typename ColumnName>
288 [[nodiscard]] Derived& WhereTrue(ColumnName const& columnName);
291 template <typename ColumnName>
292 [[nodiscard]] Derived& WhereFalse(ColumnName const& columnName);
295 template <typename LeftColumn, typename RightColumn>
296 [[nodiscard]] Derived& WhereColumn(LeftColumn const& left, std::string_view binaryOp, RightColumn const& right);
303 [[nodiscard]] Derived& InnerJoin(TableName auto joinTable,
304 std::string_view joinColumnName,
308 [[nodiscard]] Derived& InnerJoin(TableName auto joinTable,
309 std::string_view joinColumnName,
310 std::string_view onMainTableColumn);
313 template <typename OnChainCallable>
315 [[nodiscard]] Derived& InnerJoin(TableName auto joinTable, OnChainCallable const& onClauseBuilder);
329 template <auto LeftField, auto RightField>
330 [[nodiscard]] Derived& InnerJoin();
333 [[nodiscard]] Derived& LeftOuterJoin(TableName auto joinTable,
334 std::string_view joinColumnName,
338 [[nodiscard]] Derived& LeftOuterJoin(TableName auto joinTable,
339 std::string_view joinColumnName,
340 std::string_view onMainTableColumn);
343 template <typename OnChainCallable>
345 [[nodiscard]] Derived& LeftOuterJoin(TableName auto joinTable, OnChainCallable const& onClauseBuilder);
348 [[nodiscard]] Derived& RightOuterJoin(TableName auto joinTable,
349 std::string_view joinColumnName,
353 [[nodiscard]] Derived& RightOuterJoin(TableName auto joinTable,
354 std::string_view joinColumnName,
355 std::string_view onMainTableColumn);
358 template <typename OnChainCallable>
360 [[nodiscard]] Derived& RightOuterJoin(TableName auto joinTable, OnChainCallable const& onClauseBuilder);
363 [[nodiscard]] Derived& FullOuterJoin(TableName auto joinTable,
364 std::string_view joinColumnName,
368 [[nodiscard]] Derived& FullOuterJoin(TableName auto joinTable,
369 std::string_view joinColumnName,
370 std::string_view onMainTableColumn);
373 template <typename OnChainCallable>
375 [[nodiscard]] Derived& FullOuterJoin(TableName auto joinTable, OnChainCallable const& onClauseBuilder);
378 SqlSearchCondition& SearchCondition() noexcept;
381 enum class WhereJunctor : uint8_t
389 WhereJunctor m_nextWhereJunctor = WhereJunctor::Where;
390 bool m_nextIsNot =
false;
392 void AppendWhereJunctor();
395 template <
typename ColumnName>
396 requires(std::same_as<ColumnName, SqlQualifiedTableColumnName> || std::convertible_to<ColumnName, std::string_view>
397 || std::same_as<ColumnName, SqlRawColumnNameView> || std::convertible_to<ColumnName, std::string>)
398 void AppendColumnName(ColumnName
const& columnName);
401 template <
typename LiteralType>
402 void AppendLiteralValue(LiteralType
const& value);
405 template <
typename LiteralType,
typename TargetType>
406 void PopulateLiteralValueInto(LiteralType
const& value, TargetType& target);
408 template <
typename LiteralType>
409 detail::RawSqlCondition PopulateSqlSetExpression(LiteralType
const& values);
411 enum class JoinType : uint8_t
420 [[nodiscard]] Derived& Join(JoinType joinType,
421 TableName
auto joinTable,
422 std::string_view joinColumnName,
423 SqlQualifiedTableColumnName onOtherColumn);
426 [[nodiscard]] Derived& Join(JoinType joinType,
427 TableName
auto joinTable,
428 std::string_view joinColumnName,
429 std::string_view onMainTableColumn);
432 template <
typename OnChainCallable>
433 [[nodiscard]] Derived& Join(JoinType joinType, TableName
auto joinTable, OnChainCallable
const& onClauseBuilder);
436enum class SqlResultOrdering : uint8_t
444 enum class SelectType : std::uint8_t
455 SelectType selectType = SelectType::Undefined;
456 SqlQueryFormatter
const* formatter =
nullptr;
458 bool distinct =
false;
459 SqlSearchCondition searchCondition {};
467 size_t limit = (std::numeric_limits<size_t>::max)();
469 [[nodiscard]] LIGHTWEIGHT_API std::string
ToSql()
const;
473template <
typename Derived>
474class [[nodiscard]] SqlBasicSelectQueryBuilder:
public SqlWhereClauseBuilder<Derived>
478 Derived& Distinct() noexcept;
481 Derived& OrderBy(SqlQualifiedTableColumnName const& columnName,
482 SqlResultOrdering ordering = SqlResultOrdering::ASCENDING);
485 Derived& OrderBy(std::string_view columnName, SqlResultOrdering ordering = SqlResultOrdering::ASCENDING);
488 Derived& GroupBy(std::string_view columnName);
490 using ComposedQuery = detail::ComposedQuery;
493 ComposedQuery _query {};
496template <
typename Derived>
497inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::Distinct() noexcept
499 _query.distinct =
true;
500 return static_cast<Derived&
>(*this);
503template <
typename Derived>
504inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::OrderBy(std::string_view columnName,
505 SqlResultOrdering ordering)
507 if (_query.orderBy.empty())
508 _query.orderBy +=
"\n ORDER BY ";
510 _query.orderBy +=
", ";
512 _query.orderBy +=
'"';
513 _query.orderBy += columnName;
514 _query.orderBy +=
'"';
516 if (ordering == SqlResultOrdering::DESCENDING)
517 _query.orderBy +=
" DESC";
518 else if (ordering == SqlResultOrdering::ASCENDING)
519 _query.orderBy +=
" ASC";
521 return static_cast<Derived&
>(*this);
524template <
typename Derived>
525inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::OrderBy(
526 SqlQualifiedTableColumnName
const& columnName, SqlResultOrdering ordering)
528 if (_query.orderBy.empty())
529 _query.orderBy +=
"\n ORDER BY ";
531 _query.orderBy +=
", ";
533 _query.orderBy +=
'"';
534 _query.orderBy += columnName.tableName;
535 _query.orderBy +=
"\".\"";
536 _query.orderBy += columnName.columnName;
537 _query.orderBy +=
'"';
539 if (ordering == SqlResultOrdering::DESCENDING)
540 _query.orderBy +=
" DESC";
541 else if (ordering == SqlResultOrdering::ASCENDING)
542 _query.orderBy +=
" ASC";
544 return static_cast<Derived&
>(*this);
547template <
typename Derived>
548inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::GroupBy(std::string_view columnName)
550 if (_query.groupBy.empty())
551 _query.groupBy +=
"\n GROUP BY ";
553 _query.groupBy +=
", ";
555 _query.groupBy +=
'"';
556 _query.groupBy += columnName;
557 _query.groupBy +=
'"';
559 return static_cast<Derived&
>(*this);
562template <
typename Derived>
565 m_nextWhereJunctor = WhereJunctor::And;
566 return static_cast<Derived&
>(*this);
569template <
typename Derived>
572 m_nextWhereJunctor = WhereJunctor::Or;
573 return static_cast<Derived&
>(*this);
576template <
typename Derived>
579 m_nextIsNot = !m_nextIsNot;
580 return static_cast<Derived&
>(*this);
584template <
typename Derived>
585template <
typename ColumnName,
typename T>
588 if constexpr (detail::OneOf<T, SqlNullType, std::nullopt_t>)
593 return Where(columnName,
"IS NOT", value);
596 return Where(columnName,
"IS", value);
599 return Where(columnName,
"=", value);
603template <
typename Derived>
604template <
typename ColumnName,
typename T>
608 return Or().Where(columnName, value);
612template <
typename Derived>
613template <
typename Callable>
614 requires std::invocable<Callable, SqlWhereClauseBuilder<Derived>&>
617 return Or().Where(callable);
621template <
typename Derived>
622template <
typename Callable>
623 requires std::invocable<Callable, SqlWhereClauseBuilder<Derived>&>
626 auto& condition = SearchCondition().condition;
628 auto const originalSize = condition.size();
630 AppendWhereJunctor();
631 m_nextWhereJunctor = WhereJunctor::Null;
634 auto const sizeBeforeCallable = condition.size();
636 (void) callable(*
this);
638 if (condition.size() == sizeBeforeCallable)
639 condition.resize(originalSize);
643 return static_cast<Derived&
>(*this);
647template <
typename Derived>
648template <
typename ColumnName, std::ranges::input_range InputRange>
650 InputRange
const& values)
653 return static_cast<Derived&
>(*this);
654 return Where(columnName,
"IN", PopulateSqlSetExpression(values));
658template <
typename Derived>
659template <
typename ColumnName,
typename T>
661 std::initializer_list<T>
const& values)
663 if (values.begin() == values.end())
664 return static_cast<Derived&
>(*this);
665 return Where(columnName,
"IN", PopulateSqlSetExpression(values));
669template <
typename Derived>
670template <
typename ColumnName,
typename SubSelectQuery>
671 requires(std::is_invocable_r_v<std::string,
decltype(&SubSelectQuery::ToSql), SubSelectQuery
const&>)
673 SubSelectQuery
const& subSelectQuery)
675 return Where(columnName,
"IN", detail::RawSqlCondition {
"(" + subSelectQuery.ToSql() +
")" });
679template <
typename Derived>
680template <
typename ColumnName>
683 return Where(columnName,
"IS NOT", detail::RawSqlCondition {
"NULL" });
687template <
typename Derived>
688template <
typename ColumnName>
691 return Where(columnName,
"IS", detail::RawSqlCondition {
"NULL" });
695template <
typename Derived>
696template <
typename ColumnName,
typename T>
700 if constexpr (detail::OneOf<T, SqlNullType, std::nullopt_t>)
701 return Where(columnName,
"IS NOT", value);
703 return Where(columnName,
"!=", value);
707template <
typename Derived>
708template <
typename ColumnName>
711 return Where(columnName,
"=",
true);
715template <
typename Derived>
716template <
typename ColumnName>
719 return Where(columnName,
"=",
false);
723template <
typename Derived>
724template <
typename LeftColumn,
typename RightColumn>
726 std::string_view binaryOp,
727 RightColumn
const& right)
729 AppendWhereJunctor();
731 AppendColumnName(left);
732 SearchCondition().condition +=
' ';
733 SearchCondition().condition += binaryOp;
734 SearchCondition().condition +=
' ';
735 AppendColumnName(right);
737 return static_cast<Derived&
>(*this);
741struct WhereConditionLiteralType
743 constexpr static bool needsQuotes = !std::is_integral_v<T> && !std::is_floating_point_v<T> && !std::same_as<T, bool>
744 && !std::same_as<T, SqlWildcardType>;
748template <
typename Derived>
749template <
typename ColumnName, std::
size_t N>
751 std::string_view binaryOp,
752 char const (&value)[N])
754 return Where(columnName, binaryOp, std::string_view { value, N - 1 });
758template <
typename Derived>
759template <
typename ColumnName,
typename T>
761 std::string_view binaryOp,
764 auto& searchCondition = SearchCondition();
766 AppendWhereJunctor();
767 AppendColumnName(columnName);
768 searchCondition.condition +=
' ';
769 searchCondition.condition += binaryOp;
770 searchCondition.condition +=
' ';
771 AppendLiteralValue(value);
773 return static_cast<Derived&
>(*this);
777template <
typename Derived>
778template <
typename ColumnName,
typename SubSelectQuery>
779 requires(std::is_invocable_r_v<std::string,
decltype(&SubSelectQuery::ToSql), SubSelectQuery
const&>)
781 std::string_view binaryOp,
782 SubSelectQuery
const& value)
784 return Where(columnName, binaryOp, detail::RawSqlCondition {
"(" + value.ToSql() +
")" });
788template <
typename Derived>
789template <
typename ColumnName,
typename T>
791 std::string_view binaryOp,
794 return Or().
Where(columnName, binaryOp, value);
797template <
typename Derived>
799 std::string_view joinColumnName,
802 return Join(JoinType::INNER, joinTable, joinColumnName, onOtherColumn);
805template <
typename Derived>
807 std::string_view joinColumnName,
808 std::string_view onMainTableColumn)
810 return Join(JoinType::INNER, joinTable, joinColumnName, onMainTableColumn);
813template <
typename Derived>
814template <auto LeftField, auto RightField>
817#if defined(LIGHTWEIGHT_CXX26_REFLECTION)
818 return Join(JoinType::INNER,
820 FieldNameOf<LeftField>,
826 FieldNameOf<LeftField>,
831template <
typename Derived>
832template <
typename OnChainCallable>
833 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
836 return Join(JoinType::INNER, joinTable, onClauseBuilder);
839template <
typename Derived>
843 return Join(JoinType::LEFT, joinTable, joinColumnName, onOtherColumn);
846template <
typename Derived>
848 std::string_view joinColumnName,
849 std::string_view onMainTableColumn)
851 return Join(JoinType::LEFT, joinTable, joinColumnName, onMainTableColumn);
854template <
typename Derived>
855template <
typename OnChainCallable>
856 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
859 return Join(JoinType::LEFT, joinTable, onClauseBuilder);
862template <
typename Derived>
866 return Join(JoinType::RIGHT, joinTable, joinColumnName, onOtherColumn);
869template <
typename Derived>
871 std::string_view joinColumnName,
872 std::string_view onMainTableColumn)
874 return Join(JoinType::RIGHT, joinTable, joinColumnName, onMainTableColumn);
877template <
typename Derived>
878template <
typename OnChainCallable>
879 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
882 return Join(JoinType::RIGHT, joinTable, onClauseBuilder);
885template <
typename Derived>
889 return Join(JoinType::FULL, joinTable, joinColumnName, onOtherColumn);
892template <
typename Derived>
894 std::string_view joinColumnName,
895 std::string_view onMainTableColumn)
897 return Join(JoinType::FULL, joinTable, joinColumnName, onMainTableColumn);
900template <
typename Derived>
901template <
typename OnChainCallable>
902 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
905 return Join(JoinType::FULL, joinTable, onClauseBuilder);
908template <
typename Derived>
911 AppendWhereJunctor();
913 auto& condition = SearchCondition().condition;
914 condition += sqlConditionExpression;
916 return static_cast<Derived&
>(*this);
919template <
typename Derived>
922 return static_cast<Derived*
>(
this)->SearchCondition();
925template <
typename Derived>
926inline LIGHTWEIGHT_FORCE_INLINE SqlQueryFormatter
const& SqlWhereClauseBuilder<Derived>::Formatter() const noexcept
928 return static_cast<Derived const*
>(
this)->Formatter();
931template <
typename Derived>
932inline LIGHTWEIGHT_FORCE_INLINE
void SqlWhereClauseBuilder<Derived>::AppendWhereJunctor()
934 using namespace std::string_view_literals;
936 auto& condition = SearchCondition().condition;
938 switch (m_nextWhereJunctor)
940 case WhereJunctor::Null:
942 case WhereJunctor::Where:
943 condition +=
"\n WHERE "sv;
945 case WhereJunctor::And:
946 condition +=
" AND "sv;
948 case WhereJunctor::Or:
949 condition +=
" OR "sv;
955 condition +=
"NOT "sv;
959 m_nextWhereJunctor = WhereJunctor::And;
963template <
typename Derived>
964template <
typename ColumnName>
965 requires(std::same_as<ColumnName, SqlQualifiedTableColumnName> || std::convertible_to<ColumnName, std::string_view>
966 || std::same_as<ColumnName, SqlRawColumnNameView> || std::convertible_to<ColumnName, std::string>)
969 SearchCondition().condition += detail::MakeSqlColumnName(columnName);
973template <
typename Derived>
974template <
typename LiteralType>
977 auto& searchCondition = SearchCondition();
979 if constexpr (std::is_same_v<LiteralType, SqlQualifiedTableColumnName>
980 || detail::OneOf<LiteralType, SqlNullType, std::nullopt_t> || std::is_same_v<LiteralType, SqlWildcardType>
981 || std::is_same_v<LiteralType, detail::RawSqlCondition>)
983 PopulateLiteralValueInto(value, searchCondition.condition);
985 else if (searchCondition.inputBindings)
987 searchCondition.condition +=
'?';
988 searchCondition.inputBindings->emplace_back(value);
990 else if constexpr (std::is_same_v<LiteralType, bool>)
992 searchCondition.condition += Formatter().BooleanLiteral(value);
994 else if constexpr (!WhereConditionLiteralType<LiteralType>::needsQuotes)
996 searchCondition.condition += std::format(
"{}", value);
1000 searchCondition.condition += detail::MakeEscapedSqlString(std::format(
"{}", value));
1005template <
typename Derived>
1006template <
typename LiteralType,
typename TargetType>
1010 if constexpr (std::is_same_v<LiteralType, SqlQualifiedTableColumnName>)
1013 target += value.tableName;
1015 target += value.columnName;
1018 else if constexpr (detail::OneOf<LiteralType, SqlNullType, std::nullopt_t>)
1022 else if constexpr (std::is_same_v<LiteralType, SqlWildcardType>)
1026 else if constexpr (std::is_same_v<LiteralType, detail::RawSqlCondition>)
1028 target += value.condition;
1030 else if constexpr (std::is_same_v<LiteralType, bool>)
1032 target += Formatter().BooleanLiteral(value);
1034 else if constexpr (!WhereConditionLiteralType<LiteralType>::needsQuotes)
1036 target += std::format(
"{}", value);
1040 target += detail::MakeEscapedSqlString(std::format(
"{}", value));
1044template <
typename Derived>
1045template <
typename LiteralType>
1048 using namespace std::string_view_literals;
1049 std::ostringstream fragment;
1051#if !defined(__cpp_lib_ranges_enumerate)
1053 for (
auto const& value: values)
1057 for (
auto const&& [index, value]: values | std::views::enumerate)
1063 std::string valueString;
1064 PopulateLiteralValueInto(value, valueString);
1065 fragment << valueString;
1068 return detail::RawSqlCondition { fragment.str() };
1071template <
typename Derived>
1072inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Join(JoinType joinType,
1073 TableName
auto joinTable,
1074 std::string_view joinColumnName,
1075 SqlQualifiedTableColumnName onOtherColumn)
1077 static constexpr std::array<std::string_view, 4> JoinTypeStrings = {
1084 if constexpr (std::is_same_v<std::remove_cvref_t<
decltype(joinTable)>, AliasedTableName>)
1086 SearchCondition().tableJoins += std::format(
"\n"
1087 R
"( {0} JOIN "{1}" AS "{2}" ON "{2}"."{3}" = "{4}"."{5}")",
1088 JoinTypeStrings[static_cast<std::size_t
>(joinType)],
1089 joinTable.tableName,
1092 onOtherColumn.tableName,
1093 onOtherColumn.columnName);
1097 SearchCondition().tableJoins += std::format(
"\n"
1098 R
"( {0} JOIN "{1}" ON "{1}"."{2}" = "{3}"."{4}")",
1099 JoinTypeStrings[static_cast<std::size_t
>(joinType)],
1102 onOtherColumn.tableName,
1103 onOtherColumn.columnName);
1105 return static_cast<Derived&
>(*this);
1108template <
typename Derived>
1109inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Join(JoinType joinType,
1110 TableName
auto joinTable,
1111 std::string_view joinColumnName,
1112 std::string_view onMainTableColumn)
1114 return Join(joinType,
1117 SqlQualifiedTableColumnName { .tableName = SearchCondition().tableName, .columnName = onMainTableColumn });
1121template <
typename Derived>
1122template <
typename Callable>
1124 TableName
auto joinTable,
1125 Callable
const& onClauseBuilder)
1127 static constexpr std::array<std::string_view, 4> JoinTypeStrings = {
1134 size_t const originalSize = SearchCondition().tableJoins.size();
1135 SearchCondition().tableJoins +=
1136 std::format(
"\n {0} JOIN \"{1}\" ON ", JoinTypeStrings[
static_cast<std::size_t
>(joinType)], joinTable);
1137 size_t const sizeBefore = SearchCondition().tableJoins.size();
1139 size_t const sizeAfter = SearchCondition().tableJoins.size();
1140 if (sizeBefore == sizeAfter)
1141 SearchCondition().tableJoins.resize(originalSize);
1143 return static_cast<Derived&
>(*this);
Query builder for building JOIN conditions.
SqlJoinConditionBuilder & On(std::string_view joinColumnName, SqlQualifiedTableColumnName onOtherColumn)
Adds an AND join condition.
SqlJoinConditionBuilder(std::string_view referenceTable, std::string *condition) noexcept
Constructs a new SqlJoinConditionBuilder.
SqlJoinConditionBuilder & Operator(std::string_view joinColumnName, SqlQualifiedTableColumnName onOtherColumn, std::string_view op)
Adds a join condition with a custom operator.
SqlJoinConditionBuilder & OrOn(std::string_view joinColumnName, SqlQualifiedTableColumnName onOtherColumn)
Adds an OR join condition.
Derived & FullOuterJoin(TableName auto joinTable, std::string_view joinColumnName, SqlQualifiedTableColumnName onOtherColumn)
Constructs an FULL OUTER JOIN clause.
Derived & WhereTrue(ColumnName const &columnName)
Constructs or extends a WHERE clause to test for a value being true.
Derived & WhereIn(ColumnName const &columnName, InputRange const &values)
Constructs or extends an WHERE/OR clause to test for a value, satisfying std::ranges::input_range.
Derived & WhereNotNull(ColumnName const &columnName)
Constructs or extends a WHERE clause to test for a value being not null.
Derived & Where(ColumnName const &columnName, std::string_view binaryOp, T const &value)
Constructs or extends a WHERE clause to test for a binary operation.
Derived & WhereRaw(std::string_view sqlConditionExpression)
Constructs or extends a raw WHERE clause.
Derived & LeftOuterJoin(TableName auto joinTable, std::string_view joinColumnName, SqlQualifiedTableColumnName onOtherColumn)
Constructs an LEFT OUTER JOIN clause.
Derived & Not() noexcept
Indicates, that the next WHERE clause should be negated.
Derived & WhereNull(ColumnName const &columnName)
Constructs or extends an WHERE/OR clause to test for a value to be NULL.
Derived & WhereNotEqual(ColumnName const &columnName, T const &value)
Constructs or extends a WHERE clause to test for a value being equal to another column.
Derived & RightOuterJoin(TableName auto joinTable, std::string_view joinColumnName, SqlQualifiedTableColumnName onOtherColumn)
Constructs an RIGHT OUTER JOIN clause.
Derived & OrWhere(ColumnName const &columnName, std::string_view binaryOp, T const &value)
Constructs or extends a WHERE/OR clause to test for a binary operation.
Derived & WhereColumn(LeftColumn const &left, std::string_view binaryOp, RightColumn const &right)
Construts or extends a WHERE clause to test for a binary operation between two columns.
Derived & And() noexcept
Indicates, that the next WHERE clause should be AND-ed (default).
Derived & Or() noexcept
Indicates, that the next WHERE clause should be OR-ed.
Derived & WhereFalse(ColumnName const &columnName)
Constructs or extends a WHERE clause to test for a value being false.
constexpr std::string_view RecordTableName
Holds the SQL tabl ename for the given record type.
LIGHTWEIGHT_API std::vector< std::string > ToSql(SqlQueryFormatter const &formatter, SqlMigrationPlanElement const &element)
Name of table in a SQL query, where the table's name is aliased.
std::string_view alias
The alias for the table.
std::weak_ordering operator<=>(AliasedTableName const &) const =default
Three-way comparison operator.
std::string_view tableName
The table name.
SqlQualifiedTableColumnName represents a column name qualified with a table name.
std::string_view tableName
The table name.
std::string_view columnName
The column name.
SqlWildcardType is a placeholder for an explicit wildcard input parameter in a SQL query.