0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 04:47:18 +08:00

Added a table consistency checks to several dynamic methods

This commit is contained in:
rbock 2014-04-22 20:46:32 +02:00
parent 1f3e611fdf
commit 0ffd93108b
15 changed files with 89 additions and 17 deletions

View File

@ -72,6 +72,11 @@ namespace sqlpp
using _new_statement_t = typename _policies_insert_t<Needle, Replacement, Table, InsertValueList>::type; using _new_statement_t = typename _policies_insert_t<Needle, Replacement, Table, InsertValueList>::type;
using _table_set = typename _table_t::_table_set; using _table_set = typename _table_t::_table_set;
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
}; };
} }

View File

@ -32,6 +32,7 @@
#include <sqlpp11/prepared_remove.h> #include <sqlpp11/prepared_remove.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/single_table.h> #include <sqlpp11/vendor/single_table.h>
#include <sqlpp11/vendor/extra_tables.h>
#include <sqlpp11/vendor/using.h> #include <sqlpp11/vendor/using.h>
#include <sqlpp11/vendor/where.h> #include <sqlpp11/vendor/where.h>
#include <sqlpp11/vendor/policy_update.h> #include <sqlpp11/vendor/policy_update.h>
@ -49,6 +50,7 @@ namespace sqlpp
template<typename Db = void, template<typename Db = void,
typename Table = vendor::no_single_table_t, typename Table = vendor::no_single_table_t,
typename Using = vendor::no_using_t, typename Using = vendor::no_using_t,
typename ExtraTables = vendor::no_extra_tables_t,
typename Where = vendor::no_where_t typename Where = vendor::no_where_t
> >
struct remove_policies_t struct remove_policies_t
@ -56,12 +58,14 @@ namespace sqlpp
using _database_t = Db; using _database_t = Db;
using _table_t = Table; using _table_t = Table;
using _using_t = Using; using _using_t = Using;
using _extra_tables_t = ExtraTables;
using _where_t = Where; using _where_t = Where;
using _statement_t = remove_t<Db, Table, Using, Where>; using _statement_t = remove_t<Db, Table, Using, ExtraTables, Where>;
struct _methods_t: struct _methods_t:
public _using_t::template _methods_t<remove_policies_t>, public _using_t::template _methods_t<remove_policies_t>,
public _extra_tables_t::template _methods_t<remove_policies_t>,
public _where_t::template _methods_t<remove_policies_t> public _where_t::template _methods_t<remove_policies_t>
{}; {};
@ -72,7 +76,12 @@ namespace sqlpp
}; };
template<typename Needle, typename Replacement> template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement, Table, Using, Where>::type; using _new_statement_t = typename _policies_update_t<Needle, Replacement, Table, Using, ExtraTables, Where>::type;
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set, typename _using_t::_table_set, typename _extra_tables_t::_table_set>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
}; };
} }
@ -87,6 +96,7 @@ namespace sqlpp
using _database_t = typename _policies_t::_database_t; using _database_t = typename _policies_t::_database_t;
using _table_t = typename _policies_t::_table_t; using _table_t = typename _policies_t::_table_t;
using _using_t = typename _policies_t::_using_t; using _using_t = typename _policies_t::_using_t;
using _extra_tables_t = typename _policies_t::_extra_tables_t;
using _where_t = typename _policies_t::_where_t; using _where_t = typename _policies_t::_where_t;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type; using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type;

View File

