mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Added checks to prevent non-matching columns from being inserted
This commit is contained in:
parent
8ede5c7a93
commit
ae2f1948ac
@ -37,6 +37,7 @@
|
||||
#include <sqlpp11/vendor/expression.h>
|
||||
#include <sqlpp11/vendor/interpreter.h>
|
||||
#include <sqlpp11/vendor/wrong.h>
|
||||
#include <sqlpp11/detail/type_set.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
@ -46,6 +47,7 @@ namespace sqlpp
|
||||
using _is_column = std::true_type;
|
||||
using _spec_t = ColumnSpec;
|
||||
using _table = Table;
|
||||
using _table_set = detail::type_set<_table>;
|
||||
using _column_type = typename ColumnSpec::_column_type;
|
||||
struct _value_type: ColumnSpec::_value_type
|
||||
{
|
||||
|
@ -27,6 +27,7 @@
|
||||
#ifndef SQLPP_DETAIL_TYPE_SET_H
|
||||
#define SQLPP_DETAIL_TYPE_SET_H
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <sqlpp11/vendor/wrong.h>
|
||||
#include <sqlpp11/detail/logic.h>
|
||||
@ -39,17 +40,21 @@ namespace sqlpp
|
||||
template<typename... T>
|
||||
struct make_set;
|
||||
|
||||
template<typename T>
|
||||
class type_set_element {};
|
||||
|
||||
// A type set
|
||||
template<typename... Element>
|
||||
struct type_set: type_set_element<Element>...
|
||||
struct type_set
|
||||
{
|
||||
using size = std::integral_constant<size_t, sizeof...(Element)>;
|
||||
using _elements_t = std::tuple<Element...>;
|
||||
using size = std::tuple_size<_elements_t>;
|
||||
using _is_type_set = std::true_type;
|
||||
|
||||
template<typename T>
|
||||
using count = std::is_base_of<type_set_element<T>, type_set>;
|
||||
struct count
|
||||
{
|
||||
template<typename E>
|
||||
using same = std::is_same<T, E>;
|
||||
static constexpr bool value = or_t<same, Element...>::value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_superset_of
|
||||
@ -59,7 +64,9 @@ namespace sqlpp
|
||||
|
||||
template<typename... T>
|
||||
struct is_superset_of<type_set<T...>>
|
||||
: and_t<count, T...> {};
|
||||
{
|
||||
static constexpr bool value = and_t<count, T...>::value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct join
|
||||
@ -69,7 +76,9 @@ namespace sqlpp
|
||||
|
||||
template<typename... T>
|
||||
struct join<type_set<T...>>
|
||||
: make_set<Element..., T...> {};
|
||||
{
|
||||
using type = typename make_set<Element..., T...>::type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_subset_of
|
||||
@ -79,7 +88,9 @@ namespace sqlpp
|
||||
|
||||
template<typename... T>
|
||||
struct is_subset_of<type_set<T...>>
|
||||
: type_set<T...>::template is_superset_of<type_set>{};
|
||||
{
|
||||
static constexpr bool value = type_set<T...>::template is_superset_of<type_set>::value;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_disjunct_from
|
||||
@ -93,16 +104,12 @@ namespace sqlpp
|
||||
static constexpr bool value = not(or_t<type_set::count, T...>::value or or_t<type_set<T...>::template count, Element...>::value);
|
||||
};
|
||||
|
||||
template<typename T, typename Enable = void>
|
||||
template<typename T>
|
||||
struct insert
|
||||
{
|
||||
using type = type_set;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct insert<T, typename std::enable_if<not type_set::template count<T>::value>::type>
|
||||
{
|
||||
using type = type_set<Element..., T>;
|
||||
using type = typename std::conditional<count<T>::value,
|
||||
type_set,
|
||||
type_set<Element..., T>>::type;
|
||||
};
|
||||
|
||||
template<template<typename A> class Predicate, typename T>
|
||||
@ -152,6 +159,34 @@ namespace sqlpp
|
||||
template<typename... T>
|
||||
using has_duplicates = std::integral_constant<bool, make_set<T...>::type::size::value != sizeof...(T)>;
|
||||
|
||||
template<typename... T>
|
||||
struct make_joined_set
|
||||
{
|
||||
static_assert(::sqlpp::vendor::wrong_t<T...>::value, "invalid argument for joined set");
|
||||
};
|
||||
|
||||
template<>
|
||||
struct make_joined_set<>
|
||||
{
|
||||
using type = type_set<>;
|
||||
};
|
||||
|
||||
/*
|
||||
template<typename... E>
|
||||
struct make_joined_set<type_set<E...>>
|
||||
{
|
||||
using type = type_set<E...>;
|
||||
};
|
||||
*/
|
||||
|
||||
template<typename... E, typename... T>
|
||||
struct make_joined_set<type_set<E...>, T...>
|
||||
{
|
||||
using _rest = typename make_joined_set<T...>::type;
|
||||
|
||||
using type = typename type_set<E...>::template join<_rest>::type;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ namespace sqlpp
|
||||
>
|
||||
struct check_insert_t
|
||||
{
|
||||
static_assert(Table::_table_set::template is_superset_of<typename InsertValueList::_table_set>::value, "inserted columns do not match the table in insert_into");
|
||||
//static_assert(not (vendor::is_noop<InsertList>::value and vendor::is_noop<ColumnList>::value) , "calling set() or default_values()");
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
@ -66,6 +67,8 @@ namespace sqlpp
|
||||
insert_t()
|
||||
{}
|
||||
|
||||
static_assert(detail::check_insert_t<Policies...>::value, "invalid insert_into");
|
||||
|
||||
template<typename Whatever>
|
||||
insert_t(insert_t i, Whatever whatever):
|
||||
vendor::policy_t<Policies>(i, whatever)...
|
||||
|
4
include/sqlpp11/vendor/from.h
vendored
4
include/sqlpp11/vendor/from.h
vendored
@ -48,11 +48,13 @@ namespace sqlpp
|
||||
|
||||
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::and_t<is_table_t, Tables...>::value, "at least one argument is not a table or join in from()");
|
||||
|
||||
// FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance
|
||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Tables::_table_set...>;
|
||||
|
||||
|
||||
from_t(Tables... tables):
|
||||
_tables(tables...)
|
||||
|
9
include/sqlpp11/vendor/insert_value_list.h
vendored
9
include/sqlpp11/vendor/insert_value_list.h
vendored
@ -43,6 +43,7 @@ namespace sqlpp
|
||||
struct insert_default_values_t
|
||||
{
|
||||
using _is_insert_list = std::true_type;
|
||||
using _table_set = ::sqlpp::detail::type_set<>;
|
||||
using _is_dynamic = std::false_type;
|
||||
const insert_default_values_t& _insert_value_list() const { return *this; }
|
||||
};
|
||||
@ -66,6 +67,9 @@ namespace sqlpp
|
||||
|
||||
static_assert(not sqlpp::detail::or_t<must_not_insert_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()");
|
||||
|
||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::_column_t::_table_set...>::type;
|
||||
static_assert(_is_dynamic::value ? (_table_set::size::value < 2) : (_table_set::size::value == 1), "set() contains assignments for tables from several columns");
|
||||
|
||||
insert_list_t(Assignments... assignment):
|
||||
_assignments(assignment...),
|
||||
_columns({assignment._lhs}...),
|
||||
@ -111,6 +115,9 @@ namespace sqlpp
|
||||
static_assert(not ::sqlpp::detail::or_t<must_not_insert_t, Columns...>::value, "at least one column argument has a must_not_insert flag in its definition");
|
||||
|
||||
using _value_tuple_t = std::tuple<vendor::insert_value_t<Columns>...>;
|
||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Columns::_table_set...>::type;
|
||||
|
||||
static_assert(_table_set::size::value == 1, "columns from multiple tables in columns()");
|
||||
|
||||
column_list_t(Columns... columns):
|
||||
_columns(simple_column_t<Columns>{columns}...)
|
||||
@ -139,7 +146,7 @@ namespace sqlpp
|
||||
|
||||
struct no_insert_value_list_t
|
||||
{
|
||||
using _is_insert_value_list = std::true_type;
|
||||
using _table_set = ::sqlpp::detail::type_set<>;
|
||||
const no_insert_value_list_t& _insert_value_list() const { return *this; }
|
||||
};
|
||||
|
||||
|
5
include/sqlpp11/vendor/single_table.h
vendored
5
include/sqlpp11/vendor/single_table.h
vendored
@ -30,7 +30,7 @@
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/vendor/policy_update.h>
|
||||
#include <sqlpp11/vendor/crtp_wrapper.h>
|
||||
#include <iostream> // FIXME: REMOVE
|
||||
#include <sqlpp11/detail/type_set.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
@ -55,12 +55,13 @@ namespace sqlpp
|
||||
~single_table_t() = default;
|
||||
|
||||
const single_table_t& _single_table() const { return *this; }
|
||||
using _table_set = typename Table::_table_set;
|
||||
Table _table;
|
||||
};
|
||||
|
||||
struct no_single_table_t
|
||||
{
|
||||
using _is_single_table = std::true_type;
|
||||
using _table_set = ::sqlpp::detail::type_set<>;
|
||||
const no_single_table_t& _single_table() const { return *this; }
|
||||
};
|
||||
|
||||
|
20
include/sqlpp11/vendor/wrong.h
vendored
20
include/sqlpp11/vendor/wrong.h
vendored
@ -33,20 +33,14 @@ namespace sqlpp
|
||||
{
|
||||
namespace vendor
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// A template that always returns false
|
||||
// To be used with static assert, for instance, to ensure it
|
||||
// fires only when the template is instantiated.
|
||||
template<class ...T> struct wrong_t
|
||||
{
|
||||
using type = std::false_type;
|
||||
};
|
||||
}
|
||||
|
||||
// A template that always returns false
|
||||
// To be used with static assert, for instance, to ensure it
|
||||
// fires only when the template is instantiated.
|
||||
template<class ...T>
|
||||
using wrong_t = typename detail::wrong_t<T...>::type;
|
||||
struct wrong_t
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -43,7 +43,7 @@ int main()
|
||||
test::TabFoo f;
|
||||
test::TabBar t;
|
||||
|
||||
interpret(insert_into(t).columns(t.gamma, t.beta), printer).flush();
|
||||
interpret(insert_into(t).columns(t.beta, t.gamma), printer).flush();
|
||||
{
|
||||
auto i = insert_into(t).columns(t.gamma, t.beta);
|
||||
i.add_values(t.gamma = true, t.beta = "cheesecake");
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
CREATE TABLE tab_foo
|
||||
(
|
||||
delta varchar(255),
|
||||
epsilon bigint,
|
||||
omega double
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user