291 [[nodiscard]] Derived& FullOuterJoin(std::string_view joinTable, OnChainCallable const& onClauseBuilder);
294 SqlSearchCondition& SearchCondition() noexcept;
297 enum class WhereJunctor : uint8_t
305 WhereJunctor m_nextWhereJunctor = WhereJunctor::Where;
306 bool m_nextIsNot =
false;
308 void AppendWhereJunctor();
310 template <
typename ColumnName>
311 requires(std::same_as<ColumnName, SqlQualifiedTableColumnName>
312 || std::convertible_to<ColumnName, std::string_view> || std::same_as<ColumnName, SqlRawColumnNameView>
313 || std::convertible_to<ColumnName, std::string>)
314 void AppendColumnName(ColumnName
const& columnName);
316 template <
typename LiteralType>
317 void AppendLiteralValue(LiteralType
const& value);
319 enum class JoinType : uint8_t
328 [[nodiscard]] Derived& Join(JoinType joinType,
329 std::string_view joinTable,
330 std::string_view joinColumnName,
334 [[nodiscard]] Derived& Join(JoinType joinType,
335 std::string_view joinTable,
336 std::string_view joinColumnName,
337 std::string_view onMainTableColumn);
340 template <
typename OnChainCallable>
341 [[nodiscard]] Derived& Join(JoinType joinType, std::string_view joinTable, OnChainCallable
const& onClauseBuilder);
344enum class SqlResultOrdering : uint8_t
352enum class SelectType : std::uint8_t
363 SelectType selectType = SelectType::Undefined;
366 bool distinct =
false;
367 SqlSearchCondition searchCondition {};
375 size_t limit = (std::numeric_limits<size_t>::max)();
377 [[nodiscard]] LIGHTWEIGHT_API std::string
ToSql()
const;
381template <
typename Derived>
386 Derived& Distinct() noexcept;
390 SqlResultOrdering ordering = SqlResultOrdering::ASCENDING);
393 Derived& OrderBy(std::string_view columnName, SqlResultOrdering ordering = SqlResultOrdering::ASCENDING);
396 Derived& GroupBy(std::string_view columnName);
398 using ComposedQuery = detail::ComposedQuery;
401 ComposedQuery _query {};
404template <
typename Derived>
405inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::Distinct() noexcept
407 _query.distinct =
true;
408 return static_cast<Derived&
>(*this);
411template <
typename Derived>
412inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::OrderBy(std::string_view columnName,
413 SqlResultOrdering ordering)
415 if (_query.orderBy.empty())
416 _query.orderBy +=
"\n ORDER BY ";
418 _query.orderBy +=
", ";
420 _query.orderBy +=
'"';
421 _query.orderBy += columnName;
422 _query.orderBy +=
'"';
424 if (ordering == SqlResultOrdering::DESCENDING)
425 _query.orderBy +=
" DESC";
426 else if (ordering == SqlResultOrdering::ASCENDING)
427 _query.orderBy +=
" ASC";
429 return static_cast<Derived&
>(*this);
432template <
typename Derived>
433inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::OrderBy(
436 if (_query.orderBy.empty())
437 _query.orderBy +=
"\n ORDER BY ";
439 _query.orderBy +=
", ";
441 _query.orderBy +=
'"';
442 _query.orderBy += columnName.tableName;
443 _query.orderBy +=
"\".\"";
444 _query.orderBy += columnName.columnName;
445 _query.orderBy +=
'"';
447 if (ordering == SqlResultOrdering::DESCENDING)
448 _query.orderBy +=
" DESC";
449 else if (ordering == SqlResultOrdering::ASCENDING)
450 _query.orderBy +=
" ASC";
452 return static_cast<Derived&
>(*this);
455template <
typename Derived>
456inline LIGHTWEIGHT_FORCE_INLINE Derived& SqlBasicSelectQueryBuilder<Derived>::GroupBy(std::string_view columnName)
458 if (_query.groupBy.empty())
459 _query.groupBy +=
"\n GROUP BY ";
461 _query.groupBy +=
", ";
463 _query.groupBy +=
'"';
464 _query.groupBy += columnName;
465 _query.groupBy +=
'"';
467 return static_cast<Derived&
>(*this);
470template <
typename Derived>
473 m_nextWhereJunctor = WhereJunctor::And;
474 return static_cast<Derived&
>(*this);
477template <
typename Derived>
480 m_nextWhereJunctor = WhereJunctor::Or;
481 return static_cast<Derived&
>(*this);
484template <
typename Derived>
487 m_nextIsNot = !m_nextIsNot;
488 return static_cast<Derived&
>(*this);
491template <
typename Derived>
492template <
typename ColumnName,
typename T>
496 if constexpr (detail::OneOf<T, SqlNullType, std::nullopt_t>)
501 return Where(columnName,
"IS NOT", value);
504 return Where(columnName,
"IS", value);
507 return Where(columnName,
"=", value);
510template <
typename Derived>
511template <
typename ColumnName,
typename T>
515 return Or().Where(columnName, value);
518template <
typename Derived>
519template <
typename Callable>
520 requires std::invocable<Callable, SqlWhereClauseBuilder<Derived>&>
523 return Or().Where(callable);
526template <
typename Derived>
527template <
typename Callable>
528 requires std::invocable<Callable, SqlWhereClauseBuilder<Derived>&>
531 auto& condition = SearchCondition().condition;
533 auto const originalSize = condition.size();
535 AppendWhereJunctor();
536 m_nextWhereJunctor = WhereJunctor::Null;
539 auto const sizeBeforeCallable = condition.size();
541 (void) callable(*
this);
543 if (condition.size() == sizeBeforeCallable)
544 condition.resize(originalSize);
548 return static_cast<Derived&
>(*this);
554inline LIGHTWEIGHT_FORCE_INLINE RawSqlCondition PopulateSqlSetExpression(
auto const& values)
556 using namespace std::string_view_literals;
557 std::ostringstream fragment;
559 for (
auto const&& [index, value]: values | std::views::enumerate)
566 return RawSqlCondition { fragment.str() };
571template <
typename Derived>
572template <
typename ColumnName, std::ranges::input_range InputRange>
574 InputRange
const& values)
576 return Where(columnName,
"IN", detail::PopulateSqlSetExpression(values));
579template <
typename Derived>
580template <
typename ColumnName,
typename T>
582 std::initializer_list<T>
const& values)
584 return Where(columnName,
"IN", detail::PopulateSqlSetExpression(values));
587template <
typename Derived>
588template <
typename ColumnName,
typename SubSelectQuery>
589 requires(std::is_invocable_r_v<std::string,
decltype(&SubSelectQuery::ToSql), SubSelectQuery
const&>)
591 SubSelectQuery
const& subSelectQuery)
593 return Where(columnName,
"IN", detail::RawSqlCondition {
"(" + subSelectQuery.ToSql() +
")" });
596template <
typename Derived>
597template <
typename ColumnName>
600 return Where(columnName,
"IS NOT", detail::RawSqlCondition {
"NULL" });
603template <
typename Derived>
604template <
typename ColumnName>
607 return Where(columnName,
"IS", detail::RawSqlCondition {
"NULL" });
610template <
typename Derived>
611template <
typename ColumnName,
typename T>
615 if constexpr (detail::OneOf<T, SqlNullType, std::nullopt_t>)
616 return Where(columnName,
"IS NOT", value);
618 return Where(columnName,
"!=", value);
621template <
typename Derived>
622template <
typename ColumnName>
625 return Where(columnName,
"=",
true);
628template <
typename Derived>
629template <
typename ColumnName>
632 return Where(columnName,
"=",
false);
635template <
typename Derived>
636template <
typename LeftColumn,
typename RightColumn>
638 std::string_view binaryOp,
639 RightColumn
const& right)
641 AppendWhereJunctor();
643 AppendColumnName(left);
644 SearchCondition().condition +=
' ';
645 SearchCondition().condition += binaryOp;
646 SearchCondition().condition +=
' ';
647 AppendColumnName(right);
649 return static_cast<Derived&
>(*this);
653struct WhereConditionLiteralType
655 constexpr static bool needsQuotes = !std::is_integral_v<T> && !std::is_floating_point_v<T> && !std::same_as<T, bool>
656 && !std::same_as<T, SqlWildcardType>;
659template <
typename Derived>
660template <
typename ColumnName, std::
size_t N>
662 std::string_view binaryOp,
663 char const (&value)[N])
665 return Where(columnName, binaryOp, std::string_view { value, N - 1 });
668template <
typename Derived>
669template <
typename ColumnName,
typename T>
671 std::string_view binaryOp,
674 auto& searchCondition = SearchCondition();
676 AppendWhereJunctor();
677 AppendColumnName(columnName);
678 searchCondition.condition +=
' ';
679 searchCondition.condition += binaryOp;
680 searchCondition.condition +=
' ';
681 AppendLiteralValue(value);
683 return static_cast<Derived&
>(*this);
686template <
typename Derived>
687template <
typename ColumnName,
typename SubSelectQuery>
688 requires(std::is_invocable_r_v<std::string,
decltype(&SubSelectQuery::ToSql), SubSelectQuery
const&>)
690 std::string_view binaryOp,
691 SubSelectQuery
const& value)
693 return Where(columnName, binaryOp, detail::RawSqlCondition {
"(" + value.ToSql() +
")" });
696template <
typename Derived>
697template <
typename ColumnName,
typename T>
699 std::string_view binaryOp,
702 return Or().
Where(columnName, binaryOp, value);
705template <
typename Derived>
709 return Join(JoinType::INNER, joinTable, joinColumnName, onOtherColumn);
712template <
typename Derived>
714 std::string_view joinColumnName,
715 std::string_view onMainTableColumn)
717 return Join(JoinType::INNER, joinTable, joinColumnName, onMainTableColumn);
720template <
typename Derived>
721template <
typename OnChainCallable>
722 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
725 return Join(JoinType::INNER, joinTable, onClauseBuilder);
728template <
typename Derived>
732 return Join(JoinType::LEFT, joinTable, joinColumnName, onOtherColumn);
735template <
typename Derived>
737 std::string_view joinTable, std::string_view joinColumnName, std::string_view onMainTableColumn)
739 return Join(JoinType::LEFT, joinTable, joinColumnName, onMainTableColumn);
742template <
typename Derived>
743template <
typename OnChainCallable>
744 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
746 OnChainCallable
const& onClauseBuilder)
748 return Join(JoinType::LEFT, joinTable, onClauseBuilder);
751template <
typename Derived>
755 return Join(JoinType::RIGHT, joinTable, joinColumnName, onOtherColumn);
758template <
typename Derived>
760 std::string_view joinTable, std::string_view joinColumnName, std::string_view onMainTableColumn)
762 return Join(JoinType::RIGHT, joinTable, joinColumnName, onMainTableColumn);
765template <
typename Derived>
766template <
typename OnChainCallable>
767 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
769 OnChainCallable
const& onClauseBuilder)
771 return Join(JoinType::RIGHT, joinTable, onClauseBuilder);
774template <
typename Derived>
778 return Join(JoinType::FULL, joinTable, joinColumnName, onOtherColumn);
781template <
typename Derived>
783 std::string_view joinTable, std::string_view joinColumnName, std::string_view onMainTableColumn)
785 return Join(JoinType::FULL, joinTable, joinColumnName, onMainTableColumn);
788template <
typename Derived>
789template <
typename OnChainCallable>
790 requires std::invocable<OnChainCallable, SqlJoinConditionBuilder>
792 OnChainCallable
const& onClauseBuilder)
794 return Join(JoinType::FULL, joinTable, onClauseBuilder);