6#include "../SqlQueryFormatter.hpp"
32 std::string condition;
41 std::string_view tableName;
42 std::string_view columnName;
48template <
typename ColumnName>
49std::string MakeSqlColumnName(ColumnName
const& columnName)
51 using namespace std::string_view_literals;
54 if constexpr (std::is_same_v<ColumnName, SqlQualifiedTableColumnName>)
56 output.reserve(columnName.tableName.size() + columnName.columnName.size() + 5);
58 output += columnName.tableName;
60 output += columnName.columnName;
63 else if constexpr (std::is_same_v<ColumnName, SqlRawColumnNameView>)
65 output += columnName.value;
67 else if constexpr (std::is_same_v<ColumnName, SqlWildcardType>)
81std::string MakeEscapedSqlString(T
const& value)
83 std::string escapedValue;
86 for (
auto const ch: value)
99struct [[nodiscard]] SqlSearchCondition
101 std::string tableName;
102 std::string tableAlias;
103 std::string tableJoins;
104 std::string condition;
105 std::vector<SqlVariant>* inputBindings =
nullptr;
114 _referenceTable { referenceTable },
115 _condition { *condition }
121 return Operator(joinColumnName, onOtherColumn,
"AND");
126 return Operator(joinColumnName, onOtherColumn,
"OR");
134 _firstCall = !_firstCall;
136 _condition += std::format(
" {} ", op);
139 _condition += _referenceTable;
140 _condition +=
"\".\"";
141 _condition += joinColumnName;
142 _condition +=
"\" = \"";
143 _condition += onOtherColumn.tableName;
144 _condition +=
"\".\"";
145 _condition += onOtherColumn.columnName;
152 std::string_view _referenceTable;
153 std::string& _condition;
154 bool _firstCall =
true;
162template <
typename Derived>
163class [[nodiscard]] SqlWhereClauseBuilder
167 [[nodiscard]] Derived& And() noexcept;
170 [[nodiscard]] Derived& Or() noexcept;
173 [[nodiscard]] Derived& Not() noexcept;
176 [[nodiscard]] Derived& WhereRaw(std::string_view sqlConditionExpression);
179 template <typename ColumnName, typename T>
180 [[nodiscard]] Derived& Where(ColumnName const& columnName, std::string_view binaryOp, T const& value);
183 template <typename ColumnName, typename SubSelectQuery>
184 requires(std::is_invocable_r_v<std::
string, decltype(&SubSelectQuery::
ToSql), SubSelectQuery const&>)
185 [[nodiscard]] Derived& Where(ColumnName const& columnName, std::string_view binaryOp, SubSelectQuery const& value);
188 template <typename ColumnName, typename T>
189 [[nodiscard]] Derived& OrWhere(ColumnName const& columnName, std::string_view binaryOp, T const& value);
192 template <typename ColumnName, std::
size_t N>
193 Derived& Where(ColumnName const& columnName, std::string_view binaryOp,
char const (&value)[N]);
196 template <typename ColumnName, typename T>
197 [[nodiscard]] Derived& Where(ColumnName const& columnName, T const& value);
200 template <typename ColumnName, typename T>
201 [[nodiscard]] Derived& OrWhere(ColumnName const& columnName, T const& value);
204 template <typename Callable>
205 requires std::invocable<Callable, SqlWhereClauseBuilder<Derived>&>
206 [[nodiscard]] Derived& Where(Callable const& callable);
209 template <typename Callable>
210 requires std::invocable<Callable, SqlWhereClauseBuilder<Derived>&>
211 [[nodiscard]] Derived& OrWhere(Callable const& callable);
214 template <typename ColumnName, std::ranges::input_range InputRange>
215 [[nodiscard]] Derived& WhereIn(ColumnName const& columnName, InputRange const& values);
218 template <typename ColumnName, typename T>
219 [[nodiscard]] Derived& WhereIn(ColumnName const& columnName, std::initializer_list<T> const& values);
222 template <typename ColumnName, typename SubSelectQuery>
223 requires(std::is_invocable_r_v<std::
string, decltype(&SubSelectQuery::
ToSql), SubSelectQuery const&>)
224 [[nodiscard]] Derived& WhereIn(ColumnName const& columnName, SubSelectQuery const& subSelectQuery);
227 template <typename ColumnName>
228 [[nodiscard]] Derived& WhereNull(ColumnName const& columnName);
231 template <typename ColumnName>
232 [[nodiscard]] Derived& WhereNotNull(ColumnName const& columnName);
235 template <typename ColumnName, typename T>
236 [[nodiscard]] Derived& WhereNotEqual(ColumnName const& columnName, T const& value);
239 template <typename ColumnName>
240 [[nodiscard]] Derived& WhereTrue(ColumnName const& columnName);
243 template <typename ColumnName>
244 [[nodiscard]] Derived& WhereFalse(ColumnName const& columnName);
247 template <typename LeftColumn, typename RightColumn>
248 [[nodiscard]] Derived& WhereColumn(LeftColumn const& left, std::string_view binaryOp, RightColumn const& right);
251 [[nodiscard]] Derived& InnerJoin(std::string_view joinTable,
252 std::string_view joinColumnName,
256 [[nodiscard]] Derived& InnerJoin(std::string_view joinTable,
257 std::string_view joinColumnName,
258 std::string_view onMainTableColumn);
261 template <typename OnChainCallable>
263 [[nodiscard]] Derived& InnerJoin(std::string_view joinTable, OnChainCallable const& onClauseBuilder);
276 template <auto LeftField, auto RightField>
277 [[nodiscard]] Derived& InnerJoin();
280 [[nodiscard]] Derived& LeftOuterJoin(std::string_view joinTable,
281 std::string_view joinColumnName,
285 [[nodiscard]] Derived& LeftOuterJoin(std::string_view joinTable,
286 std::string_view joinColumnName,
287 std::string_view onMainTableColumn);
290 template <typename OnChainCallable>
292 [[nodiscard]] Derived& LeftOuterJoin(std::string_view joinTable, OnChainCallable const& onClauseBuilder);
295 [[nodiscard]] Derived& RightOuterJoin(std::string_view joinTable,
296 std::string_view joinColumnName,
300 [[nodiscard]] Derived& RightOuterJoin(std::string_view joinTable,
301 std::string_view joinColumnName,
302 std::string_view onMainTableColumn);
305 template <typename OnChainCallable>
307 [[nodiscard]] Derived& RightOuterJoin(std::string_view joinTable, OnChainCallable const& onClauseBuilder);
310 [[nodiscard]] Derived& FullOuterJoin(std::string_view joinTable,
311 std::string_view joinColumnName,
315 [[nodiscard]] Derived& FullOuterJoin(std::string_view joinTable,
316 std::string_view joinColumnName,
317 std::string_view onMainTableColumn);
320 template <typename OnChainCallable>
322 [[nodiscard]] Derived& FullOuterJoin(std::string_view joinTable, OnChainCallable const& onClauseBuilder);
325 SqlSearchCondition& SearchCondition() noexcept;
328 enum class WhereJunctor : uint8_t
336 WhereJunctor m_nextWhereJunctor = WhereJunctor::Where;
337 bool m_nextIsNot =
false;
339 void AppendWhereJunctor();
341 template <
typename ColumnName>
342 requires(std::same_as<ColumnName, SqlQualifiedTableColumnName> || std::convertible_to<ColumnName, std::string_view>
343 || std::same_as<ColumnName, SqlRawColumnNameView> || std::convertible_to<ColumnName, std::string>)
344 void AppendColumnName(ColumnName
const& columnName);
346 template <
typename LiteralType>
347 void AppendLiteralValue(LiteralType
const& value);
349 template <
typename LiteralType,
typename TargetType>
350 void PopulateLiteralValueInto(LiteralType
const& value, TargetType& target);
352 template <
typename LiteralType>
353 detail::RawSqlCondition PopulateSqlSetExpression(LiteralType
const& values);
355 enum class JoinType : uint8_t
364 [[nodiscard]] Derived& Join(JoinType joinType,
365 std::string_view joinTable,
366 std::string_view joinColumnName,
370 [[nodiscard]] Derived& Join(JoinType joinType,
371 std::string_view joinTable,
372 std::string_view joinColumnName,
373 std::string_view onMainTableColumn);
376 template <
typename OnChainCallable>
377 [[nodiscard]] Derived& Join(JoinType joinType, std::string_view joinTable, OnChainCallable
const& onClauseBuilder);
380enum class SqlResultOrdering : uint8_t
388enum class SelectType : std::uint8_t
399 SelectType selectType = SelectType::Undefined;
402 bool distinct =
false;
403 SqlSearchCondition searchCondition {};
411 size_t limit = (std::numeric_limits<size_t>::max)();
413 [[nodiscard]] LIGHTWEIGHT_API std::string
ToSql()
const;
417template <
typename Derived>
418class [[nodiscard]] SqlBasicSelectQueryBuilder:
public SqlWhereClauseBuilder<Derived>
422 Derived& Distinct() noexcept;
426 SqlResultOrdering ordering = SqlResultOrdering::ASCENDING);
429 Derived& OrderBy(std::string_view columnName, SqlResultOrdering ordering = SqlResultOrdering::ASCENDING);
432 Derived& GroupBy(std::string_view columnName);
434 using ComposedQuery = detail::ComposedQuery;
437 ComposedQuery _query {};
440template <
typename Derived>
441inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::Distinct() noexcept
443 _query.distinct =
true;
444 return static_cast<Derived&
>(*this);
447template <
typename Derived>
448inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::OrderBy(std::string_view columnName,
449 SqlResultOrdering ordering)
451 if (_query.orderBy.empty())
452 _query.orderBy +=
"\n ORDER BY ";
454 _query.orderBy +=
", ";
456 _query.orderBy +=
'"';
457 _query.orderBy += columnName;
458 _query.orderBy +=
'"';
460 if (ordering == SqlResultOrdering::DESCENDING)
461 _query.orderBy +=
" DESC";
462 else if (ordering == SqlResultOrdering::ASCENDING)
463 _query.orderBy +=
" ASC";
465 return static_cast<Derived&
>(*this);
468template <
typename Derived>
469inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::OrderBy(
472 if (_query.orderBy.empty())
473 _query.orderBy +=
"\n ORDER BY ";
475 _query.orderBy +=
", ";
477 _query.orderBy +=
'"';
478 _query.orderBy += columnName.tableName;
479 _query.orderBy +=
"\".\"";
480 _query.orderBy += columnName.columnName;
481 _query.orderBy +=
'"';
483 if (ordering == SqlResultOrdering::DESCENDING)
484 _query.orderBy +=
" DESC";
485 else if (ordering == SqlResultOrdering::ASCENDING)
486 _query.orderBy +=
" ASC";
488 return static_cast<Derived&
>(*this);
491template <
typename Derived>
492inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::GroupBy(std::string_view columnName)
494 if (_query.groupBy.empty())
495 _query.groupBy +=
"\n GROUP BY ";
497 _query.groupBy +=
", ";
499 _query.groupBy +=
'"';
500 _query.groupBy += columnName;
501 _query.groupBy +=
'"';
503 return static_cast<Derived&
>(*this);
506template <
typename Derived>
507inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::And() noexcept
509 m_nextWhereJunctor = WhereJunctor::And;
510 return static_cast<Derived&
>(*this);
513template <
typename Derived>
514inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Or() noexcept
516 m_nextWhereJunctor = WhereJunctor::Or;
517 return static_cast<Derived&
>(*this);
520template <
typename Derived>
521inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Not() noexcept
523 m_nextIsNot = !m_nextIsNot;
524 return static_cast<Derived&
>(*this);
527template <
typename Derived>
528template <
typename ColumnName,
typename T>
529inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Where(ColumnName
const& columnName, T
const& value)
531 if constexpr (detail::OneOf<T, SqlNullType, std::nullopt_t>)
536 return Where(columnName,
"IS NOT", value);
539 return Where(columnName,
"IS", value);
542 return Where(columnName,
"=", value);
545template <
typename Derived>
546template <
typename ColumnName,
typename T>
547inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::OrWhere(ColumnName
const& columnName,
550 return Or().Where(columnName, value);
553template <
typename Derived>
554template <
typename Callable>
555 requires std::invocable<Callable, SqlWhereClauseBuilder<Derived>&>
556inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::OrWhere(Callable
const& callable)
558 return Or().Where(callable);
561template <
typename Derived>
562template <
typename Callable>
563 requires std::invocable<Callable, SqlWhereClauseBuilder<Derived>&>
564inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Where(Callable
const& callable)
566 auto& condition = SearchCondition().condition;
568 auto const originalSize = condition.size();
570 AppendWhereJunctor();
571 m_nextWhereJunctor = WhereJunctor::Null;
574 auto const sizeBeforeCallable = condition.size();
576 (void) callable(*
this);
578 if (condition.size() == sizeBeforeCallable)
579 condition.resize(originalSize);
583 return static_cast<Derived&
>(*this);
586template <
typename Derived>
587template <
typename ColumnName, std::ranges::input_range InputRange>
588inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereIn(ColumnName
const& columnName,
589 InputRange
const& values)
591 return Where(columnName,
"IN", PopulateSqlSetExpression(values));
594template <
typename Derived>
595template <
typename ColumnName,
typename T>
596inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereIn(ColumnName
const& columnName,
597 std::initializer_list<T>
const& values)
599 return Where(columnName,
"IN", PopulateSqlSetExpression(values));
602template <
typename Derived>
603template <
typename ColumnName,
typename SubSelectQuery>
604 requires(std::is_invocable_r_v<std::string,
decltype(&SubSelectQuery::ToSql), SubSelectQuery
const&>)
605inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereIn(ColumnName
const& columnName,
606 SubSelectQuery
const& subSelectQuery)
608 return Where(columnName,
"IN", detail::RawSqlCondition {
"(" + subSelectQuery.ToSql() +
")" });
611template <
typename Derived>
612template <
typename ColumnName>
613inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereNotNull(ColumnName
const& columnName)
615 return Where(columnName,
"IS NOT", detail::RawSqlCondition {
"NULL" });
618template <
typename Derived>
619template <
typename ColumnName>
620inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereNull(ColumnName
const& columnName)
622 return Where(columnName,
"IS", detail::RawSqlCondition {
"NULL" });
625template <
typename Derived>
626template <
typename ColumnName,
typename T>
627inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereNotEqual(ColumnName
const& columnName,
630 if constexpr (detail::OneOf<T, SqlNullType, std::nullopt_t>)
631 return Where(columnName,
"IS NOT", value);
633 return Where(columnName,
"!=", value);
636template <
typename Derived>
637template <
typename ColumnName>
638inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereTrue(ColumnName
const& columnName)
640 return Where(columnName,
"=",
true);
643template <
typename Derived>
644template <
typename ColumnName>
645inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereFalse(ColumnName
const& columnName)
647 return Where(columnName,
"=",
false);
650template <
typename Derived>
651template <
typename LeftColumn,
typename RightColumn>
652inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereColumn(LeftColumn
const& left,
653 std::string_view binaryOp,
654 RightColumn
const& right)
656 AppendWhereJunctor();
658 AppendColumnName(left);
659 SearchCondition().condition +=
' ';
660 SearchCondition().condition += binaryOp;
661 SearchCondition().condition +=
' ';
662 AppendColumnName(right);
664 return static_cast<Derived&
>(*this);
668struct WhereConditionLiteralType
670 constexpr static bool needsQuotes = !std::is_integral_v<T> && !std::is_floating_point_v<T> && !std::same_as<T, bool>
671 && !std::same_as<T, SqlWildcardType>;
674template <
typename Derived>
675template <
typename ColumnName, std::
size_t N>
676inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Where(ColumnName
const& columnName,
677 std::string_view binaryOp,
678 char const (&value)[N])
680 return Where(columnName, binaryOp, std::string_view { value, N - 1 });
683template <
typename Derived>
684template <
typename ColumnName,
typename T>
685inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Where(ColumnName
const& columnName,
686 std::string_view binaryOp,
689 auto& searchCondition = SearchCondition();
691 AppendWhereJunctor();
692 AppendColumnName(columnName);
693 searchCondition.condition +=
' ';
694 searchCondition.condition += binaryOp;
695 searchCondition.condition +=
' ';
696 AppendLiteralValue(value);
698 return static_cast<Derived&
>(*this);
701template <
typename Derived>
702template <
typename ColumnName,
typename SubSelectQuery>
703 requires(std::is_invocable_r_v<std::string,
decltype(&SubSelectQuery::ToSql), SubSelectQuery
const&>)
704inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Where(ColumnName
const& columnName,
705 std::string_view binaryOp,
706 SubSelectQuery
const& value)
708 return Where(columnName, binaryOp, detail::RawSqlCondition {
"(" + value.ToSql() +
")" });
711template <
typename Derived>
712template <
typename ColumnName,
typename T>
713inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::OrWhere(ColumnName
const& columnName,
714 std::string_view binaryOp,
717 return Or().Where(columnName, binaryOp, value);
720template <
typename Derived>
721inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::InnerJoin(std::string_view joinTable,
722 std::string_view joinColumnName,
725 return Join(JoinType::INNER, joinTable, joinColumnName, onOtherColumn);
728template <
typename Derived>
729inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::InnerJoin(std::string_view joinTable,
730 std::string_view joinColumnName,
731 std::string_view onMainTableColumn)
733 return Join(JoinType::INNER, joinTable, joinColumnName, onMainTableColumn);
736template <
typename Derived>
737template <auto LeftField, auto RightField>
738Derived& SqlWhereClauseBuilder<Derived>::InnerJoin()
743 FieldNameOf<LeftField>,
747template <
typename Derived>
748template <
typename OnChainCallable>
749 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
750Derived& SqlWhereClauseBuilder<Derived>::InnerJoin(std::string_view joinTable, OnChainCallable
const& onClauseBuilder)
752 return Join(JoinType::INNER, joinTable, onClauseBuilder);
755template <
typename Derived>
756inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::LeftOuterJoin(
759 return Join(JoinType::LEFT, joinTable, joinColumnName, onOtherColumn);
762template <
typename Derived>
763inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::LeftOuterJoin(std::string_view joinTable,
764 std::string_view joinColumnName,
765 std::string_view onMainTableColumn)
767 return Join(JoinType::LEFT, joinTable, joinColumnName, onMainTableColumn);
770template <
typename Derived>
771template <
typename OnChainCallable>
772 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
773Derived& SqlWhereClauseBuilder<Derived>::LeftOuterJoin(std::string_view joinTable, OnChainCallable
const& onClauseBuilder)
775 return Join(JoinType::LEFT, joinTable, onClauseBuilder);
778template <
typename Derived>
779inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::RightOuterJoin(
782 return Join(JoinType::RIGHT, joinTable, joinColumnName, onOtherColumn);
785template <
typename Derived>
786inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::RightOuterJoin(std::string_view joinTable,
787 std::string_view joinColumnName,
788 std::string_view onMainTableColumn)
790 return Join(JoinType::RIGHT, joinTable, joinColumnName, onMainTableColumn);
793template <
typename Derived>
794template <
typename OnChainCallable>
795 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
796Derived& SqlWhereClauseBuilder<Derived>::RightOuterJoin(std::string_view joinTable, OnChainCallable
const& onClauseBuilder)
798 return Join(JoinType::RIGHT, joinTable, onClauseBuilder);
801template <
typename Derived>
802inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::FullOuterJoin(
805 return Join(JoinType::FULL, joinTable, joinColumnName, onOtherColumn);
808template <
typename Derived>
809inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::FullOuterJoin(std::string_view joinTable,
810 std::string_view joinColumnName,
811 std::string_view onMainTableColumn)
813 return Join(JoinType::FULL, joinTable, joinColumnName, onMainTableColumn);
816template <
typename Derived>
817template <
typename OnChainCallable>
818 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
819Derived& SqlWhereClauseBuilder<Derived>::FullOuterJoin(std::string_view joinTable, OnChainCallable
const& onClauseBuilder)
821 return Join(JoinType::FULL, joinTable, onClauseBuilder);
824template <
typename Derived>
825inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::WhereRaw(std::string_view sqlConditionExpression)
827 AppendWhereJunctor();
829 auto& condition = SearchCondition().condition;
830 condition += sqlConditionExpression;
832 return static_cast<Derived&
>(*this);
835template <
typename Derived>
836inline LIGHTWEIGHT_FORCE_INLINE SqlSearchCondition& SqlWhereClauseBuilder<Derived>::SearchCondition() noexcept
838 return static_cast<Derived*
>(
this)->SearchCondition();
841template <
typename Derived>
842inline LIGHTWEIGHT_FORCE_INLINE
SqlQueryFormatter const& SqlWhereClauseBuilder<Derived>::Formatter() const noexcept
844 return static_cast<Derived const*
>(
this)->Formatter();
847template <
typename Derived>
848inline LIGHTWEIGHT_FORCE_INLINE
void SqlWhereClauseBuilder<Derived>::AppendWhereJunctor()
850 using namespace std::string_view_literals;
852 auto& condition = SearchCondition().condition;
854 switch (m_nextWhereJunctor)
856 case WhereJunctor::Null:
858 case WhereJunctor::Where:
859 condition +=
"\n WHERE "sv;
861 case WhereJunctor::And:
862 condition +=
" AND "sv;
864 case WhereJunctor::Or:
865 condition +=
" OR "sv;
871 condition +=
"NOT "sv;
875 m_nextWhereJunctor = WhereJunctor::And;
878template <
typename Derived>
879template <
typename ColumnName>
880 requires(std::same_as<ColumnName, SqlQualifiedTableColumnName> || std::convertible_to<ColumnName, std::string_view>
881 || std::same_as<ColumnName, SqlRawColumnNameView> || std::convertible_to<ColumnName, std::string>)
882inline LIGHTWEIGHT_FORCE_INLINE
void SqlWhereClauseBuilder<Derived>::AppendColumnName(ColumnName
const& columnName)
884 SearchCondition().condition += detail::MakeSqlColumnName(columnName);
887template <
typename Derived>
888template <
typename LiteralType>
889inline LIGHTWEIGHT_FORCE_INLINE
void SqlWhereClauseBuilder<Derived>::AppendLiteralValue(LiteralType
const& value)
891 auto& searchCondition = SearchCondition();
893 if constexpr (std::is_same_v<LiteralType, SqlQualifiedTableColumnName>
894 || detail::OneOf<LiteralType, SqlNullType, std::nullopt_t> || std::is_same_v<LiteralType, SqlWildcardType>
895 || std::is_same_v<LiteralType, detail::RawSqlCondition>)
897 PopulateLiteralValueInto(value, searchCondition.condition);
899 else if (searchCondition.inputBindings)
901 searchCondition.condition +=
'?';
902 searchCondition.inputBindings->emplace_back(value);
904 else if constexpr (std::is_same_v<LiteralType, bool>)
906 searchCondition.condition += Formatter().BooleanLiteral(value);
908 else if constexpr (!WhereConditionLiteralType<LiteralType>::needsQuotes)
910 searchCondition.condition += std::format(
"{}", value);
914 searchCondition.condition += detail::MakeEscapedSqlString(std::format(
"{}", value));
918template <
typename Derived>
919template <
typename LiteralType,
typename TargetType>
920inline LIGHTWEIGHT_FORCE_INLINE
void SqlWhereClauseBuilder<Derived>::PopulateLiteralValueInto(LiteralType
const& value,
923 if constexpr (std::is_same_v<LiteralType, SqlQualifiedTableColumnName>)
926 target += value.tableName;
928 target += value.columnName;
931 else if constexpr (detail::OneOf<LiteralType, SqlNullType, std::nullopt_t>)
935 else if constexpr (std::is_same_v<LiteralType, SqlWildcardType>)
939 else if constexpr (std::is_same_v<LiteralType, detail::RawSqlCondition>)
941 target += value.condition;
943 else if constexpr (std::is_same_v<LiteralType, bool>)
945 target += Formatter().BooleanLiteral(value);
947 else if constexpr (!WhereConditionLiteralType<LiteralType>::needsQuotes)
949 target += std::format(
"{}", value);
953 target += detail::MakeEscapedSqlString(std::format(
"{}", value));
957template <
typename Derived>
958template <
typename LiteralType>
959detail::RawSqlCondition SqlWhereClauseBuilder<Derived>::PopulateSqlSetExpression(LiteralType
const& values)
961 using namespace std::string_view_literals;
962 std::ostringstream fragment;
964 for (
auto const&& [index, value]: values | std::views::enumerate)
969 std::string valueString;
970 PopulateLiteralValueInto(value, valueString);
971 fragment << valueString;
974 return detail::RawSqlCondition { fragment.str() };
977template <
typename Derived>
978inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Join(JoinType joinType,
979 std::string_view joinTable,
980 std::string_view joinColumnName,
983 static constexpr std::array<std::string_view, 4> JoinTypeStrings = {
990 SearchCondition().tableJoins += std::format(
"\n"
991 R
"( {0} JOIN "{1}" ON "{1}"."{2}" = "{3}"."{4}")",
992 JoinTypeStrings[static_cast<std::size_t
>(joinType)],
995 onOtherColumn.tableName,
996 onOtherColumn.columnName);
997 return static_cast<Derived&
>(*this);
1000template <
typename Derived>
1001inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Join(JoinType joinType,
1002 std::string_view joinTable,
1003 std::string_view joinColumnName,
1004 std::string_view onMainTableColumn)
1006 return Join(joinType,
1012template <
typename Derived>
1013template <
typename Callable>
1014inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlWhereClauseBuilder<Derived>::Join(JoinType joinType,
1015 std::string_view joinTable,
1016 Callable
const& onClauseBuilder)
1018 static constexpr std::array<std::string_view, 4> JoinTypeStrings = {
1025 size_t const originalSize = SearchCondition().tableJoins.size();
1026 SearchCondition().tableJoins +=
1027 std::format(
"\n {0} JOIN \"{1}\" ON ", JoinTypeStrings[
static_cast<std::size_t
>(joinType)], joinTable);
1028 size_t const sizeBefore = SearchCondition().tableJoins.size();
1030 size_t const sizeAfter = SearchCondition().tableJoins.size();
1031 if (sizeBefore == sizeAfter)
1032 SearchCondition().tableJoins.resize(originalSize);
1034 return static_cast<Derived&
>(*this);
Query builder for building JOIN conditions.
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)
SqlQualifiedTableColumnName represents a column name qualified with a table name.
SqlWildcardType is a placeholder for an explicit wildcard input parameter in a SQL query.