@ -255,22 +255,25 @@ namespace sqlpp
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _from_t::_table_set>::value; static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _from_t::_table_set>::value;
}; };
void _check_consistency() const
{
static_assert(is_table_subset_of_from<_flag_list_t>::value, "flags require additional tables in from()");
static_assert(is_table_subset_of_from<_column_list_t>::value, "selected columns require additional tables in from()");
static_assert(is_table_subset_of_from<_where_t>::value, "where() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_group_by_t>::value, "group_by() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_having_t>::value, "having() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_order_by_t>::value, "order_by() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_limit_t>::value, "limit() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_offset_t>::value, "offset() expression requires additional tables in from()");
static_assert(not _table_set::size::value, "one sub expression contains tables which are not in the from()");
}
// Execute // Execute
template<typename Database> template<typename Database>
auto _run(Database& db) const auto _run(Database& db) const
-> result_t<decltype(db.select(*this)), _result_row_t<Database>> -> result_t<decltype(db.select(*this)), _result_row_t<Database>>
{ {
#warning: need to check in add_xy method as well _check_consistency();
#warning: need add_wxy_without_table_check
static_assert(is_table_subset_of_from<_flag_list_t>::value, "flags require additional tables in from()");
static_assert(is_table_subset_of_from<_column_list_t>::value, "selected columns require additional tables in from()");
static_assert(is_table_subset_of_from<_where_t>::value, "where() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_group_by_t>::value, "group_by() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_having_t>::value, "having() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_order_by_t>::value, "order_by() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_limit_t>::value, "limit() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_offset_t>::value, "offset() expression requires additional tables in from()");
static_assert(not _table_set::size::value, "one sub expression contains tables which are not in the from()");
static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
return {db.select(*this), get_dynamic_names()}; return {db.select(*this), get_dynamic_names()};
@ -281,6 +284,7 @@ namespace sqlpp
auto _prepare(Database& db) const auto _prepare(Database& db) const
-> prepared_select_t<Database, select_t> -> prepared_select_t<Database, select_t>
{ {
_check_consistency();
return {{}, get_dynamic_names(), db.prepare_select(*this)}; return {{}, get_dynamic_names(), db.prepare_select(*this)};
} }

View File

@ -73,6 +73,12 @@ namespace sqlpp
template<typename Needle, typename Replacement> template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement, Table, UpdateList, Where>::type; using _new_statement_t = typename _policies_update_t<Needle, Replacement, Table, UpdateList, Where>::type;
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
}; };
} }

View File

