0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 12:51:13 +08:00
This commit is contained in:
Roland Bock 2024-10-20 11:15:10 +02:00
parent 32529eac90
commit 982812abcc
7 changed files with 30 additions and 81 deletions

View File

@ -107,7 +107,6 @@ namespace sqlpp
auto to_sql_string(Context& context, const join_t<Lhs, JoinType, Rhs, Condition>& t) -> std::string auto to_sql_string(Context& context, const join_t<Lhs, JoinType, Rhs, Condition>& t) -> std::string
{ {
static_assert(not std::is_same<JoinType, cross_join_t>::value, ""); static_assert(not std::is_same<JoinType, cross_join_t>::value, "");
#warning: need to enclose with from_table here to turn this into table_ref (important for CTE)
return to_sql_string(context, t._lhs) + JoinType::_name + to_sql_string(context, t._rhs) + " ON " + return to_sql_string(context, t._lhs) + JoinType::_name + to_sql_string(context, t._rhs) + " ON " +
to_sql_string(context, t._condition); to_sql_string(context, t._condition);
} }
@ -187,7 +186,6 @@ namespace sqlpp
// Note: See sqlpp11/core/basic/join_fwd.h for forward declarations including check_join_args. // Note: See sqlpp11/core/basic/join_fwd.h for forward declarations including check_join_args.
#warning: reactivate check_join_args?
template <typename Lhs, typename Rhs, typename /* = check_join_args<Lhs, Rhs> */> template <typename Lhs, typename Rhs, typename /* = check_join_args<Lhs, Rhs> */>
auto join(Lhs lhs, Rhs rhs) -> pre_join_t<table_ref_t<Lhs>, inner_join_t, table_ref_t<Rhs>> auto join(Lhs lhs, Rhs rhs) -> pre_join_t<table_ref_t<Lhs>, inner_join_t, table_ref_t<Rhs>>
{ {

View File

@ -30,20 +30,6 @@
namespace sqlpp namespace sqlpp
{ {
template <typename T>
auto from_table(T t) -> T
{
return t;
}
template <typename T>
struct from_table_impl
{
using type = T;
};
template <typename T>
using from_table_t = typename from_table_impl<T>::type;
template <typename T> template <typename T>
auto make_table_ref(T t) -> T auto make_table_ref(T t) -> T
{ {

View File

@ -88,54 +88,19 @@ namespace sqlpp
return {}; return {};
} }
template <typename NameTagProvider, typename Statement, typename... FieldSpecs> // make_cte translates the `Statement` into field_specs...
auto from_table(cte_t<NameTagProvider, Statement, FieldSpecs...> /*unused*/) -> cte_ref_t<NameTagProvider> // The field_specs are required to add column data members to the CTE.
{
return cte_ref_t<NameTagProvider>{};
}
template <typename NameTagProvider, typename Statement, typename... FieldSpecs>
struct from_table_impl<cte_t<NameTagProvider, Statement, FieldSpecs...>>
{
using type = cte_ref_t<NameTagProvider>;
};
#warning: Why can't we use FieldSpec directly? If not, does this one need to inherit from name_tag_base?
template <typename FieldSpec>
struct cte_column_spec_t
{
using _sqlpp_name_tag = name_tag_of_t<FieldSpec>;
using value_type = value_type_of_t<FieldSpec>;
};
template<typename FieldSpec>
struct name_tag_of<cte_column_spec_t<FieldSpec>> : public name_tag_of<FieldSpec>{};
template <typename NameTagProvider, typename Statement, typename ResultRow> template <typename NameTagProvider, typename Statement, typename ResultRow>
struct make_cte_impl struct make_cte;
{
using type = void;
};
template <typename NameTagProvider, typename Statement, typename... FieldSpecs> template <typename NameTagProvider, typename Statement, typename... FieldSpecs>
struct make_cte_impl<NameTagProvider, Statement, result_row_t<void, FieldSpecs...>> struct make_cte<NameTagProvider, Statement, result_row_t<void, FieldSpecs...>>
{ {
using type = cte_t<NameTagProvider, Statement, FieldSpecs...>; using type = cte_t<NameTagProvider, Statement, FieldSpecs...>;
}; };
template <typename NameTagProvider, typename Statement> template <typename NameTagProvider, typename Statement>
using make_cte_t = typename make_cte_impl<NameTagProvider, Statement, get_result_row_t<Statement>>::type; using make_cte_t = typename make_cte<NameTagProvider, Statement, get_result_row_t<Statement>>::type;
// workaround for msvc unknown internal error
// template <typename NameTagProvider, typename Statement, typename... FieldSpecs>
// struct cte_t
// : public member_t<cte_column_spec_t<FieldSpecs>, column_t<NameTagProvider, cte_column_spec_t<FieldSpecs>>>...
template <typename NameTagProvider, typename FieldSpec>
struct cte_base
{
using type = member_t<FieldSpec, column_t<cte_ref_t<NameTagProvider>, cte_column_spec_t<FieldSpec>>>;
};
template <typename Check, typename Union> template <typename Check, typename Union>
struct union_cte_impl struct union_cte_impl
@ -162,9 +127,18 @@ namespace sqlpp
template <typename... T> template <typename... T>
using check_cte_union_t = typename check_cte_union<T...>::type; using check_cte_union_t = typename check_cte_union<T...>::type;
template <typename NameTagProvider, typename Statement, typename... FieldSpecs> // cte_member is a helper to add column data members to `cte_t`.
struct cte_t : public cte_base<NameTagProvider, FieldSpecs>::type..., public enable_join<cte_t<NameTagProvider, Statement, FieldSpecs...>> template <typename NameTagProvider, typename FieldSpec>
struct cte_member
{ {
using type = member_t<FieldSpec, column_t<cte_ref_t<NameTagProvider>, FieldSpec>>;
};
template <typename NameTagProvider, typename Statement, typename... FieldSpecs>
struct cte_t : public cte_member<NameTagProvider, FieldSpecs>::type...,
public enable_join<cte_t<NameTagProvider, Statement, FieldSpecs...>>
{
#warning: remove
using _traits = make_traits<no_value_t, tag::is_cte>; using _traits = make_traits<no_value_t, tag::is_cte>;
using _nodes = detail::type_vector<>; using _nodes = detail::type_vector<>;
using _provided_tables = detail::type_set<cte_t>; using _provided_tables = detail::type_set<cte_t>;
@ -173,7 +147,7 @@ namespace sqlpp
constexpr static bool _is_recursive = required_ctes_of<Statement>::template count<NameTagProvider>(); constexpr static bool _is_recursive = required_ctes_of<Statement>::template count<NameTagProvider>();
using _column_tuple_t = std::tuple<column_t<NameTagProvider, cte_column_spec_t<FieldSpecs>>...>; using _column_tuple_t = std::tuple<column_t<cte_ref_t<NameTagProvider>, FieldSpecs>...>;
using _result_row_t = result_row_t<void, FieldSpecs...>; using _result_row_t = result_row_t<void, FieldSpecs...>;

View File

@ -116,7 +116,7 @@ namespace sqlpp
using _consistency_check = consistent_t; using _consistency_check = consistent_t;
template <typename Table> template <typename Table>
auto from(Table table) const -> _new_statement_t<check_from_static_t<Table>, from_t<from_table_t<Table>>> auto from(Table table) const -> _new_statement_t<check_from_static_t<Table>, from_t<table_ref_t<Table>>>
{ {
using Check = check_from_static_t<Table>; using Check = check_from_static_t<Table>;
return _from_impl(Check{}, table); return _from_impl(Check{}, table);
@ -128,10 +128,10 @@ namespace sqlpp
template <typename Table> template <typename Table>
auto _from_impl(consistent_t /*unused*/, Table table) const auto _from_impl(consistent_t /*unused*/, Table table) const
-> _new_statement_t<consistent_t, from_t<from_table_t<Table>>> -> _new_statement_t<consistent_t, from_t<table_ref_t<Table>>>
{ {
return {static_cast<const derived_statement_t<Policies>&>(*this), return {static_cast<const derived_statement_t<Policies>&>(*this),
from_data_t<from_table_t<Table>>{from_table(table)}}; from_data_t<table_ref_t<Table>>{make_table_ref(table)}};
} }
}; };
}; };

View File

@ -33,26 +33,18 @@
namespace sqlpp namespace sqlpp
{ {
template <typename Db, typename Expr> #warning: Need to add tests for eval.
struct eval_t template <typename Db,
typename Expr,
typename std::enable_if<not std::is_convertible<Expr, std::string>::value, int>::type = 0>
auto eval(Db& db, Expr expr) -> result_value_t<value_type_of_t<Expr>>
{ {
static_assert(is_database<Db>::value, "Db parameter of eval has to be a database connection"); static_assert(is_database<Db>::value, "Db parameter of eval has to be a database connection");
static_assert(is_expression_t<Expr>::value, static_assert(is_expression_t<Expr>::value,
"Expression parameter of eval has to be an sqlpp expression or a string"); "Expression parameter of eval has to be an sqlpp expression or a string");
static_assert(required_tables_of_t<Expr>::size::value == 0, static_assert(required_tables_of_t<Expr>::size::value == 0,
"Expression cannot be used in eval because it requires tables"); "Expression cannot be used in eval because it requires tables");
using _name_type = alias::a_t;
using _value_type = value_type_of_t<Expr>;
#warning: Or do we expect users to provide the optional, too?
using _field_spec = field_spec_t<_name_type, ::sqlpp::optional<_value_type>>;
using type = typename _field_spec::cpp_type;
};
template <typename Db,
typename Expr,
typename std::enable_if<not std::is_convertible<Expr, std::string>::value, int>::type = 0>
auto eval(Db& db, Expr expr) -> typename eval_t<typename Db::_connection_base_t, Expr>::type
{
return db(select(expr.as(alias::a))).front().a; return db(select(expr.as(alias::a))).front().a;
} }

View File

@ -35,12 +35,11 @@ namespace sqlpp
{ {
#warning: Do we need this? It should be possible to use name_tag_of_t and value_type_of_t somehow #warning: Do we need this? It should be possible to use name_tag_of_t and value_type_of_t somehow
template <typename NameType, typename ValueType> template <typename NameType, typename ValueType>
struct field_spec_t : public name_tag_base struct field_spec_t
{ {
using _sqlpp_name_tag = NameType;
#warning: Maybe rename result_value in result_value_type? #warning: Maybe rename result_value in result_value_type?
using cpp_type = result_value_t<ValueType>; using result_value_type = result_value_t<ValueType>;
using value_type = ValueType; // This is used by column_t
}; };
template <typename NameType, typename ValueType> template <typename NameType, typename ValueType>

View File

@ -40,9 +40,9 @@ namespace sqlpp
struct result_row_impl; struct result_row_impl;
template <typename Db, std::size_t index, typename FieldSpec> template <typename Db, std::size_t index, typename FieldSpec>
struct result_field : public member_t<FieldSpec, typename FieldSpec::cpp_type> struct result_field : public member_t<FieldSpec, typename FieldSpec::result_value_type>
{ {
using _field = member_t<FieldSpec, typename FieldSpec::cpp_type>; using _field = member_t<FieldSpec, typename FieldSpec::result_value_type>;
result_field() = default; result_field() = default;