Added improved check for potential name duplicates in from()

This commit is contained in:
rbock
2014-06-26 18:56:07 +02:00
parent 2266787e94
commit 1f20d244c7
5 changed files with 64 additions and 24 deletions
+18
View File
@@ -211,6 +211,24 @@ namespace sqlpp
template<typename Minuend, typename Subtrahend>
using make_difference_set_t = typename make_difference_set<Minuend, Subtrahend>::type;
template<template<typename> class Transformation, typename T>
struct transform_set
{
static_assert(::sqlpp::wrong_t<T>::value, "invalid argument for transform_set");
};
template<template<typename> class Transformation, typename... E>
struct transform_set<Transformation, type_set<E...>>
{
using type = typename make_type_set<Transformation<E>...>::type;
};
template<template<typename> class Transformation, typename T>
using transform_set_t = typename transform_set<Transformation, T>::type;
}
}
+31 -19
View File
@@ -32,6 +32,7 @@
#include <sqlpp11/interpretable_list.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/detail/sum.h>
#include <sqlpp11/policy_update.h>
namespace sqlpp
@@ -60,18 +61,8 @@ namespace sqlpp
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::from>;
using _recursive_traits = make_recursive_traits<Tables...>;
using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table or join argument required in from()");
// FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in from()");
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in from()");
static_assert(required_tables_of<from_t>::size::value == 0, "at least one table depends on another table");
// Data
using _data_t = from_data_t<Database, Tables...>;
@@ -84,7 +75,9 @@ namespace sqlpp
{
static_assert(_is_dynamic::value, "from::add() must not be called for static from()");
static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
#warning need to check if table is already known
using _known_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table
using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
static_assert(not detail::is_element_of<typename Table::_name_t, _known_table_names>::value, "Must not use the same table name twice in from()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>;
@@ -172,20 +165,39 @@ namespace sqlpp
static void _check_consistency() {}
template<typename... Args>
auto from(Args... args)
-> _new_statement_t<from_t<void, Args...>>
template<typename... Tables>
auto from(Tables... tables)
-> _new_statement_t<from_t<void, Tables...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), from_data_t<void, Args...>{args...} };
static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
return _from_impl<void>(tables...);
}
template<typename... Args>
auto dynamic_from(Args... args)
-> _new_statement_t<from_t<_database_t, Args...>>
template<typename... Tables>
auto dynamic_from(Tables... tables)
-> _new_statement_t<from_t<_database_t, Tables...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), from_data_t<_database_t, Args...>{args...} };
return _from_impl<_database_t>(tables...);
}
private:
template<typename Database, typename... Tables>
auto _from_impl(Tables... tables)
-> _new_statement_t<from_t<Database, Tables...>>
{
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in from()");
static_assert(required_tables_of<from_t<Database, Tables...>>::size::value == 0, "at least one table depends on another table");
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
using _unique_table_names = detail::transform_set_t<name_of, _unique_tables>;
static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()");
static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()");
return { *static_cast<typename Policies::_statement_t*>(this), from_data_t<Database, Tables...>{tables...} };
}
};
};
-1
View File
@@ -32,7 +32,6 @@
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_remove.h>
#include <sqlpp11/noop.h>
#warning: need to use another table provider, since delete can be used with several tables
#include <sqlpp11/from.h>
#include <sqlpp11/extra_tables.h>
#include <sqlpp11/using.h>
+9
View File
@@ -187,6 +187,12 @@ namespace sqlpp
using type = typename T::_recursive_traits::_parameters;
};
template<typename T>
struct name_of_impl
{
using type = typename T::_name_t;
};
template<typename... T>
struct make_parameter_tuple_impl
{
@@ -211,6 +217,9 @@ namespace sqlpp
template<typename T>
using parameters_of = typename detail::parameters_of_impl<T>::type;
template<typename T>
using name_of = typename detail::name_of_impl<T>::type;
template<typename ValueType, typename... Tags>
struct make_traits
{
+6 -4
View File
@@ -49,8 +49,10 @@ namespace sqlpp
struct verbatim_table_t: public sqlpp::table_t<verbatim_table_t, detail::unusable_pseudo_column_t>
{
verbatim_table_t(std::string name):
_name(name)
struct _name_t {};
verbatim_table_t(std::string representation):
_representation(representation)
{
}
@@ -60,7 +62,7 @@ namespace sqlpp
verbatim_table_t& operator=(verbatim_table_t&& rhs) = default;
~verbatim_table_t() = default;
std::string _name;
std::string _representation;
};
template<typename Context>
@@ -70,7 +72,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << t._name;
context << t._representation;
return context;
}
};