Added the ability to add subqueries in select_from (#39)

This commit is contained in:
Dr. Patrick Urbanke (劉自成)
2025-08-09 00:36:53 +02:00
committed by GitHub
parent ad1cae049b
commit f536efbde9
19 changed files with 894 additions and 172 deletions

View File

@@ -18,6 +18,8 @@
namespace sqlgen::dynamic {
struct SelectFrom {
using TableOrQueryType = rfl::Variant<Table, Ref<SelectFrom>>;
struct Field {
Operation val;
std::optional<std::string> as;
@@ -25,12 +27,12 @@ struct SelectFrom {
struct Join {
JoinType how;
rfl::Variant<Table, Ref<SelectFrom>> table_or_query;
TableOrQueryType table_or_query;
std::string alias;
std::optional<Condition> on;
};
Table table;
TableOrQueryType table_or_query;
std::vector<Field> fields;
std::optional<std::string> alias = std::nullopt;
std::optional<std::vector<Join>> joins = std::nullopt;

View File

@@ -19,6 +19,7 @@
#include "order_by.hpp"
#include "to.hpp"
#include "transpilation/Join.hpp"
#include "transpilation/TableWrapper.hpp"
#include "transpilation/fields_to_named_tuple_t.hpp"
#include "transpilation/group_by_t.hpp"
#include "transpilation/order_by_t.hpp"
@@ -31,19 +32,20 @@
namespace sqlgen {
template <class TableTupleType, class AliasType, class FieldsType,
class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType, class ContainerType,
class Connection>
class TableOrQueryType, class JoinsType, class WhereType,
class GroupByType, class OrderByType, class LimitType,
class ContainerType, class Connection>
requires is_connection<Connection>
auto select_from_impl(const Ref<Connection>& _conn, const FieldsType& _fields,
const TableOrQueryType& _table_or_query,
const JoinsType& _joins, const WhereType& _where,
const LimitType& _limit) {
if constexpr (internal::is_range_v<ContainerType>) {
const auto query =
transpilation::to_select_from<TableTupleType, AliasType, FieldsType,
JoinsType, WhereType, GroupByType,
OrderByType, LimitType>(_fields, _joins,
_where, _limit);
TableOrQueryType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType>(
_fields, _table_or_query, _joins, _where, _limit);
return _conn->read(query).transform(
[](auto&& _it) { return ContainerType(_it); });
@@ -65,36 +67,40 @@ auto select_from_impl(const Ref<Connection>& _conn, const FieldsType& _fields,
using RangeType = Range<
transpilation::fields_to_named_tuple_t<TableTupleType, FieldsType>>;
return select_from_impl<TableTupleType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType,
RangeType>(_conn, _fields, _joins, _where, _limit)
return select_from_impl<TableTupleType, AliasType, FieldsType,
TableOrQueryType, JoinsType, WhereType, GroupByType,
OrderByType, LimitType, RangeType>(
_conn, _fields, _table_or_query, _joins, _where, _limit)
.and_then(to_container);
}
}
template <class TableTupleType, class AliasType, class FieldsType,
class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType, class ContainerType,
class Connection>
class TableOrQueryType, class JoinsType, class WhereType,
class GroupByType, class OrderByType, class LimitType,
class ContainerType, class Connection>
requires is_connection<Connection>
auto select_from_impl(const Result<Ref<Connection>>& _res,
const FieldsType& _fields, const JoinsType& _joins,
const WhereType& _where, const LimitType& _limit) {
const FieldsType& _fields,
const TableOrQueryType& _table_or_query,
const JoinsType& _joins, const WhereType& _where,
const LimitType& _limit) {
return _res.and_then([&](const auto& _conn) {
return select_from_impl<TableTupleType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType,
ContainerType>(_conn, _joins, _where, _limit);
return select_from_impl<TableTupleType, AliasType, FieldsType,
TableOrQueryType, JoinsType, WhereType, GroupByType,
OrderByType, LimitType, ContainerType>(
_conn, _table_or_query, _joins, _where, _limit);
});
}
template <class StructType, class AliasType, class FieldsType,
template <class TableOrQueryType, class AliasType, class FieldsType,
class JoinsType = Nothing, class WhereType = Nothing,
class GroupByType = Nothing, class OrderByType = Nothing,
class LimitType = Nothing, class ToType = Nothing>
struct SelectFrom {
auto operator()(const auto& _conn) const {
using TableTupleType =
transpilation::table_tuple_t<StructType, AliasType, JoinsType>;
transpilation::table_tuple_t<TableOrQueryType, AliasType, JoinsType>;
if constexpr (std::is_same_v<ToType, Nothing> ||
std::ranges::input_range<std::remove_cvref_t<ToType>>) {
@@ -103,10 +109,10 @@ struct SelectFrom {
Range<transpilation::fields_to_named_tuple_t<
TableTupleType, FieldsType>>,
ToType>;
return select_from_impl<TableTupleType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType,
ContainerType>(_conn, fields_, joins_, where_,
limit_);
return select_from_impl<
TableTupleType, AliasType, FieldsType, TableOrQueryType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType, ContainerType>(
_conn, fields_, from_, joins_, where_, limit_);
} else {
const auto extract_result = [](auto&& _vec) -> Result<ToType> {
@@ -119,19 +125,20 @@ struct SelectFrom {
return std::move(_vec[0]);
};
return select_from_impl<TableTupleType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType,
return select_from_impl<TableTupleType, AliasType, FieldsType,
TableOrQueryType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType,
std::vector<std::remove_cvref_t<ToType>>>(
_conn, fields_, joins_, where_, limit_)
_conn, fields_, from_, joins_, where_, limit_)
.and_then(extract_result);
}
}
template <class TableOrQueryType, class ConditionType,
template <class OtherTableOrQueryType, class ConditionType,
rfl::internal::StringLiteral _alias>
friend auto operator|(
const SelectFrom& _s,
const transpilation::Join<TableOrQueryType, ConditionType, _alias>&
const transpilation::Join<OtherTableOrQueryType, ConditionType, _alias>&
_join) {
static_assert(std::is_same_v<WhereType, Nothing>,
"You cannot call where(...) before a join.");
@@ -146,23 +153,25 @@ struct SelectFrom {
if constexpr (std::is_same_v<JoinsType, Nothing>) {
using NewJoinsType = rfl::Tuple<
transpilation::Join<TableOrQueryType, ConditionType, _alias>>;
transpilation::Join<OtherTableOrQueryType, ConditionType, _alias>>;
return SelectFrom<StructType, AliasType, FieldsType, NewJoinsType,
return SelectFrom<TableOrQueryType, AliasType, FieldsType, NewJoinsType,
WhereType, GroupByType, OrderByType, LimitType, ToType>{
.fields_ = _s.fields_, .joins_ = NewJoinsType(_join)};
.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = NewJoinsType(_join)};
} else {
using TupleType = rfl::Tuple<
transpilation::Join<TableOrQueryType, ConditionType, _alias>>;
transpilation::Join<OtherTableOrQueryType, ConditionType, _alias>>;
const auto joins = rfl::tuple_cat(_s.joins_, TupleType(_join));
using NewJoinsType = std::remove_cvref_t<decltype(joins)>;
return SelectFrom<StructType, AliasType, FieldsType, NewJoinsType,
return SelectFrom<TableOrQueryType, AliasType, FieldsType, NewJoinsType,
WhereType, GroupByType, OrderByType, LimitType, ToType>{
.fields_ = _s.fields_, .joins_ = joins};
.fields_ = _s.fields_, .from_ = _s.from_, .joins_ = joins};
}
}
@@ -180,10 +189,12 @@ struct SelectFrom {
"You cannot call limit(...) before where(...).");
static_assert(std::is_same_v<ToType, Nothing>,
"You cannot call to<...> before where(...).");
return SelectFrom<StructType, AliasType, FieldsType, JoinsType,
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
ConditionType, GroupByType, OrderByType, LimitType,
ToType>{
.fields_ = _s.fields_, .joins_ = _s.joins_, .where_ = _where.condition};
ToType>{.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
.where_ = _where.condition};
}
template <class... ColTypes>
@@ -200,11 +211,14 @@ struct SelectFrom {
"You cannot call to<...> before group_by(...).");
static_assert(sizeof...(ColTypes) != 0,
"You must assign at least one column to group_by.");
return SelectFrom<
StructType, AliasType, FieldsType, JoinsType, WhereType,
transpilation::group_by_t<StructType, typename ColTypes::ColType...>,
OrderByType, LimitType, ToType>{
.fields_ = _s.fields_, .joins_ = _s.joins_, .where_ = _s.where_};
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType,
transpilation::group_by_t<TableOrQueryType,
typename ColTypes::ColType...>,
OrderByType, LimitType, ToType>{.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
.where_ = _s.where_};
}
template <class... ColTypes>
@@ -221,23 +235,27 @@ struct SelectFrom {
"You must assign at least one column to order_by.");
using TableTupleType =
transpilation::table_tuple_t<StructType, AliasType, JoinsType>;
transpilation::table_tuple_t<TableOrQueryType, AliasType, JoinsType>;
using NewOrderByType = transpilation::order_by_t<
TableTupleType, GroupByType,
typename std::remove_cvref_t<ColTypes>::ColType...>;
return SelectFrom<StructType, AliasType, FieldsType, JoinsType, WhereType,
GroupByType, NewOrderByType, LimitType, ToType>{
.fields_ = _s.fields_, .joins_ = _s.joins_, .where_ = _s.where_};
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, NewOrderByType, LimitType,
ToType>{.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
.where_ = _s.where_};
}
friend auto operator|(const SelectFrom& _s, const Limit& _limit) {
static_assert(std::is_same_v<LimitType, Nothing>,
"You cannot call limit twice.");
return SelectFrom<StructType, AliasType, FieldsType, JoinsType, WhereType,
GroupByType, OrderByType, Limit, ToType>{
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, Limit, ToType>{
.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
.where_ = _s.where_,
.limit_ = _limit};
@@ -247,16 +265,19 @@ struct SelectFrom {
friend auto operator|(const SelectFrom& _s, const To<NewToType>&) {
static_assert(std::is_same_v<ToType, Nothing>,
"You cannot call to<...> twice.");
return SelectFrom<StructType, AliasType, FieldsType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType, NewToType>{
.fields_ = _s.fields_,
.joins_ = _s.joins_,
.where_ = _s.where_,
.limit_ = _s.limit_};
return SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType,
NewToType>{.fields_ = _s.fields_,
.from_ = _s.from_,
.joins_ = _s.joins_,
.where_ = _s.where_,
.limit_ = _s.limit_};
}
FieldsType fields_;
TableOrQueryType from_;
JoinsType joins_;
WhereType where_;
@@ -266,62 +287,66 @@ struct SelectFrom {
namespace transpilation {
template <class StructType, class AliasType, class FieldsType, class JoinsType,
class... Args>
template <class TableOrQueryType, class AliasType, class FieldsType,
class JoinsType, class... Args>
struct ExtractTable<
SelectFrom<StructType, AliasType, FieldsType, JoinsType, Args...>> {
using TableTupleType = table_tuple_t<StructType, AliasType, JoinsType>;
SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType, Args...>> {
using TableTupleType = table_tuple_t<TableOrQueryType, AliasType, JoinsType>;
using Type = fields_to_named_tuple_t<TableTupleType, FieldsType>;
};
template <class TableTupleType, class StructType, class AliasType,
class FieldsType, class JoinsType, class WhereType, class GroupByType,
template <class TableOrQueryType, class AliasType, class FieldsType,
class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType, class ToType>
struct ToJoin<TableTupleType, SelectFrom<StructType, AliasType, FieldsType,
JoinsType, WhereType, GroupByType,
OrderByType, LimitType, ToType>> {
template <class ConditionType, rfl::internal::StringLiteral _alias>
dynamic::Join operator()(
const transpilation::Join<
SelectFrom<StructType, AliasType, FieldsType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType, ToType>,
ConditionType, _alias>& _join) {
const auto& query = _join.table_or_query;
using NestedTableTupleType =
table_tuple_t<StructType, AliasType, JoinsType>;
return dynamic::Join{
.how = _join.how,
.table_or_query = Ref<dynamic::SelectFrom>::make(
transpilation::to_select_from<NestedTableTupleType, AliasType,
FieldsType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType>(
query.fields_, query.joins_, query.where_, query.limit_)),
.alias = Literal<_alias>().str(),
.on = to_condition<TableTupleType>(_join.on)};
struct ToTableOrQuery<
SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType, ToType>> {
dynamic::SelectFrom::TableOrQueryType operator()(const auto& _query) {
using TableTupleType =
table_tuple_t<TableOrQueryType, AliasType, JoinsType>;
return Ref<dynamic::SelectFrom>::make(
transpilation::to_select_from<TableTupleType, AliasType, FieldsType,
TableOrQueryType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType>(
_query.fields_, _query.from_, _query.joins_, _query.where_,
_query.limit_));
}
};
} // namespace transpilation
template <class StructType, class... FieldTypes>
template <class TableType, class... FieldTypes>
inline auto select_from(const FieldTypes&... _fields) {
using FieldsType =
rfl::Tuple<typename internal::GetColType<FieldTypes>::Type...>;
return SelectFrom<StructType, Nothing, FieldsType>{
return SelectFrom<transpilation::TableWrapper<TableType>, Nothing,
FieldsType>{
.fields_ =
FieldsType(internal::GetColType<FieldTypes>::get_value(_fields)...)};
FieldsType(internal::GetColType<FieldTypes>::get_value(_fields)...),
.from_ = transpilation::TableWrapper<TableType>{}};
}
template <class StructType, rfl::internal::StringLiteral _alias,
template <class TableType, rfl::internal::StringLiteral _alias,
class... FieldTypes>
inline auto select_from(const FieldTypes&... _fields) {
using FieldsType =
rfl::Tuple<typename internal::GetColType<FieldTypes>::Type...>;
return SelectFrom<StructType, Literal<_alias>, FieldsType>{
return SelectFrom<transpilation::TableWrapper<TableType>, Literal<_alias>,
FieldsType>{
.fields_ =
FieldsType(internal::GetColType<FieldTypes>::get_value(_fields)...)};
FieldsType(internal::GetColType<FieldTypes>::get_value(_fields)...),
.from_ = transpilation::TableWrapper<TableType>{}};
}
template <rfl::internal::StringLiteral _alias, class QueryType,
class... FieldTypes>
inline auto select_from(const QueryType& _query, const FieldTypes&... _fields) {
using FieldsType =
rfl::Tuple<typename internal::GetColType<FieldTypes>::Type...>;
return SelectFrom<QueryType, Literal<_alias>, FieldsType>{
.fields_ =
FieldsType(internal::GetColType<FieldTypes>::get_value(_fields)...),
.from_ = _query};
}
} // namespace sqlgen

View File

@@ -8,6 +8,7 @@
#include "../Literal.hpp"
#include "../dynamic/JoinType.hpp"
#include "TableWrapper.hpp"
namespace sqlgen::transpilation {
@@ -45,6 +46,11 @@ struct GetTableType<Literal<_alias>,
"Alias could not be identified.");
};
template <rfl::internal::StringLiteral _alias, class T>
struct GetTableType<Literal<_alias>, TableWrapper<T>> {
using TableType = T;
};
template <rfl::internal::StringLiteral _alias, class T>
struct GetTableType<Literal<_alias>, T> {
using TableType = T;
@@ -60,6 +66,11 @@ struct GetTableType<std::integral_constant<size_t, _i>,
"Alias could not be identified.");
};
template <size_t _i, class T>
struct GetTableType<std::integral_constant<size_t, _i>, TableWrapper<T>> {
using TableType = T;
};
template <size_t _i, class T>
struct GetTableType<std::integral_constant<size_t, _i>, T> {
using TableType = T;

View File

@@ -42,7 +42,7 @@ dynamic::SelectFrom read_to_select_from(const WhereType& _where = WhereType{},
}));
return dynamic::SelectFrom{
.table =
.table_or_query =
dynamic::Table{.name = get_tablename<T>(), .schema = get_schema<T>()},
.fields = fields,
.where = to_condition<std::remove_cvref_t<T>>(_where),

View File

@@ -11,18 +11,18 @@
namespace sqlgen::transpilation {
template <class StructType, class AliasType, class JoinsType>
template <class TableOrQueryType, class AliasType, class JoinsType>
struct TableTupleType;
template <class StructType, class AliasType>
struct TableTupleType<StructType, AliasType, Nothing> {
using Type = StructType;
template <class TableOrQueryType, class AliasType>
struct TableTupleType<TableOrQueryType, AliasType, Nothing> {
using Type = TableOrQueryType;
};
template <class StructType, class AliasType, class... JoinTypes>
struct TableTupleType<StructType, AliasType, rfl::Tuple<JoinTypes...>> {
template <class TableOrQueryType, class AliasType, class... JoinTypes>
struct TableTupleType<TableOrQueryType, AliasType, rfl::Tuple<JoinTypes...>> {
using Type = rfl::Tuple<
std::pair<extract_table_t<StructType>, AliasType>,
std::pair<extract_table_t<TableOrQueryType>, AliasType>,
std::pair<extract_table_t<typename JoinTypes::TableOrQueryType>,
typename JoinTypes::Alias>...>;
static_assert(
@@ -30,9 +30,9 @@ struct TableTupleType<StructType, AliasType, rfl::Tuple<JoinTypes...>> {
"Your SELECT FROM query cannot contain duplicate aliases.");
};
template <class StructType, class AliasType, class JoinsType>
template <class TableOrQueryType, class AliasType, class JoinsType>
using table_tuple_t =
typename TableTupleType<std::remove_cvref_t<StructType>,
typename TableTupleType<std::remove_cvref_t<TableOrQueryType>,
std::remove_cvref_t<AliasType>,
std::remove_cvref_t<JoinsType>>::Type;

View File

@@ -19,6 +19,19 @@ namespace sqlgen::transpilation {
template <class TableTupleType, class T>
struct ToJoin;
template <class TableTupleType, class QueryType>
struct ToJoin {
template <class ConditionType, rfl::internal::StringLiteral _alias>
dynamic::Join operator()(
const transpilation::Join<QueryType, ConditionType, _alias>& _join) {
return dynamic::Join{
.how = _join.how,
.table_or_query = to_table_or_query(_join.table_or_query),
.alias = Literal<_alias>().str(),
.on = to_condition<TableTupleType>(_join.on)};
}
};
template <class TableTupleType, class TableType>
struct ToJoin<TableTupleType, TableWrapper<TableType>> {
template <class ConditionType, rfl::internal::StringLiteral _alias>

View File

@@ -15,11 +15,10 @@
#include "../dynamic/Table.hpp"
#include "../internal/collect/vector.hpp"
#include "Join.hpp"
#include "TableWrapper.hpp"
#include "check_aggregations.hpp"
#include "flatten_fields_t.hpp"
#include "get_schema.hpp"
#include "get_table_t.hpp"
#include "get_tablename.hpp"
#include "make_fields.hpp"
#include "to_alias.hpp"
#include "to_condition.hpp"
@@ -27,13 +26,15 @@
#include "to_joins.hpp"
#include "to_limit.hpp"
#include "to_order_by.hpp"
#include "to_table_or_query.hpp"
namespace sqlgen::transpilation {
template <class TableTupleType, class AliasType, class FieldsType,
class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType>
class TableOrQueryType, class JoinsType, class WhereType,
class GroupByType, class OrderByType, class LimitType>
dynamic::SelectFrom to_select_from(const FieldsType& _fields,
const TableOrQueryType& _table_or_query,
const JoinsType& _joins,
const WhereType& _where,
const LimitType& _limit) {
@@ -43,17 +44,12 @@ dynamic::SelectFrom to_select_from(const FieldsType& _fields,
"The aggregations were not set up correctly. Please check the "
"trace for a more detailed error message.");
using StructType =
get_table_t<std::integral_constant<size_t, 0>, TableTupleType>;
const auto fields = make_fields<TableTupleType, FieldsType>(
_fields,
std::make_integer_sequence<int, rfl::tuple_size_v<FieldsType>>());
return dynamic::SelectFrom{
.table = dynamic::Table{.alias = to_alias<AliasType>(),
.name = get_tablename<StructType>(),
.schema = get_schema<StructType>()},
.table_or_query = to_table_or_query(_table_or_query),
.fields = fields,
.alias = to_alias<AliasType>(),
.joins = to_joins<TableTupleType>(_joins),

View File

@@ -77,17 +77,20 @@ struct ToSQL<Read<ContainerType, WhereType, OrderByType, LimitType>> {
}
};
template <class StructType, class AliasType, class FieldsType, class JoinsType,
class WhereType, class GroupByType, class OrderByType,
class LimitType, class ToType>
struct ToSQL<SelectFrom<StructType, AliasType, FieldsType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType, ToType>> {
template <class TableOrQueryType, class AliasType, class FieldsType,
class JoinsType, class WhereType, class GroupByType,
class OrderByType, class LimitType, class ToType>
struct ToSQL<
SelectFrom<TableOrQueryType, AliasType, FieldsType, JoinsType, WhereType,
GroupByType, OrderByType, LimitType, ToType>> {
dynamic::Statement operator()(const auto& _select_from) const {
using TableTupleType = table_tuple_t<StructType, AliasType, JoinsType>;
return to_select_from<TableTupleType, AliasType, FieldsType, JoinsType,
WhereType, GroupByType, OrderByType, LimitType>(
_select_from.fields_, _select_from.joins_, _select_from.where_,
_select_from.limit_);
using TableTupleType =
table_tuple_t<TableOrQueryType, AliasType, JoinsType>;
return to_select_from<TableTupleType, AliasType, FieldsType,
TableOrQueryType, JoinsType, WhereType, GroupByType,
OrderByType, LimitType>(
_select_from.fields_, _select_from.from_, _select_from.joins_,
_select_from.where_, _select_from.limit_);
}
};

View File

@@ -0,0 +1,34 @@
#ifndef SQLGEN_TRANSPILATION_TO_TABLE_OR_QUERY_HPP_
#define SQLGEN_TRANSPILATION_TO_TABLE_OR_QUERY_HPP_
#include <rfl.hpp>
#include <type_traits>
#include "../dynamic/SelectFrom.hpp"
#include "../dynamic/Table.hpp"
#include "TableWrapper.hpp"
#include "get_schema.hpp"
#include "get_tablename.hpp"
namespace sqlgen::transpilation {
template <class T>
struct ToTableOrQuery;
template <class TableType>
struct ToTableOrQuery<TableWrapper<TableType>> {
dynamic::SelectFrom::TableOrQueryType operator()(const auto&) {
using T = std::remove_cvref_t<TableType>;
return dynamic::Table{.name = get_tablename<T>(),
.schema = get_schema<T>()};
}
};
template <class T>
dynamic::SelectFrom::TableOrQueryType to_table_or_query(const T& _t) {
return ToTableOrQuery<T>{}(_t);
}
} // namespace sqlgen::transpilation
#endif