#pragma once #include "spacetimedb/query_builder/expr.h" #include "spacetimedb/query_builder/join.h" #include "spacetimedb/query_builder/table.h" #include #include #include #include namespace SpacetimeDB { template using Query = query_builder::RawQuery; namespace detail { template struct NamedQuerySourceTag { using type = TRow; const char* __table_name_internal; }; struct NotAQuerySourceTag {}; template struct query_source_row_type {}; template concept HasQuerySourceRowType = requires { typename query_source_row_type>::type; }; template using query_source_row_type_t = typename query_source_row_type>::type; template requires query_builder::QueryBuilderReturn struct query_source_row_type { using type = query_builder::query_row_type_t; }; template struct query_source_row_type> { using type = TRow; }; template struct query_source_row_type> { using type = TRow; }; template constexpr auto MakeQuerySourceTag(const char* source_name) { if constexpr (HasQuerySourceRowType) { return NamedQuerySourceTag>{source_name}; } else { return NotAQuerySourceTag{}; } } template constexpr const char* GetQuerySourceName(const TSourceTag& tag) { return tag.__table_name_internal; } } // namespace detail class QueryBuilder { public: template [[nodiscard]] constexpr query_builder::Table table(const char* table_name, TCols cols, TIxCols ix_cols) const { return query_builder::Table(table_name, std::move(cols), std::move(ix_cols)); } template [[nodiscard]] constexpr auto table(TTableTag tag) const -> query_builder::Table< typename std::remove_cvref_t::type, decltype(query_builder::HasCols::type>::get(std::declval())), decltype(query_builder::HasIxCols::type>::get(std::declval()))> { using TRow = typename std::remove_cvref_t::type; const char* table_name = detail::GetQuerySourceName(tag); return table( table_name, query_builder::HasCols::get(table_name), query_builder::HasIxCols::get(table_name)); } template [[nodiscard]] constexpr auto operator[](TTableTag tag) const -> decltype(table(tag)) { return table(tag); } }; } // namespace SpacetimeDB