@ -70,10 +70,17 @@ namespace sqlpp
struct _methods_t struct _methods_t
{ {
template<typename Expression> template<typename Expression>
void add_group_by_ntc(Expression expression)
{
add_group_by<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_group_by(Expression expression) void add_group_by(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_group_by must not be called for static group_by"); static_assert(_is_dynamic::value, "add_group_by must not be called for static group_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_group_by()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_group_by()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_group_by()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_expression_t<Expression>>; using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_expression_t<Expression>>;

View File

@ -67,10 +67,17 @@ namespace sqlpp
struct _methods_t struct _methods_t
{ {
template<typename Expression> template<typename Expression>
void add_having_ntc(Expression expression)
{
add_having<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_having(Expression expression) void add_having(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_having must not be called for static having"); static_assert(_is_dynamic::value, "add_having must not be called for static having");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_having()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_having()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_having()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_expression_t<Expression>>; using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_expression_t<Expression>>;

View File

@ -93,6 +93,7 @@ namespace sqlpp
template<typename Limit> template<typename Limit>
void set_limit(Limit value) void set_limit(Limit value)
{ {
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Limit>::type; using arg_t = typename wrap_operand<Limit>::type;
static_cast<typename Policies::_statement_t*>(this)->_limit._value = arg_t{value}; static_cast<typename Policies::_statement_t*>(this)->_limit._value = arg_t{value};
static_cast<typename Policies::_statement_t*>(this)->_limit._initialized = true; static_cast<typename Policies::_statement_t*>(this)->_limit._initialized = true;

View File

@ -92,6 +92,7 @@ namespace sqlpp
template<typename Offset> template<typename Offset>
void set_offset(Offset value) void set_offset(Offset value)
{ {
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Offset>::type; using arg_t = typename wrap_operand<Offset>::type;
static_cast<typename Policies::_statement_t*>(this)->_offset._value = arg_t{value}; static_cast<typename Policies::_statement_t*>(this)->_offset._value = arg_t{value};
static_cast<typename Policies::_statement_t*>(this)->_offset._initialized = true; static_cast<typename Policies::_statement_t*>(this)->_offset._initialized = true;

View File

@ -69,10 +69,17 @@ namespace sqlpp
struct _methods_t struct _methods_t
{ {
template<typename Expression> template<typename Expression>
void add_order_by_ntc(Expression expression)
{
add_order_by<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_order_by(Expression expression) void add_order_by(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_order_by must not be called for static order_by"); static_assert(_is_dynamic::value, "add_order_by must not be called for static order_by");
static_assert(is_sort_order_t<Expression>::value, "invalid expression argument in add_order_by()"); static_assert(is_sort_order_t<Expression>::value, "invalid expression argument in add_order_by()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_order_by()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_sort_order_t<Expression>>; using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_sort_order_t<Expression>>;

View File

@ -188,15 +188,15 @@ namespace sqlpp
template<typename NamedExpression> template<typename NamedExpression>
void add_column_ntc(NamedExpression namedExpression) void add_column_ntc(NamedExpression namedExpression)
{ {
add_column<NamedExpression, std::true_type>(namedExpression); add_column<NamedExpression, std::false_type>(namedExpression);
} }
template<typename NamedExpression, typename Ntc = std::false_type> template<typename NamedExpression, typename TableCheckRequired = std::true_type>
void add_column(NamedExpression namedExpression) void add_column(NamedExpression namedExpression)
{ {
static_assert(_is_dynamic::value, "add_column can only be called for dynamic_column"); static_assert(_is_dynamic::value, "add_column can only be called for dynamic_column");
static_assert(is_named_expression_t<NamedExpression>::value, "invalid named expression argument in add_column()"); static_assert(is_named_expression_t<NamedExpression>::value, "invalid named expression argument in add_column()");
static_assert(Ntc::value or Policies::template _no_unknown_tables<NamedExpression>::value, "named expression uses tables unknown to this statement in add_column()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<NamedExpression>::value, "named expression uses tables unknown to this statement in add_column()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_named_expression_t<NamedExpression>>; using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_named_expression_t<NamedExpression>>;

View File

@ -66,10 +66,17 @@ namespace sqlpp
struct _methods_t struct _methods_t
{ {
template<typename Flag> template<typename Flag>
void add_flag_ntc(Flag flag)
{
add_flag<Flag, std::false_type>(flag);
}
template<typename Flag, typename TableCheckRequired = std::true_type>
void add_flag(Flag flag) void add_flag(Flag flag)
{ {
static_assert(_is_dynamic::value, "add_flag must not be called for static select flags"); static_assert(_is_dynamic::value, "add_flag must not be called for static select flags");
static_assert(is_select_flag_t<Flag>::value, "invalid select flag argument in add_flag()"); static_assert(is_select_flag_t<Flag>::value, "invalid select flag argument in add_flag()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Flag>::value, "flag uses tables unknown to this statement in add_flag()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_select_flag_t<Flag>>; using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_select_flag_t<Flag>>;

View File

@ -72,11 +72,18 @@ namespace sqlpp
struct _methods_t struct _methods_t
{ {
template<typename Assignment> template<typename Assignment>
void add_set_ntc(Assignment assignment)
{
add_set<Assignment, std::false_type>(assignment);
}
template<typename Assignment, typename TableCheckRequired = std::true_type>
void add_set(Assignment assignment) void add_set(Assignment assignment)
{ {
static_assert(_is_dynamic::value, "add_set must not be called for static from()"); static_assert(_is_dynamic::value, "add_set must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add_set()"); static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add_set()");
static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_column_t>::value, "set() argument must not be updated"); static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_column_t>::value, "add_set() argument must not be updated");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "assignment uses tables unknown to this statement in add_set()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t,
_is_dynamic, _is_dynamic,

View File

@ -51,6 +51,8 @@ namespace sqlpp
static_assert(::sqlpp::detail::all_t<is_table_t, Tables...>::value, "at least one argument is not an table in using()"); static_assert(::sqlpp::detail::all_t<is_table_t, Tables...>::value, "at least one argument is not an table in using()");
using _table_set = ::sqlpp::detail::make_joined_set_t<typename Tables::_table_set...>;
using_t(Tables... tables): using_t(Tables... tables):
_tables(tables...) _tables(tables...)
{} {}

View File

@ -68,10 +68,17 @@ namespace sqlpp
struct _methods_t struct _methods_t
{ {
template<typename Expression> template<typename Expression>
void add_where_ntc(Expression expression)
{
add_where<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_where(Expression expression) void add_where(Expression expression)
{ {
static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where"); static_assert(_is_dynamic::value, "add_where can only be called for dynamic_where");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_where()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_where()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_where()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_expression_t<Expression>>; using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_expression_t<Expression>>;

View File

@ -62,6 +62,7 @@ int main()
serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).str(); serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).str();
auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where(); auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where();
u.add_set(t.gamma = false); u.add_set(t.gamma = false);
u.add_where(t.gamma != false);
serialize(u, printer).str(); serialize(u, printer).str();
db(u); db(u);