mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Merge branch 'feature/rewrite_traits' into develop
This commit is contained in:
commit
e4ecd0bc68
@ -28,23 +28,20 @@
|
|||||||
#define SQLPP_ALIAS_H
|
#define SQLPP_ALIAS_H
|
||||||
|
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/vendor/serializer.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Expression, typename AliasProvider>
|
template<typename Expression, typename AliasProvider>
|
||||||
struct expression_alias_t
|
struct expression_alias_t
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<value_type_of<Expression>, tag::named_expression, tag::alias>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Expression>;
|
||||||
|
|
||||||
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");
|
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");
|
||||||
static_assert(not is_alias_t<Expression>::value, "cannot create an alias of an alias");
|
static_assert(not is_alias_t<Expression>::value, "cannot create an alias of an alias");
|
||||||
|
|
||||||
struct _value_type: Expression::_value_type
|
|
||||||
{
|
|
||||||
using _is_expression = std::false_type;
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
using _is_alias = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
using _name_t = typename AliasProvider::_name_t;
|
using _name_t = typename AliasProvider::_name_t;
|
||||||
using _table_set = typename Expression::_table_set;
|
|
||||||
|
|
||||||
Expression _expression;
|
Expression _expression;
|
||||||
};
|
};
|
||||||
|
@ -37,11 +37,8 @@ namespace sqlpp
|
|||||||
template<typename Select>
|
template<typename Select>
|
||||||
struct any_t
|
struct any_t
|
||||||
{
|
{
|
||||||
struct _value_type: public Select::_value_type::_base_value_type
|
using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::multi_expression>;
|
||||||
{
|
using _recursive_traits = make_recursive_traits<Select>;
|
||||||
using _is_expression = std::false_type;
|
|
||||||
using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
@ -55,8 +52,6 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
using _table_set = typename Select::_table_set;
|
|
||||||
|
|
||||||
any_t(Select select):
|
any_t(Select select):
|
||||||
_select(select)
|
_select(select)
|
||||||
{}
|
{}
|
||||||
@ -91,7 +86,8 @@ namespace sqlpp
|
|||||||
auto any(T t) -> typename vendor::any_t<vendor::wrap_operand_t<T>>
|
auto any(T t) -> typename vendor::any_t<vendor::wrap_operand_t<T>>
|
||||||
{
|
{
|
||||||
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "any() requires a select expression as argument");
|
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "any() requires a select expression as argument");
|
||||||
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "any() requires a single column select expression as argument");
|
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "any() requires a single column select expression as argument");
|
||||||
|
// FIXME: can we accept non-values like NULL here?
|
||||||
return { t };
|
return { t };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,16 +36,12 @@ namespace sqlpp
|
|||||||
template<typename Flag, typename Expr>
|
template<typename Flag, typename Expr>
|
||||||
struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>>
|
struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>>
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<floating_point, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Expr>;
|
||||||
|
|
||||||
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "avg() used with flag other than 'distinct'");
|
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "avg() used with flag other than 'distinct'");
|
||||||
static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument");
|
static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument");
|
||||||
|
|
||||||
struct _value_type: public floating_point
|
|
||||||
{
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
using _table_set = typename Expr::_table_set;
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
static constexpr const char* _get_name() { return "AVG"; }
|
static constexpr const char* _get_name() { return "AVG"; }
|
||||||
|
@ -32,16 +32,11 @@
|
|||||||
#include <sqlpp11/vendor/expression_fwd.h>
|
#include <sqlpp11/vendor/expression_fwd.h>
|
||||||
#include <sqlpp11/vendor/in_fwd.h>
|
#include <sqlpp11/vendor/in_fwd.h>
|
||||||
#include <sqlpp11/vendor/is_null_fwd.h>
|
#include <sqlpp11/vendor/is_null_fwd.h>
|
||||||
|
#include <sqlpp11/vendor/wrap_operand.h>
|
||||||
#include <sqlpp11/detail/logic.h>
|
#include <sqlpp11/detail/logic.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
struct boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
// basic operators
|
// basic operators
|
||||||
template<typename Base, template<typename> class IsCorrectValueType>
|
template<typename Base, template<typename> class IsCorrectValueType>
|
||||||
struct basic_expression_operators
|
struct basic_expression_operators
|
||||||
|
@ -42,16 +42,12 @@ namespace sqlpp
|
|||||||
// boolean value type
|
// boolean value type
|
||||||
struct boolean
|
struct boolean
|
||||||
{
|
{
|
||||||
using _value_type = boolean;
|
using _tag = ::sqlpp::tag::boolean;
|
||||||
using _base_value_type = boolean;
|
|
||||||
using _is_boolean = std::true_type;
|
|
||||||
using _is_value = std::true_type;
|
|
||||||
using _is_expression = std::true_type;
|
|
||||||
using _cpp_value_type = bool;
|
using _cpp_value_type = bool;
|
||||||
|
|
||||||
struct _parameter_t
|
struct _parameter_t
|
||||||
{
|
{
|
||||||
using _value_type = boolean;
|
using _value_type = boolean; // FIXME
|
||||||
|
|
||||||
_parameter_t():
|
_parameter_t():
|
||||||
_value(false),
|
_value(false),
|
||||||
|
@ -45,21 +45,22 @@ namespace sqlpp
|
|||||||
struct column_t: public ColumnSpec::_value_type::template expression_operators<column_t<Table, ColumnSpec>>,
|
struct column_t: public ColumnSpec::_value_type::template expression_operators<column_t<Table, ColumnSpec>>,
|
||||||
public ColumnSpec::_value_type::template column_operators<column_t<Table, ColumnSpec>>
|
public ColumnSpec::_value_type::template column_operators<column_t<Table, ColumnSpec>>
|
||||||
{
|
{
|
||||||
using _is_column = std::true_type;
|
using _traits = make_traits<typename ColumnSpec::_value_type, tag::column, tag::expression, tag::named_expression>;
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _parameters = std::tuple<>;
|
||||||
|
using _provided_tables = detail::type_set<>;
|
||||||
|
using _required_tables = detail::type_set<Table>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
};
|
||||||
|
|
||||||
using _spec_t = ColumnSpec;
|
using _spec_t = ColumnSpec;
|
||||||
using _table = Table;
|
using _table = Table;
|
||||||
using _table_set = detail::type_set<_table>;
|
using _column_type = typename _spec_t::_column_type;
|
||||||
using _column_type = typename ColumnSpec::_column_type;
|
using _name_t = typename _spec_t::_name_t;
|
||||||
struct _value_type: ColumnSpec::_value_type
|
|
||||||
{
|
|
||||||
using _is_expression = std::true_type;
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
using _is_alias = std::false_type;
|
|
||||||
};
|
|
||||||
template<typename T>
|
|
||||||
using _is_valid_operand = typename _value_type::template _is_valid_operand<T>;
|
|
||||||
|
|
||||||
using _name_t = typename ColumnSpec::_name_t;
|
template<typename T>
|
||||||
|
using _is_valid_operand = typename ColumnSpec::_value_type::template _is_valid_operand<T>;
|
||||||
|
|
||||||
column_t() = default;
|
column_t() = default;
|
||||||
column_t(const column_t&) = default;
|
column_t(const column_t&) = default;
|
||||||
@ -80,12 +81,12 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
auto operator =(T t) const -> vendor::assignment_t<column_t, typename vendor::wrap_operand<T>::type>
|
auto operator =(T t) const -> vendor::assignment_t<column_t, vendor::wrap_operand_t<T>>
|
||||||
{
|
{
|
||||||
using rhs = vendor::wrap_operand_t<T>;
|
using rhs = vendor::wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand assignment operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand assignment operand");
|
||||||
|
|
||||||
return { *this, {t} };
|
return { *this, rhs{t} };
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator =(sqlpp::null_t) const
|
auto operator =(sqlpp::null_t) const
|
||||||
|
@ -37,16 +37,12 @@ namespace sqlpp
|
|||||||
template<typename Flag, typename Expr>
|
template<typename Flag, typename Expr>
|
||||||
struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>>
|
struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>>
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Expr>;
|
||||||
|
|
||||||
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "count() used with flag other than 'distinct'");
|
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "count() used with flag other than 'distinct'");
|
||||||
static_assert(is_expression_t<Expr>::value, "count() requires a sql expression as argument");
|
static_assert(is_expression_t<Expr>::value, "count() requires a sql expression as argument");
|
||||||
|
|
||||||
struct _value_type: public sqlpp::detail::integral
|
|
||||||
{
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
using _table_set = typename Expr::_table_set;
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
static constexpr const char* _get_name() { return "COUNT"; }
|
static constexpr const char* _get_name() { return "COUNT"; }
|
||||||
|
@ -33,9 +33,8 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct default_value_t
|
struct default_value_t
|
||||||
{
|
{
|
||||||
static constexpr bool _is_expression = true;
|
using _traits = make_traits<no_value_t, tag::expression>;
|
||||||
using _value_type = no_value_t;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
|
|
||||||
static constexpr bool _is_trivial() { return false; }
|
static constexpr bool _is_trivial() { return false; }
|
||||||
};
|
};
|
||||||
|
60
include/sqlpp11/detail/get_last.h
Normal file
60
include/sqlpp11/detail/get_last.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_DETAIL_GET_LAST_H
|
||||||
|
#define SQLPP_DETAIL_GET_LAST_H
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<template<typename> class Predicate, typename Default, typename... T>
|
||||||
|
struct get_last_if_impl;
|
||||||
|
|
||||||
|
template<template<typename> class Predicate, typename Default>
|
||||||
|
struct get_last_if_impl<Predicate, Default>
|
||||||
|
{
|
||||||
|
using type = Default;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<template<typename> class Predicate, typename Default, typename T, typename... Rest>
|
||||||
|
struct get_last_if_impl<Predicate, Default, T, Rest...>
|
||||||
|
{
|
||||||
|
using rest = typename get_last_if_impl<Predicate, Default, Rest...>::type;
|
||||||
|
using type = typename std::conditional<std::is_same<rest, Default>::value and Predicate<T>::value,
|
||||||
|
T,
|
||||||
|
rest>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<template<typename> class Predicate, typename Default, typename... T>
|
||||||
|
using get_last_if = typename get_last_if_impl<Predicate, Default, T...>::type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -24,23 +24,32 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SQLPP_DETAIL_ARG_SELECTOR_H
|
#ifndef SQLPP_DETAIL_PICK_ARG_H
|
||||||
#define SQLPP_DETAIL_ARG_SELECTOR_H
|
#define SQLPP_DETAIL_PICK_ARG_H
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Target>
|
template<typename Target, typename Statement, typename Term>
|
||||||
struct arg_selector
|
Target pick_arg_impl(Statement statement, Term term, const std::true_type&)
|
||||||
{
|
{
|
||||||
static Target _(Target, Target t) { return t; }
|
return term;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename X>
|
template<typename Target, typename Statement, typename Term>
|
||||||
static Target _(X, Target t) { return t; }
|
Target pick_arg_impl(Statement statement, Term term, const std::false_type&)
|
||||||
|
{
|
||||||
|
return static_cast<Target>(statement);
|
||||||
|
};
|
||||||
|
|
||||||
template<typename X>
|
// Returns a statement's term either by picking the term from the statement or using the new term
|
||||||
static Target _(Target t, X) { return t; }
|
template<typename Target, typename Statement, typename Term>
|
||||||
|
Target pick_arg(Statement statement, Term term)
|
||||||
|
{
|
||||||
|
return pick_arg_impl<Target>(statement, term, std::is_same<Target, Term>());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -157,6 +157,9 @@ namespace sqlpp
|
|||||||
using type = typename make_type_set_if<Predicate, Rest...>::type::template insert_if<Predicate, T>::type;
|
using type = typename make_type_set_if<Predicate, Rest...>::type::template insert_if<Predicate, T>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<template<typename> class Predicate, typename... T>
|
||||||
|
using make_type_set_if_t = typename make_type_set_if<Predicate, T...>::type;
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename... T>
|
template<template<typename> class Predicate, typename... T>
|
||||||
struct make_type_set_if_not
|
struct make_type_set_if_not
|
||||||
{
|
{
|
||||||
|
@ -36,15 +36,11 @@ namespace sqlpp
|
|||||||
template<typename Select>
|
template<typename Select>
|
||||||
struct exists_t: public boolean::template expression_operators<exists_t<Select>>
|
struct exists_t: public boolean::template expression_operators<exists_t<Select>>
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Select>;
|
||||||
|
|
||||||
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");
|
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");
|
||||||
|
|
||||||
struct _value_type: public boolean
|
|
||||||
{
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
using _table_set = typename Select::_table_set;
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
static constexpr const char* _get_name() { return "EXISTS"; }
|
static constexpr const char* _get_name() { return "EXISTS"; }
|
||||||
|
@ -41,17 +41,12 @@ namespace sqlpp
|
|||||||
// floating_point value type
|
// floating_point value type
|
||||||
struct floating_point
|
struct floating_point
|
||||||
{
|
{
|
||||||
using _value_type = floating_point;
|
using _tag = ::sqlpp::tag::floating_point;
|
||||||
using _base_value_type = floating_point;
|
|
||||||
using _is_numeric = std::true_type;
|
|
||||||
using _is_floating_point = std::true_type;
|
|
||||||
using _is_value = std::true_type;
|
|
||||||
using _is_expression = std::true_type;
|
|
||||||
using _cpp_value_type = double;
|
using _cpp_value_type = double;
|
||||||
|
|
||||||
struct _parameter_t
|
struct _parameter_t
|
||||||
{
|
{
|
||||||
using _value_type = integral;
|
using _value_type = floating_point;
|
||||||
|
|
||||||
_parameter_t():
|
_parameter_t():
|
||||||
_value(0),
|
_value(0),
|
||||||
|
@ -48,16 +48,17 @@ namespace sqlpp
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
auto value(T t) -> vendor::wrap_operand_t<T>
|
auto value(T t) -> vendor::wrap_operand_t<T>
|
||||||
{
|
{
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _provided_tables = detail::type_set<>;
|
||||||
static_assert(not is_value_t<T>::value, "value() is to be called with non-sql-type like int, or string");
|
using _required_tables = ::sqlpp::detail::type_set<>;
|
||||||
|
static_assert(not is_expression_t<T>::value, "value() is to be called with non-sql-type like int, or string");
|
||||||
return { t };
|
return { t };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim
|
template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim
|
||||||
struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>
|
struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>
|
||||||
{
|
{
|
||||||
using _value_type = ValueType;
|
using _traits = make_traits<ValueType, ::sqlpp::tag::expression>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
verbatim_t(std::string verbatim): _verbatim(verbatim) {}
|
verbatim_t(std::string verbatim): _verbatim(verbatim) {}
|
||||||
verbatim_t(const verbatim_t&) = default;
|
verbatim_t(const verbatim_t&) = default;
|
||||||
@ -91,7 +92,7 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression, typename Context>
|
template<typename Expression, typename Context>
|
||||||
auto flatten(const Expression& exp, const Context& context) -> verbatim_t<typename Expression::_value_type::_base_value_type>
|
auto flatten(const Expression& exp, const Context& context) -> verbatim_t<value_type_of<Expression>>
|
||||||
{
|
{
|
||||||
static_assert(not make_parameter_list_t<Expression>::type::size::value, "parameters not supported in flattened expressions");
|
static_assert(not make_parameter_list_t<Expression>::type::size::value, "parameters not supported in flattened expressions");
|
||||||
context.clear();
|
context.clear();
|
||||||
@ -102,9 +103,10 @@ namespace sqlpp
|
|||||||
template<typename Container>
|
template<typename Container>
|
||||||
struct value_list_t // to be used in .in() method
|
struct value_list_t // to be used in .in() method
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<vendor::value_type_t<typename Container::value_type>>;
|
||||||
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
using _container_t = Container;
|
using _container_t = Container;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;// FIXME: Could it be something else?
|
|
||||||
using _value_type = vendor::value_type_t<typename _container_t::value_type>;
|
|
||||||
|
|
||||||
value_list_t(_container_t container):
|
value_list_t(_container_t container):
|
||||||
_container(container)
|
_container(container)
|
||||||
@ -146,7 +148,7 @@ namespace sqlpp
|
|||||||
template<typename Container>
|
template<typename Container>
|
||||||
auto value_list(Container c) -> value_list_t<Container>
|
auto value_list(Container c) -> value_list_t<Container>
|
||||||
{
|
{
|
||||||
static_assert(not is_value_t<typename Container::value_type>::value, "value_list() is to be called with a container of non-sql-type like std::vector<int>, or std::list(string)");
|
static_assert(not is_expression_t<typename Container::value_type>::value, "value_list() is to be called with a container of non-sql-type like std::vector<int>, or std::list(string)");
|
||||||
return { c };
|
return { c };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,78 +35,84 @@
|
|||||||
#include <sqlpp11/vendor/single_table.h>
|
#include <sqlpp11/vendor/single_table.h>
|
||||||
#include <sqlpp11/vendor/insert_value_list.h>
|
#include <sqlpp11/vendor/insert_value_list.h>
|
||||||
#include <sqlpp11/vendor/policy_update.h>
|
#include <sqlpp11/vendor/policy_update.h>
|
||||||
#include <sqlpp11/detail/arg_selector.h>
|
|
||||||
|
#include <sqlpp11/detail/get_last.h>
|
||||||
|
#include <sqlpp11/detail/pick_arg.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db,
|
template<typename Db, typename... Policies>
|
||||||
typename... Policies
|
|
||||||
>
|
|
||||||
struct insert_t;
|
struct insert_t;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Db,
|
template<typename Db, typename... Policies>
|
||||||
typename Table = vendor::no_single_table_t,
|
|
||||||
typename InsertValueList = vendor::no_insert_value_list_t
|
|
||||||
>
|
|
||||||
struct insert_policies_t
|
struct insert_policies_t
|
||||||
{
|
{
|
||||||
using _database_t = Db;
|
using _database_t = Db;
|
||||||
using _table_t = Table;
|
|
||||||
using _insert_value_list_t = InsertValueList;
|
|
||||||
|
|
||||||
using _statement_t = insert_t<Db, Table, InsertValueList>;
|
using _statement_t = insert_t<Db, Policies...>;
|
||||||
|
|
||||||
struct _methods_t:
|
struct _methods_t: public Policies::template _methods_t<insert_policies_t>...
|
||||||
public _insert_value_list_t::template _methods_t<insert_policies_t>
|
|
||||||
{};
|
{};
|
||||||
|
|
||||||
template<typename Needle, typename Replacement, typename... Policies>
|
template<typename Needle, typename Replacement>
|
||||||
struct _policies_insert_t
|
struct _policies_update_t
|
||||||
{
|
{
|
||||||
|
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
|
||||||
using type = insert_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
|
using type = insert_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Needle, typename Replacement>
|
template<typename Needle, typename Replacement>
|
||||||
using _new_statement_t = typename _policies_insert_t<Needle, Replacement, Table, InsertValueList>::type;
|
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
|
||||||
|
|
||||||
using _table_set = typename _table_t::_table_set;
|
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
||||||
|
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
||||||
|
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
|
||||||
|
|
||||||
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set>;
|
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
|
||||||
|
|
||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
|
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
||||||
|
|
||||||
|
// The tables not covered by the from.
|
||||||
|
using _required_tables = detail::make_difference_set_t<
|
||||||
|
_all_required_tables,
|
||||||
|
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
|
||||||
|
>;
|
||||||
|
|
||||||
|
using _traits = make_traits<no_value_t>; // FIXME
|
||||||
|
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _parameters = std::tuple<>; // FIXME
|
||||||
|
using _required_tables = _required_tables;
|
||||||
|
using _provided_tables = detail::type_set<>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// INSERT
|
// INSERT
|
||||||
template<typename Db,
|
template<typename Db, typename... Policies>
|
||||||
typename... Policies
|
|
||||||
>
|
|
||||||
struct insert_t:
|
struct insert_t:
|
||||||
|
public Policies...,
|
||||||
public detail::insert_policies_t<Db, Policies...>::_methods_t
|
public detail::insert_policies_t<Db, Policies...>::_methods_t
|
||||||
{
|
{
|
||||||
using _policies_t = typename detail::insert_policies_t<Db, Policies...>;
|
using _policies_t = typename detail::insert_policies_t<Db, Policies...>;
|
||||||
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 _insert_value_list_t = typename _policies_t::_insert_value_list_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;
|
||||||
|
|
||||||
using _parameter_tuple_t = std::tuple<Policies...>;
|
|
||||||
using _parameter_list_t = typename make_parameter_list_t<insert_t>::type;
|
using _parameter_list_t = typename make_parameter_list_t<insert_t>::type;
|
||||||
|
|
||||||
static_assert(::sqlpp::detail::is_superset_of<typename _table_t::_table_set, typename _insert_value_list_t::_table_set>::value, "columns do not match the table they are to be inserted into");
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
insert_t()
|
constexpr insert_t()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename Statement, typename T>
|
template<typename Statement, typename Term>
|
||||||
insert_t(Statement s, T t):
|
insert_t(Statement statement, Term term):
|
||||||
_table(detail::arg_selector<_table_t>::_(s._table, t)),
|
Policies(detail::pick_arg<Policies>(statement, term))...
|
||||||
_insert_value_list(detail::arg_selector<_insert_value_list_t>::_(s._insert_value_list, t))
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
insert_t(const insert_t&) = default;
|
insert_t(const insert_t&) = default;
|
||||||
@ -126,12 +132,6 @@ namespace sqlpp
|
|||||||
return _parameter_list_t::size::value;
|
return _parameter_list_t::size::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename A>
|
|
||||||
struct is_table_subset_of_table
|
|
||||||
{
|
|
||||||
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _table_t::_table_set>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
void _check_consistency() const
|
void _check_consistency() const
|
||||||
{
|
{
|
||||||
// FIXME: Read up on what is allowed/prohibited in INSERT
|
// FIXME: Read up on what is allowed/prohibited in INSERT
|
||||||
@ -154,9 +154,6 @@ namespace sqlpp
|
|||||||
|
|
||||||
return {{}, db.prepare_insert(*this)};
|
return {{}, db.prepare_insert(*this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
_insert_value_list_t _insert_value_list;
|
|
||||||
_table_t _table;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace vendor
|
namespace vendor
|
||||||
@ -169,30 +166,45 @@ namespace sqlpp
|
|||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "INSERT INTO ";
|
context << "INSERT INTO ";
|
||||||
serialize(t._table, context);
|
|
||||||
serialize(t._insert_value_list, context);
|
using swallow = int[];
|
||||||
|
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename... Policies>
|
template<typename Database>
|
||||||
using make_insert_t = typename detail::insert_policies_t<Database, Policies...>::_statement_t;
|
using blank_insert_t = insert_t<Database,
|
||||||
|
vendor::no_single_table_t,
|
||||||
|
vendor::no_insert_value_list_t>;
|
||||||
|
|
||||||
|
constexpr auto insert()
|
||||||
|
-> blank_insert_t<void>
|
||||||
|
{
|
||||||
|
return { blank_insert_t<void>() };
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Table>
|
template<typename Table>
|
||||||
constexpr auto insert_into(Table table)
|
constexpr auto insert_into(Table table)
|
||||||
-> make_insert_t<void, vendor::single_table_t<void, Table>>
|
-> decltype(blank_insert_t<void>().into(table))
|
||||||
{
|
{
|
||||||
return { make_insert_t<void>(), vendor::single_table_t<void, Table>{table} };
|
return { blank_insert_t<void>().into(table) };
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Database>
|
||||||
|
constexpr auto dynamic_insert(const Database&)
|
||||||
|
-> decltype(blank_insert_t<Database>())
|
||||||
|
{
|
||||||
|
return { blank_insert_t<Database>() };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename Table>
|
template<typename Database, typename Table>
|
||||||
constexpr auto dynamic_insert_into(const Database&, Table table)
|
constexpr auto dynamic_insert_into(const Database&, Table table)
|
||||||
-> make_insert_t<Database, vendor::single_table_t<void, Table>>
|
-> decltype(blank_insert_t<Database>().into(table))
|
||||||
{
|
{
|
||||||
return { make_insert_t<Database>(), vendor::single_table_t<void, Table>{table} };
|
return { blank_insert_t<Database>().into(table) };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,15 +42,9 @@ namespace sqlpp
|
|||||||
// integral value type
|
// integral value type
|
||||||
struct integral
|
struct integral
|
||||||
{
|
{
|
||||||
using _value_type = integral;
|
using _tag = ::sqlpp::tag::integral;
|
||||||
using _base_value_type = integral;
|
|
||||||
using _is_numeric = std::true_type;
|
|
||||||
using _is_integral = std::true_type;
|
|
||||||
using _is_value = std::true_type;
|
|
||||||
using _is_expression = std::true_type;
|
|
||||||
using _cpp_value_type = int64_t;
|
using _cpp_value_type = int64_t;
|
||||||
|
|
||||||
|
|
||||||
struct _parameter_t
|
struct _parameter_t
|
||||||
{
|
{
|
||||||
using _value_type = integral;
|
using _value_type = integral;
|
||||||
|
@ -77,16 +77,17 @@ namespace sqlpp
|
|||||||
template<typename JoinType, typename Lhs, typename Rhs, typename On = vendor::noop>
|
template<typename JoinType, typename Lhs, typename Rhs, typename On = vendor::noop>
|
||||||
struct join_t
|
struct join_t
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::table, tag::join>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
||||||
|
|
||||||
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
|
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
|
||||||
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
|
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
|
||||||
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
|
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
|
||||||
static_assert(vendor::is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
|
static_assert(vendor::is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
|
||||||
|
|
||||||
static_assert(::sqlpp::detail::is_disjunct_from<typename Lhs::_table_set, typename Rhs::_table_set>::value, "joined tables must not be identical");
|
static_assert(::sqlpp::detail::is_disjunct_from<typename Lhs::_provided_tables, typename Rhs::_provided_tables>::value, "joined tables must not be identical");
|
||||||
|
|
||||||
using _is_table = std::true_type;
|
static_assert(_recursive_traits::_required_tables::size::value == 0, "joined tables must not depend on other tables");
|
||||||
using _is_join = std::true_type;
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
|
|
||||||
|
|
||||||
template<typename OnT>
|
template<typename OnT>
|
||||||
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
|
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
|
||||||
|
@ -34,16 +34,12 @@ namespace sqlpp
|
|||||||
namespace vendor
|
namespace vendor
|
||||||
{
|
{
|
||||||
template<typename Expr>
|
template<typename Expr>
|
||||||
struct max_t: public Expr::_value_type::template expression_operators<max_t<Expr>>
|
struct max_t: public value_type_of<Expr>::template expression_operators<max_t<Expr>>
|
||||||
{
|
{
|
||||||
static_assert(is_value_t<Expr>::value, "max() requires a value expression as argument");
|
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Expr>;
|
||||||
|
|
||||||
struct _value_type: public Expr::_value_type::_base_value_type
|
static_assert(is_expression_t<Expr>::value, "max() requires a value expression as argument");
|
||||||
{
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
using _table_set = typename Expr::_table_set;
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
@ -91,7 +87,7 @@ namespace sqlpp
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
auto max(T t) -> typename vendor::max_t<vendor::wrap_operand_t<T>>
|
auto max(T t) -> typename vendor::max_t<vendor::wrap_operand_t<T>>
|
||||||
{
|
{
|
||||||
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "max() requires a value expression as argument");
|
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "max() requires a value expression as argument");
|
||||||
return { t };
|
return { t };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,16 +34,12 @@ namespace sqlpp
|
|||||||
namespace vendor
|
namespace vendor
|
||||||
{
|
{
|
||||||
template<typename Expr>
|
template<typename Expr>
|
||||||
struct min_t: public Expr::_value_type::template expression_operators<min_t<Expr>>
|
struct min_t: public value_type_of<Expr>::template expression_operators<min_t<Expr>>
|
||||||
{
|
{
|
||||||
static_assert(is_value_t<Expr>::value, "min() requires a value expression as argument");
|
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Expr>;
|
||||||
|
|
||||||
struct _value_type: public Expr::_value_type::_base_value_type
|
static_assert(is_expression_t<Expr>::value, "min() requires a value expression as argument");
|
||||||
{
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
using _table_set = typename Expr::_table_set;
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
@ -91,7 +87,7 @@ namespace sqlpp
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
auto min(T t) -> typename vendor::min_t<vendor::wrap_operand_t<T>>
|
auto min(T t) -> typename vendor::min_t<vendor::wrap_operand_t<T>>
|
||||||
{
|
{
|
||||||
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "min() requires a value expression as argument");
|
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "min() requires a value expression as argument");
|
||||||
return { t };
|
return { t };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,9 +41,10 @@ namespace sqlpp
|
|||||||
template<typename Unused, typename... Columns>
|
template<typename Unused, typename... Columns>
|
||||||
struct multi_column_t
|
struct multi_column_t
|
||||||
{
|
{
|
||||||
static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
|
using _traits = make_traits<no_value_t>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Columns...>;
|
||||||
|
|
||||||
using _table_set = sqlpp::detail::make_joined_set_t<typename Columns::_table_set...>;
|
static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
|
||||||
|
|
||||||
multi_column_t(std::tuple<Columns...> columns):
|
multi_column_t(std::tuple<Columns...> columns):
|
||||||
_columns(columns)
|
_columns(columns)
|
||||||
@ -75,10 +76,12 @@ namespace sqlpp
|
|||||||
template<typename AliasProvider, typename... Columns>
|
template<typename AliasProvider, typename... Columns>
|
||||||
struct multi_column_alias_t
|
struct multi_column_alias_t
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::alias, tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Columns...>;
|
||||||
|
|
||||||
static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
|
static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
|
||||||
|
|
||||||
using _name_t = typename AliasProvider::_name_t;
|
using _name_t = typename AliasProvider::_name_t;
|
||||||
using _table_set = sqlpp::detail::make_joined_set_t<typename Columns::_table_set...>;
|
|
||||||
|
|
||||||
multi_column_alias_t(multi_column_t<void, Columns...> multi_column):
|
multi_column_alias_t(multi_column_t<void, Columns...> multi_column):
|
||||||
_columns(multi_column._columns)
|
_columns(multi_column._columns)
|
||||||
|
@ -33,11 +33,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct no_value_t
|
struct no_value_t
|
||||||
{
|
{
|
||||||
template<typename T>
|
using _tag = void;
|
||||||
using _constraint = std::false_type;
|
|
||||||
|
|
||||||
using _base_value_type = no_value_t;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct _is_valid_operand
|
struct _is_valid_operand
|
||||||
{
|
{
|
||||||
|
@ -33,9 +33,8 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct null_t
|
struct null_t
|
||||||
{
|
{
|
||||||
static constexpr bool _is_expression = true;
|
using _traits = make_traits<no_value_t, tag::expression>;
|
||||||
using _value_type = no_value_t;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace vendor
|
namespace vendor
|
||||||
|
@ -37,7 +37,9 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Expr>
|
template<typename Database, typename... Expr>
|
||||||
struct on_t
|
struct on_t
|
||||||
{
|
{
|
||||||
using _is_on = std::true_type;
|
using _traits = make_traits<no_value_t, tag::on>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Expr...>;
|
||||||
|
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()");
|
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()");
|
||||||
|
@ -36,14 +36,16 @@ namespace sqlpp
|
|||||||
template<typename ValueType, typename NameType>
|
template<typename ValueType, typename NameType>
|
||||||
struct parameter_t: public ValueType::template expression_operators<parameter_t<ValueType, NameType>>
|
struct parameter_t: public ValueType::template expression_operators<parameter_t<ValueType, NameType>>
|
||||||
{
|
{
|
||||||
struct _value_type: public ValueType
|
using _traits = make_traits<ValueType, tag::parameter, tag::expression>;
|
||||||
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
using _is_expression = std::true_type;
|
using _parameters = std::tuple<parameter_t>;
|
||||||
using _is_alias = std::false_type;
|
using _provided_tables = detail::type_set<>;
|
||||||
|
using _required_tables = detail::type_set<>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
};
|
};
|
||||||
using _is_parameter = std::true_type;
|
|
||||||
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>;
|
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>;
|
||||||
using _table_set = sqlpp::detail::type_set<>;
|
|
||||||
|
|
||||||
parameter_t()
|
parameter_t()
|
||||||
{}
|
{}
|
||||||
@ -82,7 +84,7 @@ namespace sqlpp
|
|||||||
auto parameter(const ValueType&, const AliasProvider&)
|
auto parameter(const ValueType&, const AliasProvider&)
|
||||||
-> parameter_t<ValueType, AliasProvider>
|
-> parameter_t<ValueType, AliasProvider>
|
||||||
{
|
{
|
||||||
static_assert(is_value_t<ValueType>::value, "first argument is not a value type");
|
static_assert(is_expression_t<ValueType>::value, "first argument is not a value type");
|
||||||
static_assert(is_alias_provider_t<AliasProvider>::value, "second argument is not an alias provider");
|
static_assert(is_alias_provider_t<AliasProvider>::value, "second argument is not an alias provider");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -31,88 +31,89 @@
|
|||||||
#include <sqlpp11/parameter_list.h>
|
#include <sqlpp11/parameter_list.h>
|
||||||
#include <sqlpp11/prepared_remove.h>
|
#include <sqlpp11/prepared_remove.h>
|
||||||
#include <sqlpp11/vendor/noop.h>
|
#include <sqlpp11/vendor/noop.h>
|
||||||
|
#warning: need to use another table provider, since delete can be used with several tables
|
||||||
#include <sqlpp11/vendor/single_table.h>
|
#include <sqlpp11/vendor/single_table.h>
|
||||||
#include <sqlpp11/vendor/extra_tables.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>
|
||||||
#include <sqlpp11/detail/arg_selector.h>
|
|
||||||
|
#include <sqlpp11/detail/get_last.h>
|
||||||
|
#include <sqlpp11/detail/pick_arg.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db,
|
template<typename Db, typename... Policies>
|
||||||
typename... Policies
|
|
||||||
>
|
|
||||||
struct remove_t;
|
struct remove_t;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Db = void,
|
template<typename Db = void, typename... Policies>
|
||||||
typename Table = vendor::no_single_table_t,
|
|
||||||
typename Using = vendor::no_using_t,
|
|
||||||
typename ExtraTables = vendor::no_extra_tables_t,
|
|
||||||
typename Where = vendor::no_where_t
|
|
||||||
>
|
|
||||||
struct remove_policies_t
|
struct remove_policies_t
|
||||||
{
|
{
|
||||||
using _database_t = Db;
|
using _database_t = Db;
|
||||||
using _table_t = Table;
|
using _statement_t = remove_t<Db, Policies...>;
|
||||||
using _using_t = Using;
|
|
||||||
using _extra_tables_t = ExtraTables;
|
|
||||||
using _where_t = Where;
|
|
||||||
|
|
||||||
using _statement_t = remove_t<Db, Table, Using, ExtraTables, Where>;
|
struct _methods_t: public Policies::template _methods_t<remove_policies_t>...
|
||||||
|
|
||||||
struct _methods_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>
|
|
||||||
{};
|
{};
|
||||||
|
|
||||||
template<typename Needle, typename Replacement, typename... Policies>
|
template<typename Needle, typename Replacement>
|
||||||
struct _policies_update_t
|
struct _policies_update_t
|
||||||
{
|
{
|
||||||
|
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
|
||||||
using type = remove_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
|
using type = remove_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Needle, typename Replacement>
|
template<typename Needle, typename Replacement>
|
||||||
using _new_statement_t = typename _policies_update_t<Needle, Replacement, Table, Using, ExtraTables, Where>::type;
|
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::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>;
|
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
||||||
|
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
||||||
|
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
|
||||||
|
|
||||||
|
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
|
||||||
|
|
||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
|
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
||||||
|
|
||||||
|
// The tables not covered by the from.
|
||||||
|
using _required_tables = detail::make_difference_set_t<
|
||||||
|
_all_required_tables,
|
||||||
|
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
|
||||||
|
>;
|
||||||
|
|
||||||
|
using _traits = make_traits<no_value_t>; // FIXME
|
||||||
|
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _parameters = std::tuple<>; // FIXME
|
||||||
|
using _required_tables = _required_tables;
|
||||||
|
using _provided_tables = detail::type_set<>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// REMOVE
|
// REMOVE
|
||||||
template<typename Db,
|
template<typename Db, typename... Policies>
|
||||||
typename... Policies
|
|
||||||
>
|
|
||||||
struct remove_t:
|
struct remove_t:
|
||||||
|
public Policies...,
|
||||||
public detail::remove_policies_t<Db, Policies...>::_methods_t
|
public detail::remove_policies_t<Db, Policies...>::_methods_t
|
||||||
{
|
{
|
||||||
using _policies_t = typename detail::remove_policies_t<Db, Policies...>;
|
using _policies_t = typename detail::remove_policies_t<Db, Policies...>;
|
||||||
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 _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 _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;
|
||||||
|
|
||||||
using _parameter_tuple_t = std::tuple<Policies...>;
|
|
||||||
using _parameter_list_t = typename make_parameter_list_t<remove_t>::type;
|
using _parameter_list_t = typename make_parameter_list_t<remove_t>::type;
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
remove_t()
|
constexpr remove_t()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename Statement, typename T>
|
template<typename Statement, typename Term>
|
||||||
remove_t(Statement s, T t):
|
remove_t(Statement statement, Term term):
|
||||||
_table(detail::arg_selector<_table_t>::_(s._table, t)),
|
Policies(detail::pick_arg<Policies>(statement, term))...
|
||||||
_using(detail::arg_selector<_using_t>::_(s._using, t)),
|
|
||||||
_where(detail::arg_selector<_where_t>::_(s._where, t))
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
remove_t(const remove_t&) = default;
|
remove_t(const remove_t&) = default;
|
||||||
@ -132,18 +133,15 @@ namespace sqlpp
|
|||||||
return _parameter_list_t::size::value;
|
return _parameter_list_t::size::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename A>
|
|
||||||
struct is_table_subset_of_table
|
|
||||||
{
|
|
||||||
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _table_t::_table_set>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
void _check_consistency() const
|
void _check_consistency() const
|
||||||
{
|
{
|
||||||
|
#warning reactivate checks
|
||||||
|
#if 0
|
||||||
static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
|
static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
|
||||||
|
|
||||||
// FIXME: Read more details about what is allowed and what not in SQL DELETE
|
// FIXME: Read more details about what is allowed and what not in SQL DELETE
|
||||||
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
|
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database>
|
template<typename Database>
|
||||||
@ -163,10 +161,6 @@ namespace sqlpp
|
|||||||
|
|
||||||
return {{}, db.prepare_remove(*this)};
|
return {{}, db.prepare_remove(*this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
_table_t _table;
|
|
||||||
_using_t _using;
|
|
||||||
_where_t _where;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace vendor
|
namespace vendor
|
||||||
@ -179,31 +173,46 @@ namespace sqlpp
|
|||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "DELETE FROM ";
|
context << "DELETE FROM ";
|
||||||
serialize(t._table, context);
|
using swallow = int[];
|
||||||
serialize(t._using, context);
|
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
|
||||||
serialize(t._where, context);
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename... Policies>
|
template<typename Database>
|
||||||
using make_remove_t = typename detail::remove_policies_t<Database, Policies...>::_statement_t;
|
using blank_remove_t = remove_t<Database,
|
||||||
|
vendor::no_single_table_t,
|
||||||
|
vendor::no_using_t,
|
||||||
|
vendor::no_extra_tables_t,
|
||||||
|
vendor::no_where_t>;
|
||||||
|
|
||||||
|
constexpr auto remove()
|
||||||
|
-> blank_remove_t<void>
|
||||||
|
{
|
||||||
|
return { blank_remove_t<void>() };
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Table>
|
template<typename Table>
|
||||||
constexpr auto remove_from(Table table)
|
constexpr auto remove_from(Table table)
|
||||||
-> make_remove_t<void, vendor::single_table_t<void, Table>>
|
-> decltype(blank_remove_t<void>().from(table))
|
||||||
{
|
{
|
||||||
return { make_remove_t<void>(), vendor::single_table_t<void, Table>{table} };
|
return { blank_remove_t<void>().from(table) };
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Database>
|
||||||
|
constexpr auto dynamic_remove(const Database&)
|
||||||
|
-> decltype(blank_remove_t<Database>())
|
||||||
|
{
|
||||||
|
return { blank_remove_t<Database>() };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename Table>
|
template<typename Database, typename Table>
|
||||||
constexpr auto dynamic_remove_from(const Database&, Table table)
|
constexpr auto dynamic_remove_from(const Database&, Table table)
|
||||||
-> make_remove_t<Database, vendor::single_table_t<void, Table>>
|
-> decltype(blank_remove_t<Database>().from(table))
|
||||||
{
|
{
|
||||||
return { make_remove_t<Database>(), vendor::single_table_t<void, Table>{table} };
|
return { blank_remove_t<Database>().from(table) };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,9 +42,9 @@ namespace sqlpp
|
|||||||
|
|
||||||
template<typename Db, std::size_t index, typename NamedExpr>
|
template<typename Db, std::size_t index, typename NamedExpr>
|
||||||
struct result_field:
|
struct result_field:
|
||||||
public NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>
|
public NamedExpr::_name_t::template _member_t<typename value_type_of<NamedExpr>::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>
|
||||||
{
|
{
|
||||||
using _field = typename NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>;
|
using _field = typename NamedExpr::_name_t::template _member_t<typename value_type_of<NamedExpr>::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>;
|
||||||
|
|
||||||
result_field() = default;
|
result_field() = default;
|
||||||
result_field(const char_result_row_t& char_result_row_t):
|
result_field(const char_result_row_t& char_result_row_t):
|
||||||
|
@ -47,59 +47,28 @@
|
|||||||
#include <sqlpp11/vendor/wrong.h>
|
#include <sqlpp11/vendor/wrong.h>
|
||||||
#include <sqlpp11/vendor/policy_update.h>
|
#include <sqlpp11/vendor/policy_update.h>
|
||||||
|
|
||||||
#include <sqlpp11/detail/arg_selector.h>
|
#include <sqlpp11/detail/get_last.h>
|
||||||
|
#include <sqlpp11/detail/pick_arg.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db,
|
template<typename Db, typename... Policies>
|
||||||
typename... Policies
|
|
||||||
>
|
|
||||||
struct select_t;
|
struct select_t;
|
||||||
|
|
||||||
|
#warning STEPS:
|
||||||
|
#warning deal with different return types in the connector (select could be a single value, update could be a range of rows)
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Db = void,
|
template<typename Db = void, typename... Policies>
|
||||||
typename FlagList = vendor::no_select_flag_list_t,
|
|
||||||
typename ColumnList = vendor::no_select_column_list_t,
|
|
||||||
typename From = vendor::no_from_t,
|
|
||||||
typename ExtraTables = vendor::no_extra_tables_t,
|
|
||||||
typename Where = vendor::no_where_t,
|
|
||||||
typename GroupBy = vendor::no_group_by_t,
|
|
||||||
typename Having = vendor::no_having_t,
|
|
||||||
typename OrderBy = vendor::no_order_by_t,
|
|
||||||
typename Limit = vendor::no_limit_t,
|
|
||||||
typename Offset = vendor::no_offset_t
|
|
||||||
>
|
|
||||||
struct select_policies_t
|
struct select_policies_t
|
||||||
{
|
{
|
||||||
using _database_t = Db;
|
using _database_t = Db;
|
||||||
using _flag_list_t = FlagList;
|
using _statement_t = select_t<Db, Policies...>;
|
||||||
using _column_list_t = ColumnList;
|
|
||||||
using _from_t = From;
|
|
||||||
using _extra_tables_t = ExtraTables;
|
|
||||||
using _where_t = Where;
|
|
||||||
using _group_by_t = GroupBy;
|
|
||||||
using _having_t = Having;
|
|
||||||
using _order_by_t = OrderBy;
|
|
||||||
using _limit_t = Limit;
|
|
||||||
using _offset_t = Offset;
|
|
||||||
|
|
||||||
using _statement_t = select_t<Db, FlagList, ColumnList, From, ExtraTables, Where, GroupBy, Having, OrderBy, Limit, Offset>;
|
struct _methods_t: public Policies::template _methods_t<select_policies_t>...
|
||||||
|
|
||||||
struct _methods_t:
|
|
||||||
public _flag_list_t::template _methods_t<select_policies_t>,
|
|
||||||
public _column_list_t::template _methods_t<select_policies_t>,
|
|
||||||
public _from_t::template _methods_t<select_policies_t>,
|
|
||||||
public _extra_tables_t::template _methods_t<select_policies_t>,
|
|
||||||
public _where_t::template _methods_t<select_policies_t>,
|
|
||||||
public _group_by_t::template _methods_t<select_policies_t>,
|
|
||||||
public _having_t::template _methods_t<select_policies_t>,
|
|
||||||
public _order_by_t::template _methods_t<select_policies_t>,
|
|
||||||
public _limit_t::template _methods_t<select_policies_t>,
|
|
||||||
public _offset_t::template _methods_t<select_policies_t>
|
|
||||||
{};
|
{};
|
||||||
|
|
||||||
template<typename Needle, typename Replacement, typename... Policies>
|
template<typename Needle, typename Replacement>
|
||||||
struct _policies_update_t
|
struct _policies_update_t
|
||||||
{
|
{
|
||||||
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
|
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
|
||||||
@ -107,48 +76,55 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Needle, typename Replacement>
|
template<typename Needle, typename Replacement>
|
||||||
using _new_statement_t = typename _policies_update_t<Needle, Replacement, FlagList, ColumnList, From, ExtraTables, Where, GroupBy, Having, OrderBy, Limit, Offset>::type;
|
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
|
||||||
|
|
||||||
static_assert(is_noop_t<ColumnList>::value or sqlpp::is_select_column_list_t<ColumnList>::value, "column list of select is neither naught nor a valid column list");
|
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
||||||
static_assert(is_noop_t<From>::value or sqlpp::is_from_t<From>::value, "from() part of select is neither naught nor a valid from()");
|
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
||||||
|
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
|
||||||
|
|
||||||
using _known_tables = detail::make_joined_set_t<typename _from_t::_table_set, typename _extra_tables_t::_table_set>;
|
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
|
||||||
|
|
||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
|
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
||||||
|
|
||||||
using _required_tables =
|
|
||||||
detail::make_joined_set_t<
|
|
||||||
typename _flag_list_t::_table_set,
|
|
||||||
typename _column_list_t::_table_set,
|
|
||||||
typename _where_t::_table_set,
|
|
||||||
typename _group_by_t::_table_set,
|
|
||||||
typename _having_t::_table_set,
|
|
||||||
typename _order_by_t::_table_set,
|
|
||||||
typename _limit_t::_table_set,
|
|
||||||
typename _offset_t::_table_set
|
|
||||||
>;
|
|
||||||
|
|
||||||
// The tables not covered by the from.
|
// The tables not covered by the from.
|
||||||
using _table_set = detail::make_difference_set_t<
|
using _required_tables = detail::make_difference_set_t<
|
||||||
_required_tables,
|
_all_required_tables,
|
||||||
typename _from_t::_table_set // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity
|
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
using _result_type_provider = detail::get_last_if<is_return_value_t, vendor::no_select_column_list_t, Policies...>;
|
||||||
|
|
||||||
// A select can be used as a pseudo table if
|
// A select can be used as a pseudo table if
|
||||||
// - at least one column is selected
|
// - at least one column is selected
|
||||||
// - the select is complete (leaks no tables)
|
// - the select is complete (leaks no tables)
|
||||||
using _can_be_used_as_table = typename std::conditional<
|
using _can_be_used_as_table = typename std::conditional<
|
||||||
is_select_column_list_t<_column_list_t>::value and _table_set::size::value == 0,
|
is_select_column_list_t<_result_type_provider>::value and _required_tables::size::value == 0,
|
||||||
std::true_type,
|
std::true_type,
|
||||||
std::false_type
|
std::false_type
|
||||||
>::type;
|
>::type;
|
||||||
|
|
||||||
using _value_type = typename std::conditional<
|
using _value_type = typename std::conditional<
|
||||||
is_select_column_list_t<_column_list_t>::value and is_subset_of<typename _column_list_t::_table_set, typename _from_t::_table_set>::value,
|
detail::none_t<is_missing_t<Policies>::value...>::value,
|
||||||
typename ColumnList::_value_type,
|
value_type_of<_result_type_provider>,
|
||||||
no_value_t // If something is selected that requires a table, then we require a from for this to be a value
|
no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value
|
||||||
>::type;
|
>::type;
|
||||||
|
|
||||||
|
using _is_expression = typename std::conditional<
|
||||||
|
std::is_same<_value_type, no_value_t>::value,
|
||||||
|
std::false_type,
|
||||||
|
std::true_type>::type;
|
||||||
|
|
||||||
|
using _traits = make_traits<_value_type>;
|
||||||
|
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _parameters = std::tuple<>; // FIXME
|
||||||
|
using _required_tables = _required_tables;
|
||||||
|
using _provided_tables = detail::type_set<>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,53 +133,38 @@ namespace sqlpp
|
|||||||
typename... Policies
|
typename... Policies
|
||||||
>
|
>
|
||||||
struct select_t:
|
struct select_t:
|
||||||
|
public Policies...,
|
||||||
public detail::select_policies_t<Db, Policies...>::_value_type::template expression_operators<select_t<Db, Policies...>>,
|
public detail::select_policies_t<Db, Policies...>::_value_type::template expression_operators<select_t<Db, Policies...>>,
|
||||||
public detail::select_policies_t<Db, Policies...>::_methods_t
|
public detail::select_policies_t<Db, Policies...>::_methods_t
|
||||||
{
|
{
|
||||||
using _policies_t = typename detail::select_policies_t<Db, Policies...>;
|
using _policies_t = typename detail::select_policies_t<Db, Policies...>;
|
||||||
using _database_t = typename _policies_t::_database_t;
|
|
||||||
using _flag_list_t = typename _policies_t::_flag_list_t;
|
|
||||||
using _column_list_t = typename _policies_t::_column_list_t;
|
|
||||||
using _from_t = typename _policies_t::_from_t;
|
|
||||||
using _extra_tables_t = typename _policies_t::_extra_tables_t;
|
|
||||||
using _where_t = typename _policies_t::_where_t;
|
|
||||||
using _group_by_t = typename _policies_t::_group_by_t;
|
|
||||||
using _having_t = typename _policies_t::_having_t;
|
|
||||||
using _order_by_t = typename _policies_t::_order_by_t;
|
|
||||||
using _limit_t = typename _policies_t::_limit_t;
|
|
||||||
using _offset_t = typename _policies_t::_offset_t;
|
|
||||||
|
|
||||||
|
using _traits = make_traits<value_type_of<_policies_t>, ::sqlpp::tag::select, tag::expression_if<typename _policies_t::_is_expression>, tag::named_expression_if<typename _policies_t::_is_expression>>;
|
||||||
|
using _recursive_traits = typename _policies_t::_recursive_traits;
|
||||||
|
|
||||||
|
using _database_t = Db;
|
||||||
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;
|
||||||
|
|
||||||
|
using _result_type_provider = typename _policies_t::_result_type_provider;
|
||||||
|
|
||||||
using _parameter_tuple_t = std::tuple<Policies...>;
|
using _parameter_tuple_t = std::tuple<Policies...>;
|
||||||
using _parameter_list_t = typename make_parameter_list_t<select_t>::type;
|
using _parameter_list_t = typename make_parameter_list_t<select_t>::type;
|
||||||
using _table_set = typename _policies_t::_table_set;
|
|
||||||
|
|
||||||
template<typename Database>
|
template<typename Database>
|
||||||
using _result_row_t = typename _column_list_t::template _result_row_t<Database>;
|
using _result_row_t = typename _result_type_provider::template _result_row_t<Database>;
|
||||||
using _dynamic_names_t = typename _column_list_t::_dynamic_names_t;
|
using _dynamic_names_t = typename _result_type_provider::_dynamic_names_t;
|
||||||
|
|
||||||
using _is_select = std::true_type;
|
|
||||||
using _requires_braces = std::true_type;
|
using _requires_braces = std::true_type;
|
||||||
|
|
||||||
using _value_type = typename detail::select_policies_t<Db, Policies...>::_value_type;
|
using _name_t = typename _result_type_provider::_name_t;
|
||||||
using _name_t = typename _column_list_t::_name_t;
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
select_t()
|
select_t()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename Statement, typename T>
|
template<typename Statement, typename Term>
|
||||||
select_t(Statement s, T t):
|
select_t(Statement statement, Term term):
|
||||||
_flag_list(detail::arg_selector<_flag_list_t>::_(s._flag_list, t)),
|
Policies(detail::pick_arg<Policies>(statement, term))...
|
||||||
_column_list(detail::arg_selector<_column_list_t>::_(s._column_list, t)),
|
|
||||||
_from(detail::arg_selector<_from_t>::_(s._from, t)),
|
|
||||||
_where(detail::arg_selector<_where_t>::_(s._where, t)),
|
|
||||||
_group_by(detail::arg_selector<_group_by_t>::_(s._group_by, t)),
|
|
||||||
_having(detail::arg_selector<_having_t>::_(s._having, t)),
|
|
||||||
_order_by(detail::arg_selector<_order_by_t>::_(s._order_by, t)),
|
|
||||||
_limit(detail::arg_selector<_limit_t>::_(s._limit, t)),
|
|
||||||
_offset(detail::arg_selector<_offset_t>::_(s._offset, t))
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
select_t(const select_t& r) = default;
|
select_t(const select_t& r) = default;
|
||||||
@ -216,7 +177,7 @@ namespace sqlpp
|
|||||||
template<typename AliasProvider>
|
template<typename AliasProvider>
|
||||||
struct _pseudo_table_t
|
struct _pseudo_table_t
|
||||||
{
|
{
|
||||||
using table = typename _column_list_t::template _pseudo_table_t<select_t>;
|
using table = typename _result_type_provider::template _pseudo_table_t<select_t>;
|
||||||
using alias = typename table::template _alias_t<AliasProvider>;
|
using alias = typename table::template _alias_t<AliasProvider>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -230,7 +191,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
const _dynamic_names_t& get_dynamic_names() const
|
const _dynamic_names_t& get_dynamic_names() const
|
||||||
{
|
{
|
||||||
return _column_list._dynamic_columns._dynamic_expression_names;
|
return static_cast<const _result_type_provider&>(*this)._dynamic_columns._dynamic_expression_names;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr size_t _get_static_no_of_parameters()
|
static constexpr size_t _get_static_no_of_parameters()
|
||||||
@ -245,28 +206,13 @@ namespace sqlpp
|
|||||||
|
|
||||||
size_t get_no_of_result_columns() const
|
size_t get_no_of_result_columns() const
|
||||||
{
|
{
|
||||||
return _column_list_t::static_size() + get_dynamic_names().size();
|
return _result_type_provider::static_size() + get_dynamic_names().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename A>
|
|
||||||
struct is_table_subset_of_from
|
|
||||||
{
|
|
||||||
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _from_t::_table_set>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
void _check_consistency() const
|
void _check_consistency() const
|
||||||
{
|
{
|
||||||
static_assert(is_select_column_list_t<_column_list_t>::value, "no columns selected");
|
#warning check for missing terms here, and for missing tables
|
||||||
|
static_assert(not required_tables_of<_policies_t>::size::value, "one sub expression contains tables which are not in the from()");
|
||||||
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
|
||||||
@ -289,16 +235,6 @@ namespace sqlpp
|
|||||||
|
|
||||||
return {{}, get_dynamic_names(), db.prepare_select(*this)};
|
return {{}, get_dynamic_names(), db.prepare_select(*this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
_flag_list_t _flag_list;
|
|
||||||
_column_list_t _column_list;
|
|
||||||
_from_t _from;
|
|
||||||
_where_t _where;
|
|
||||||
_group_by_t _group_by;
|
|
||||||
_having_t _having;
|
|
||||||
_order_by_t _order_by;
|
|
||||||
_limit_t _limit;
|
|
||||||
_offset_t _offset;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace vendor
|
namespace vendor
|
||||||
@ -312,47 +248,51 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
context << "SELECT ";
|
context << "SELECT ";
|
||||||
|
|
||||||
serialize(t._flag_list, context);
|
using swallow = int[];
|
||||||
serialize(t._column_list, context);
|
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
|
||||||
serialize(t._from, context);
|
|
||||||
serialize(t._where, context);
|
|
||||||
serialize(t._group_by, context);
|
|
||||||
serialize(t._having, context);
|
|
||||||
serialize(t._order_by, context);
|
|
||||||
serialize(t._limit, context);
|
|
||||||
serialize(t._offset, context);
|
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename... Policies>
|
template<typename Database>
|
||||||
using make_select_t = typename detail::select_policies_t<Database, Policies...>::_statement_t;
|
using blank_select_t = select_t<Database,
|
||||||
|
vendor::no_select_flag_list_t,
|
||||||
|
vendor::no_select_column_list_t,
|
||||||
|
vendor::no_from_t,
|
||||||
|
vendor::no_extra_tables_t,
|
||||||
|
vendor::no_where_t,
|
||||||
|
vendor::no_group_by_t,
|
||||||
|
vendor::no_having_t,
|
||||||
|
vendor::no_order_by_t,
|
||||||
|
vendor::no_limit_t,
|
||||||
|
vendor::no_offset_t>;
|
||||||
|
|
||||||
make_select_t<void> select() // FIXME: These should be constexpr
|
|
||||||
|
blank_select_t<void> select() // FIXME: These should be constexpr
|
||||||
{
|
{
|
||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Columns>
|
template<typename... Columns>
|
||||||
auto select(Columns... columns)
|
auto select(Columns... columns)
|
||||||
-> make_select_t<void, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>>
|
-> decltype(blank_select_t<void>().columns(columns...))
|
||||||
{
|
{
|
||||||
return { make_select_t<void>(), detail::make_select_column_list_t<void, Columns...>{std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)} };
|
return blank_select_t<void>().columns(columns...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database>
|
template<typename Database>
|
||||||
make_select_t<Database> dynamic_select(const Database&)
|
blank_select_t<Database> dynamic_select(const Database&)
|
||||||
{
|
{
|
||||||
return { make_select_t<Database>() };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename... Columns>
|
template<typename Database, typename... Columns>
|
||||||
auto dynamic_select(const Database&, Columns... columns)
|
auto dynamic_select(const Database&, Columns... columns)
|
||||||
-> make_select_t<Database, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>>
|
-> decltype(blank_select_t<Database>().columns(columns...))
|
||||||
{
|
{
|
||||||
return { make_select_t<Database>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) };
|
return blank_select_t<Database>().columns(columns...);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,11 +37,8 @@ namespace sqlpp
|
|||||||
// standard select flags
|
// standard select flags
|
||||||
struct all_t
|
struct all_t
|
||||||
{
|
{
|
||||||
struct _value_type
|
using _traits = make_traits<no_value_t, tag::select_flag>;
|
||||||
{
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
using _is_select_flag = std::true_type;
|
|
||||||
};
|
|
||||||
using _table_set = detail::type_set<>;
|
|
||||||
};
|
};
|
||||||
static constexpr all_t all = {};
|
static constexpr all_t all = {};
|
||||||
|
|
||||||
@ -60,11 +57,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct distinct_t
|
struct distinct_t
|
||||||
{
|
{
|
||||||
struct _value_type
|
using _traits = make_traits<no_value_t, tag::select_flag>;
|
||||||
{
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
using _is_select_flag = std::true_type;
|
|
||||||
};
|
|
||||||
using _table_set = detail::type_set<>;
|
|
||||||
};
|
};
|
||||||
static constexpr distinct_t distinct = {};
|
static constexpr distinct_t distinct = {};
|
||||||
|
|
||||||
@ -83,11 +77,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct straight_join_t
|
struct straight_join_t
|
||||||
{
|
{
|
||||||
struct _value_type
|
using _traits = make_traits<no_value_t, tag::select_flag>;
|
||||||
{
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
using _is_select_flag = std::true_type;
|
|
||||||
};
|
|
||||||
using _table_set = detail::type_set<>;
|
|
||||||
};
|
};
|
||||||
static constexpr straight_join_t straight_join = {};
|
static constexpr straight_join_t straight_join = {};
|
||||||
|
|
||||||
|
@ -37,11 +37,8 @@ namespace sqlpp
|
|||||||
template<typename Select>
|
template<typename Select>
|
||||||
struct some_t
|
struct some_t
|
||||||
{
|
{
|
||||||
struct _value_type: public Select::_value_type::_base_value_type
|
using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::multi_expression>;
|
||||||
{
|
using _recursive_traits = make_recursive_traits<Select>;
|
||||||
using _is_expression = std::false_type;
|
|
||||||
using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
@ -54,7 +51,6 @@ namespace sqlpp
|
|||||||
const T& operator()() const { return some; }
|
const T& operator()() const { return some; }
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
using _table_set = typename Select::_table_set;
|
|
||||||
|
|
||||||
some_t(Select select):
|
some_t(Select select):
|
||||||
_select(select)
|
_select(select)
|
||||||
@ -91,7 +87,7 @@ namespace sqlpp
|
|||||||
auto some(T t) -> typename vendor::some_t<vendor::wrap_operand_t<T>>
|
auto some(T t) -> typename vendor::some_t<vendor::wrap_operand_t<T>>
|
||||||
{
|
{
|
||||||
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "some() requires a single column select expression as argument");
|
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "some() requires a single column select expression as argument");
|
||||||
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "some() requires a single column select expression as argument");
|
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "some() requires a single column select expression as argument");
|
||||||
return { t };
|
return { t };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,8 @@ namespace sqlpp
|
|||||||
template<typename Expression, sort_type SortType>
|
template<typename Expression, sort_type SortType>
|
||||||
struct sort_order_t
|
struct sort_order_t
|
||||||
{
|
{
|
||||||
using _is_sort_order = std::true_type;
|
using _traits = make_traits<no_value_t, tag::sort_order, sqlpp::tag::expression>;
|
||||||
using _table_set = typename Expression::_table_set;
|
using _recursive_traits = make_recursive_traits<Expression>;
|
||||||
|
|
||||||
Expression _expression;
|
Expression _expression;
|
||||||
};
|
};
|
||||||
|
@ -34,16 +34,14 @@ namespace sqlpp
|
|||||||
namespace vendor
|
namespace vendor
|
||||||
{
|
{
|
||||||
template<typename Flag, typename Expr>
|
template<typename Flag, typename Expr>
|
||||||
struct sum_t: public Expr::_value_type::template expression_operators<sum_t<Flag, Expr>>
|
struct sum_t: public value_type_of<Expr>::template expression_operators<sum_t<Flag, Expr>>
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Expr>;
|
||||||
|
|
||||||
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "sum() used with flag other than 'distinct'");
|
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "sum() used with flag other than 'distinct'");
|
||||||
static_assert(is_numeric_t<Expr>::value, "sum() requires a numeric expression as argument");
|
static_assert(is_numeric_t<Expr>::value, "sum() requires a numeric expression as argument");
|
||||||
|
|
||||||
struct _value_type: public Expr::_value_type::_base_value_type
|
|
||||||
{
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
static constexpr const char* _get_name() { return "SUM"; }
|
static constexpr const char* _get_name() { return "SUM"; }
|
||||||
|
@ -42,14 +42,22 @@ namespace sqlpp
|
|||||||
template<typename Table, typename... ColumnSpec>
|
template<typename Table, typename... ColumnSpec>
|
||||||
struct table_t: public table_base_t, public ColumnSpec::_name_t::template _member_t<column_t<Table, ColumnSpec>>...
|
struct table_t: public table_base_t, public ColumnSpec::_name_t::template _member_t<column_t<Table, ColumnSpec>>...
|
||||||
{
|
{
|
||||||
using _table_set = detail::type_set<Table>; // Hint need a type_set here to be similar to a join (which always represents more than one table)
|
using _traits = make_traits<no_value_t, tag::table>;
|
||||||
|
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _parameters = std::tuple<>;
|
||||||
|
using _required_tables = detail::type_set<>;
|
||||||
|
using _provided_tables = detail::type_set<Table>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
};
|
||||||
|
|
||||||
static_assert(sizeof...(ColumnSpec), "at least one column required per table");
|
static_assert(sizeof...(ColumnSpec), "at least one column required per table");
|
||||||
using _required_insert_columns = typename detail::make_type_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type;
|
using _required_insert_columns = typename detail::make_type_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type;
|
||||||
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
|
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
|
||||||
template<typename AliasProvider>
|
template<typename AliasProvider>
|
||||||
using _alias_t = table_alias_t<AliasProvider, Table, ColumnSpec...>;
|
using _alias_t = table_alias_t<AliasProvider, Table, ColumnSpec...>;
|
||||||
|
|
||||||
using _is_table = std::true_type;
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
join_t<inner_join_t, Table, T> join(T t)
|
join_t<inner_join_t, Table, T> join(T t)
|
||||||
|
@ -41,16 +41,18 @@ namespace sqlpp
|
|||||||
struct table_alias_t: public table_alias_base_t, public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
|
struct table_alias_t: public table_alias_base_t, public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
|
||||||
{
|
{
|
||||||
//FIXME: Need to add join functionality
|
//FIXME: Need to add join functionality
|
||||||
using _is_table = std::true_type;
|
using _traits = make_traits<value_type_of<Table>, tag::table, tag::alias, tag::named_expression_if<is_expression_t<Table>>>;
|
||||||
using _table_set = detail::type_set<AliasProvider>;
|
|
||||||
|
|
||||||
struct _value_type: Table::_value_type
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
using _is_expression = std::false_type;
|
using _parameters = std::tuple<>;
|
||||||
using _is_named_expression = copy_type_trait<Table, is_value_t>;
|
using _required_tables = detail::type_set<>;
|
||||||
using _is_alias = std::true_type;
|
using _provided_tables = detail::type_set<AliasProvider>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static_assert(required_tables_of<Table>::size::value == 0, "table aliases must not depend on external tables");
|
||||||
|
|
||||||
using _name_t = typename AliasProvider::_name_t;
|
using _name_t = typename AliasProvider::_name_t;
|
||||||
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
|
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
|
||||||
|
|
||||||
|
@ -41,11 +41,7 @@ namespace sqlpp
|
|||||||
// text value type
|
// text value type
|
||||||
struct text
|
struct text
|
||||||
{
|
{
|
||||||
using _value_type = text;
|
using _tag = ::sqlpp::tag::text;
|
||||||
using _base_value_type = text;
|
|
||||||
using _is_text = std::true_type;
|
|
||||||
using _is_value = std::true_type;
|
|
||||||
using _is_expression = std::true_type;
|
|
||||||
using _cpp_value_type = std::string;
|
using _cpp_value_type = std::string;
|
||||||
|
|
||||||
struct _parameter_t
|
struct _parameter_t
|
||||||
|
@ -32,15 +32,15 @@
|
|||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/serialize.h>
|
#include <sqlpp11/serialize.h>
|
||||||
#include <sqlpp11/vendor/serializer.h>
|
#include <sqlpp11/vendor/serializer.h>
|
||||||
|
#include <sqlpp11/vendor/wrap_operand.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Operand>
|
template<typename Operand>
|
||||||
struct tvin_t
|
struct tvin_t
|
||||||
{
|
{
|
||||||
using _operand_t = Operand;
|
using _traits = make_traits<value_type_of<Operand>, tag::expression>;
|
||||||
using _value_type = typename _operand_t::_value_type;
|
using _recursive_traits = make_recursive_traits<Operand>;
|
||||||
using _table_set = typename _operand_t::_table_set;
|
|
||||||
|
|
||||||
tvin_t(Operand operand):
|
tvin_t(Operand operand):
|
||||||
_value(operand)
|
_value(operand)
|
||||||
@ -56,7 +56,7 @@ namespace sqlpp
|
|||||||
return _value._is_trivial();
|
return _value._is_trivial();
|
||||||
}
|
}
|
||||||
|
|
||||||
_operand_t _value;
|
Operand _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace vendor
|
namespace vendor
|
||||||
@ -73,17 +73,19 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename Operand>
|
||||||
struct maybe_tvin_t
|
struct maybe_tvin_t
|
||||||
{
|
{
|
||||||
using _table_set = typename T::_table_set;
|
using _traits = make_traits<value_type_of<Operand>, tag::expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Operand>;
|
||||||
|
|
||||||
static constexpr bool _is_trivial()
|
static constexpr bool _is_trivial()
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
maybe_tvin_t(T t):
|
maybe_tvin_t(Operand operand):
|
||||||
_value(t)
|
_value(operand)
|
||||||
{}
|
{}
|
||||||
maybe_tvin_t(const maybe_tvin_t&) = default;
|
maybe_tvin_t(const maybe_tvin_t&) = default;
|
||||||
maybe_tvin_t(maybe_tvin_t&&) = default;
|
maybe_tvin_t(maybe_tvin_t&&) = default;
|
||||||
@ -91,20 +93,22 @@ namespace sqlpp
|
|||||||
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
|
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
|
||||||
~maybe_tvin_t() = default;
|
~maybe_tvin_t() = default;
|
||||||
|
|
||||||
T _value;
|
Operand _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename Operand>
|
||||||
struct maybe_tvin_t<tvin_t<T>>
|
struct maybe_tvin_t<tvin_t<Operand>>
|
||||||
{
|
{
|
||||||
using _table_set = typename T::_table_set;
|
using _traits = make_traits<value_type_of<Operand>, tag::expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Operand>;
|
||||||
|
|
||||||
bool _is_trivial() const
|
bool _is_trivial() const
|
||||||
{
|
{
|
||||||
return _value._is_trivial();
|
return _value._is_trivial();
|
||||||
};
|
};
|
||||||
|
|
||||||
maybe_tvin_t(tvin_t<T> t):
|
maybe_tvin_t(tvin_t<Operand> operand):
|
||||||
_value(t._value)
|
_value(operand._value)
|
||||||
{}
|
{}
|
||||||
maybe_tvin_t(const maybe_tvin_t&) = default;
|
maybe_tvin_t(const maybe_tvin_t&) = default;
|
||||||
maybe_tvin_t(maybe_tvin_t&&) = default;
|
maybe_tvin_t(maybe_tvin_t&&) = default;
|
||||||
@ -112,7 +116,7 @@ namespace sqlpp
|
|||||||
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
|
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
|
||||||
~maybe_tvin_t() = default;
|
~maybe_tvin_t() = default;
|
||||||
|
|
||||||
typename tvin_t<T>::_operand_t _value;
|
typename tvin_t<Operand>::_operand_t _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace vendor
|
namespace vendor
|
||||||
@ -137,13 +141,13 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename Operand>
|
||||||
auto tvin(T t) -> tvin_t<typename vendor::wrap_operand<T>::type>
|
auto tvin(Operand operand) -> tvin_t<typename vendor::wrap_operand<Operand>::type>
|
||||||
{
|
{
|
||||||
using _operand_t = typename vendor::wrap_operand<T>::type;
|
using _operand_t = typename vendor::wrap_operand<Operand>::type;
|
||||||
static_assert(std::is_same<_operand_t, vendor::text_operand>::value
|
static_assert(std::is_same<_operand_t, vendor::text_operand>::value
|
||||||
or not std::is_same<_operand_t, T>::value, "tvin() used with invalid type (only string and primitive types allowed)");
|
or not std::is_same<_operand_t, Operand>::value, "tvin() used with invalid type (only string and primitive types allowed)");
|
||||||
return {{t}};
|
return {{operand}};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@
|
|||||||
#define SQLPP_TYPE_TRAITS_H
|
#define SQLPP_TYPE_TRAITS_H
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sqlpp11/vendor/wrap_operand.h>
|
#include <sqlpp11/detail/type_set.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -40,8 +40,12 @@ namespace sqlpp
|
|||||||
template<typename T>\
|
template<typename T>\
|
||||||
struct is_##name##_impl<T, typename std::enable_if<std::is_same<typename T::_value_type::_is_##name, std::true_type>::value>::type>: std::true_type {};\
|
struct is_##name##_impl<T, typename std::enable_if<std::is_same<typename T::_value_type::_is_##name, std::true_type>::value>::type>: std::true_type {};\
|
||||||
}\
|
}\
|
||||||
|
namespace tag\
|
||||||
|
{\
|
||||||
|
struct name{};\
|
||||||
|
};\
|
||||||
template<typename T>\
|
template<typename T>\
|
||||||
struct is_##name##_t: detail::is_##name##_impl<T> {};
|
using is_##name##_t = detail::is_element_of<tag::name, typename T::_traits::_tags>;
|
||||||
|
|
||||||
#define SQLPP_IS_COLUMN_TRAIT_GENERATOR(name) \
|
#define SQLPP_IS_COLUMN_TRAIT_GENERATOR(name) \
|
||||||
namespace detail\
|
namespace detail\
|
||||||
@ -77,13 +81,25 @@ namespace sqlpp
|
|||||||
struct connector_##name##_t: detail::connector_##name##_impl<T> {};
|
struct connector_##name##_t: detail::connector_##name##_impl<T> {};
|
||||||
|
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(boolean);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(boolean);
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(numeric);
|
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(integral);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(integral);
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(floating_point);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(floating_point);
|
||||||
|
template<typename T>
|
||||||
|
using is_numeric_t = detail::any_t<
|
||||||
|
detail::is_element_of<tag::integral, typename T::_traits::_tags>::value,
|
||||||
|
detail::is_element_of<tag::floating_point, typename T::_traits::_tags>::value>;
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(text);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(text);
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(value);
|
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(expression);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(expression);
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression);
|
||||||
|
namespace tag
|
||||||
|
{
|
||||||
|
template<typename C>
|
||||||
|
using named_expression_if = typename std::conditional<C::value, tag::named_expression, void>::type;
|
||||||
|
}
|
||||||
|
namespace tag
|
||||||
|
{
|
||||||
|
template<typename C>
|
||||||
|
using expression_if = typename std::conditional<C::value, tag::expression, void>::type;
|
||||||
|
}
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_expression);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_expression);
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(alias);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(alias);
|
||||||
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag);
|
||||||
@ -94,41 +110,99 @@ namespace sqlpp
|
|||||||
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null);
|
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null);
|
||||||
SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null);
|
SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null);
|
||||||
|
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_noop);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(noop);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_table);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(missing);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_join);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(return_value);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(table);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_column);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(join);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_select);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(pseudo_table);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(column);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_select_column_list);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(select);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_from);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag_list);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_on);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_column_list);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_dynamic);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(from);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_where);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(single_table);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_group_by);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(extra_tables);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_having);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(on);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_order_by);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(dynamic);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_limit);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(where);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_offset);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(group_by);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_using);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(having);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_column_list);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(order_by);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_multi_column);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(limit);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_value_list);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(offset);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_assignment);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(using_);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_update_list);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(column_list);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_list);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_column);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(value_list);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value_list);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(assignment);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_sort_order);
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(update_list);
|
||||||
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_list);
|
||||||
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value);
|
||||||
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value_list);
|
||||||
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(sort_order);
|
||||||
|
SQLPP_IS_VALUE_TRAIT_GENERATOR(parameter);
|
||||||
|
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(requires_braces);
|
SQLPP_TYPE_TRAIT_GENERATOR(requires_braces);
|
||||||
SQLPP_TYPE_TRAIT_GENERATOR(is_parameter);
|
|
||||||
|
|
||||||
SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value);
|
SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value);
|
||||||
SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity);
|
SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity);
|
||||||
|
|
||||||
template<typename T, template<typename> class IsTag>
|
template<typename T, template<typename> class IsTag>
|
||||||
using copy_type_trait = typename std::conditional<IsTag<T>::value, std::true_type, std::false_type>::type;
|
using copy_type_trait = typename std::conditional<IsTag<T>::value, std::true_type, std::false_type>::type;
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
struct value_type_of_impl
|
||||||
|
{
|
||||||
|
using type = typename T::_traits::_value_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct required_table_of_impl
|
||||||
|
{
|
||||||
|
using type = typename T::_recursive_traits::_required_tables;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct provided_table_of_impl
|
||||||
|
{
|
||||||
|
using type = typename T::_recursive_traits::_provided_tables;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct extra_table_of_impl
|
||||||
|
{
|
||||||
|
using type = typename T::_recursive_traits::_extra_tables;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
using value_type_of = typename detail::value_type_of_impl<T>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using required_tables_of = typename detail::required_table_of_impl<T>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using provided_tables_of = typename detail::provided_table_of_impl<T>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using extra_tables_of = typename detail::extra_table_of_impl<T>::type;
|
||||||
|
|
||||||
|
template<typename ValueType, typename... Tags>
|
||||||
|
struct make_traits
|
||||||
|
{
|
||||||
|
using _value_type = ValueType;
|
||||||
|
using _tags = detail::make_type_set_t<typename ValueType::_tag, Tags...>;
|
||||||
|
};
|
||||||
|
template<typename... Arguments>
|
||||||
|
struct make_recursive_traits
|
||||||
|
{
|
||||||
|
using _required_tables = detail::make_joined_set_t<required_tables_of<Arguments>...>;
|
||||||
|
using _provided_tables = detail::make_joined_set_t<provided_tables_of<Arguments>...>;
|
||||||
|
using _extra_tables = detail::make_joined_set_t<extra_tables_of<Arguments>...>;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,82 +35,84 @@
|
|||||||
#include <sqlpp11/vendor/noop.h>
|
#include <sqlpp11/vendor/noop.h>
|
||||||
#include <sqlpp11/vendor/where.h>
|
#include <sqlpp11/vendor/where.h>
|
||||||
#include <sqlpp11/vendor/policy_update.h>
|
#include <sqlpp11/vendor/policy_update.h>
|
||||||
#include <sqlpp11/detail/arg_selector.h>
|
|
||||||
|
#include <sqlpp11/detail/get_last.h>
|
||||||
|
#include <sqlpp11/detail/pick_arg.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db,
|
template<typename Db, typename... Policies>
|
||||||
typename... Policies
|
|
||||||
>
|
|
||||||
struct update_t;
|
struct update_t;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Db = void,
|
template<typename Db = void, typename... Policies>
|
||||||
typename Table = vendor::no_single_table_t,
|
|
||||||
typename UpdateList = vendor::no_update_list_t,
|
|
||||||
typename Where = vendor::no_where_t
|
|
||||||
>
|
|
||||||
struct update_policies_t
|
struct update_policies_t
|
||||||
{
|
{
|
||||||
using _database_t = Db;
|
using _database_t = Db;
|
||||||
using _table_t = Table;
|
|
||||||
using _update_list_t = UpdateList;
|
|
||||||
using _where_t = Where;
|
|
||||||
|
|
||||||
using _statement_t = update_t<Db, Table, UpdateList, Where>;
|
using _statement_t = update_t<Db, Policies...>;
|
||||||
|
|
||||||
struct _methods_t:
|
struct _methods_t: public Policies::template _methods_t<update_policies_t>...
|
||||||
public _update_list_t::template _methods_t<update_policies_t>,
|
|
||||||
public _where_t::template _methods_t<update_policies_t>
|
|
||||||
{};
|
{};
|
||||||
|
|
||||||
template<typename Needle, typename Replacement, typename... Policies>
|
template<typename Needle, typename Replacement>
|
||||||
struct _policies_update_t
|
struct _policies_update_t
|
||||||
{
|
{
|
||||||
|
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
|
||||||
using type = update_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
|
using type = update_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
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>::type;
|
||||||
|
|
||||||
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set>;
|
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
||||||
|
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
||||||
|
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
|
||||||
|
|
||||||
|
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
|
||||||
|
|
||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
|
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
||||||
|
|
||||||
|
// The tables not covered by the from.
|
||||||
|
using _required_tables = detail::make_difference_set_t<
|
||||||
|
_all_required_tables,
|
||||||
|
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
|
||||||
|
>;
|
||||||
|
|
||||||
|
using _traits = make_traits<no_value_t>; // FIXME
|
||||||
|
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _parameters = std::tuple<>; // FIXME
|
||||||
|
using _required_tables = _required_tables;
|
||||||
|
using _provided_tables = detail::type_set<>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Db,
|
// UPDATE
|
||||||
typename... Policies
|
template<typename Db, typename... Policies>
|
||||||
>
|
|
||||||
struct update_t:
|
struct update_t:
|
||||||
|
public Policies...,
|
||||||
public detail::update_policies_t<Db, Policies...>::_methods_t
|
public detail::update_policies_t<Db, Policies...>::_methods_t
|
||||||
{
|
{
|
||||||
using _policies_t = typename detail::update_policies_t<Db, Policies...>;
|
using _policies_t = typename detail::update_policies_t<Db, Policies...>;
|
||||||
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 _update_list_t = typename _policies_t::_update_list_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;
|
||||||
|
|
||||||
using _parameter_tuple_t = std::tuple<Policies...>;
|
|
||||||
using _parameter_list_t = typename make_parameter_list_t<update_t>::type;
|
using _parameter_list_t = typename make_parameter_list_t<update_t>::type;
|
||||||
|
|
||||||
static_assert(::sqlpp::detail::is_superset_of<typename _table_t::_table_set, typename _update_list_t::_table_set>::value, "updated columns do not match the table");
|
|
||||||
static_assert(::sqlpp::detail::is_superset_of<typename _table_t::_table_set, typename _where_t::_table_set>::value, "where condition does not match updated table");
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
update_t()
|
constexpr update_t()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename Statement, typename T>
|
template<typename Statement, typename Term>
|
||||||
update_t(Statement s, T t):
|
update_t(Statement statement, Term term):
|
||||||
_table(detail::arg_selector<_table_t>::_(s._table, t)),
|
Policies(detail::pick_arg<Policies>(statement, term))...
|
||||||
_update_list(detail::arg_selector<_update_list_t>::_(s._update_list, t)),
|
|
||||||
_where(detail::arg_selector<_where_t>::_(s._where, t))
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
update_t(const update_t&) = default;
|
update_t(const update_t&) = default;
|
||||||
@ -130,18 +132,15 @@ namespace sqlpp
|
|||||||
return _parameter_list_t::size::value;
|
return _parameter_list_t::size::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename A>
|
|
||||||
struct is_table_subset_of_table
|
|
||||||
{
|
|
||||||
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _table_t::_table_set>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
void _check_consistency() const
|
void _check_consistency() const
|
||||||
{
|
{
|
||||||
|
#warning reactivate tests
|
||||||
|
/*
|
||||||
static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
|
static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
|
||||||
|
|
||||||
static_assert(is_table_subset_of_table<_update_list_t>::value, "updates require additional tables");
|
static_assert(is_table_subset_of_table<_update_list_t>::value, "updates require additional tables");
|
||||||
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
|
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database>
|
template<typename Database>
|
||||||
@ -161,10 +160,6 @@ namespace sqlpp
|
|||||||
|
|
||||||
return {{}, db.prepare_update(*this)};
|
return {{}, db.prepare_update(*this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
_table_t _table;
|
|
||||||
_update_list_t _update_list;
|
|
||||||
_where_t _where;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace vendor
|
namespace vendor
|
||||||
@ -177,31 +172,32 @@ namespace sqlpp
|
|||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "UPDATE ";
|
context << "UPDATE ";
|
||||||
serialize(t._table, context);
|
using swallow = int[];
|
||||||
serialize(t._update_list, context);
|
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
|
||||||
serialize(t._where, context);
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename... Policies>
|
template<typename Database>
|
||||||
using make_update_t = typename detail::update_policies_t<Database, Policies...>::_statement_t;
|
using blank_update_t = update_t<Database,
|
||||||
|
vendor::no_single_table_t,
|
||||||
|
vendor::no_update_list_t,
|
||||||
|
vendor::no_where_t>;
|
||||||
|
|
||||||
template<typename Table>
|
template<typename Table>
|
||||||
constexpr auto update(Table table)
|
constexpr auto update(Table table)
|
||||||
-> make_update_t<void, vendor::single_table_t<void, Table>>
|
-> decltype(blank_update_t<void>().from(table))
|
||||||
{
|
{
|
||||||
return { update_t<void>(), vendor::single_table_t<void, Table>{table} };
|
return { blank_update_t<void>().from(table) };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename Table>
|
template<typename Database, typename Table>
|
||||||
constexpr auto dynamic_update(const Database&, Table table)
|
constexpr auto dynamic_update(const Database&, Table table)
|
||||||
-> make_update_t<Database, vendor::single_table_t<void, Table>>
|
-> decltype(blank_update_t<Database>().from(table))
|
||||||
{
|
{
|
||||||
return { update_t<Database>(), vendor::single_table_t<void, Table>{table} };
|
return { blank_update_t<Database>().from(table) };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
30
include/sqlpp11/vendor/assignment.h
vendored
30
include/sqlpp11/vendor/assignment.h
vendored
@ -59,21 +59,21 @@ namespace sqlpp
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
bool is_trivial(const T& t)
|
bool is_trivial(const T& t)
|
||||||
{
|
{
|
||||||
return is_trivial_t<typename T::value_type>::_(t);
|
return is_trivial_t<T>::_(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
struct assignment_t
|
struct assignment_t
|
||||||
{
|
{
|
||||||
using _is_assignment = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::assignment>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
||||||
|
|
||||||
using _column_t = Lhs;
|
using _column_t = Lhs;
|
||||||
using value_type = Rhs;
|
using _value_t = Rhs;
|
||||||
using _parameter_tuple_t = std::tuple<_column_t, Rhs>;
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
|
|
||||||
|
|
||||||
static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same<Rhs, null_t>::value, "column must not be null");
|
static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same<_value_t, null_t>::value, "column must not be null");
|
||||||
|
|
||||||
assignment_t(_column_t lhs, value_type rhs):
|
assignment_t(_column_t lhs, _value_t rhs):
|
||||||
_lhs(lhs),
|
_lhs(lhs),
|
||||||
_rhs(rhs)
|
_rhs(rhs)
|
||||||
{}
|
{}
|
||||||
@ -85,7 +85,7 @@ namespace sqlpp
|
|||||||
~assignment_t() = default;
|
~assignment_t() = default;
|
||||||
|
|
||||||
_column_t _lhs;
|
_column_t _lhs;
|
||||||
value_type _rhs;
|
_value_t _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Lhs, typename Rhs>
|
template<typename Context, typename Lhs, typename Rhs>
|
||||||
@ -96,7 +96,7 @@ namespace sqlpp
|
|||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if ((trivial_value_is_null_t<typename T::_column_t>::value
|
if ((trivial_value_is_null_t<typename T::_column_t>::value
|
||||||
and is_trivial_t<typename T::value_type>::_(t._rhs))
|
and is_trivial(t._rhs))
|
||||||
or (std::is_same<Rhs, null_t>::value))
|
or (std::is_same<Rhs, null_t>::value))
|
||||||
{
|
{
|
||||||
serialize(simple_column(t._lhs), context);
|
serialize(simple_column(t._lhs), context);
|
||||||
@ -115,15 +115,15 @@ namespace sqlpp
|
|||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
struct assignment_t<Lhs, tvin_t<Rhs>>
|
struct assignment_t<Lhs, tvin_t<Rhs>>
|
||||||
{
|
{
|
||||||
using _is_assignment = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::assignment>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
||||||
|
|
||||||
using _column_t = Lhs;
|
using _column_t = Lhs;
|
||||||
using value_type = tvin_t<Rhs>;
|
using _value_t = tvin_t<Rhs>;
|
||||||
using _parameter_tuple_t = std::tuple<_column_t, Rhs>;
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
|
|
||||||
|
|
||||||
static_assert(can_be_null_t<_column_t>::value, "column cannot be null");
|
static_assert(can_be_null_t<_column_t>::value, "column cannot be null");
|
||||||
|
|
||||||
assignment_t(_column_t lhs, value_type rhs):
|
assignment_t(_column_t lhs, _value_t rhs):
|
||||||
_lhs(lhs),
|
_lhs(lhs),
|
||||||
_rhs(rhs)
|
_rhs(rhs)
|
||||||
{}
|
{}
|
||||||
@ -135,7 +135,7 @@ namespace sqlpp
|
|||||||
~assignment_t() = default;
|
~assignment_t() = default;
|
||||||
|
|
||||||
_column_t _lhs;
|
_column_t _lhs;
|
||||||
value_type _rhs;
|
_value_t _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Lhs, typename Rhs>
|
template<typename Context, typename Lhs, typename Rhs>
|
||||||
|
13
include/sqlpp11/vendor/concat.h
vendored
13
include/sqlpp11/vendor/concat.h
vendored
@ -35,18 +35,15 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
namespace vendor
|
namespace vendor
|
||||||
{
|
{
|
||||||
|
// FIXME: Remove First, inherit from text_t
|
||||||
template<typename First, typename... Args>
|
template<typename First, typename... Args>
|
||||||
struct concat_t: public First::_value_type::template expression_operators<concat_t<First, Args...>>
|
struct concat_t: public value_type_of<First>::template expression_operators<concat_t<First, Args...>>
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<value_type_of<First>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<First, Args...>;
|
||||||
|
|
||||||
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
|
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
|
||||||
static_assert(sqlpp::detail::all_t<is_text_t<First>::value, is_text_t<Args>::value...>::value, "at least one non-text argument detected in concat()");
|
static_assert(sqlpp::detail::all_t<is_text_t<First>::value, is_text_t<Args>::value...>::value, "at least one non-text argument detected in concat()");
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename First::_table_set, typename Args::_table_set...>::type;
|
|
||||||
|
|
||||||
struct _value_type: public First::_value_type::_base_value_type
|
|
||||||
{
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
static constexpr const char* _get_name() { return "CONCAT"; }
|
static constexpr const char* _get_name() { return "CONCAT"; }
|
||||||
|
41
include/sqlpp11/vendor/expression.h
vendored
41
include/sqlpp11/vendor/expression.h
vendored
@ -40,11 +40,10 @@ namespace sqlpp
|
|||||||
namespace vendor
|
namespace vendor
|
||||||
{
|
{
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
struct binary_expression_t<Lhs, tag::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<equal_to_t<Lhs, Rhs>>
|
struct binary_expression_t<Lhs, op::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<equal_to_t<Lhs, Rhs>>
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<boolean, sqlpp::tag::expression>;
|
||||||
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
|
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
|
|
||||||
|
|
||||||
binary_expression_t(Lhs lhs, Rhs rhs):
|
binary_expression_t(Lhs lhs, Rhs rhs):
|
||||||
_lhs(lhs),
|
_lhs(lhs),
|
||||||
@ -85,11 +84,10 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
struct binary_expression_t<Lhs, tag::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<not_equal_to_t<Lhs, Rhs>>
|
struct binary_expression_t<Lhs, op::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<not_equal_to_t<Lhs, Rhs>>
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<boolean, sqlpp::tag::expression>;
|
||||||
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
|
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
|
|
||||||
|
|
||||||
binary_expression_t(Lhs lhs, Rhs rhs):
|
binary_expression_t(Lhs lhs, Rhs rhs):
|
||||||
_lhs(lhs),
|
_lhs(lhs),
|
||||||
@ -130,11 +128,10 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Rhs>
|
template<typename Rhs>
|
||||||
struct unary_expression_t<tag::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<logical_not_t<Rhs>>
|
struct unary_expression_t<op::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<logical_not_t<Rhs>>
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<boolean, sqlpp::tag::expression>;
|
||||||
using _parameter_tuple_t = std::tuple<Rhs>;
|
using _recursive_traits = make_recursive_traits<Rhs>;
|
||||||
using _table_set = typename Rhs::_table_set;
|
|
||||||
|
|
||||||
unary_expression_t(Rhs rhs):
|
unary_expression_t(Rhs rhs):
|
||||||
_rhs(rhs)
|
_rhs(rhs)
|
||||||
@ -165,15 +162,12 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename O, typename Rhs>
|
template<typename Lhs, typename O, typename Rhs>
|
||||||
struct binary_expression_t: public O::_value_type::template expression_operators<binary_expression_t<Lhs, O, Rhs>>
|
struct binary_expression_t: public value_type_of<O>::template expression_operators<binary_expression_t<Lhs, O, Rhs>>
|
||||||
{
|
{
|
||||||
using _lhs_t = Lhs;
|
using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>;
|
||||||
using _rhs_t = Rhs;
|
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
||||||
using _value_type = typename O::_value_type;
|
|
||||||
using _parameter_tuple_t = std::tuple<_lhs_t, _rhs_t>;
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
|
|
||||||
|
|
||||||
binary_expression_t(_lhs_t lhs, _rhs_t rhs):
|
binary_expression_t(Lhs lhs, Rhs rhs):
|
||||||
_lhs(lhs),
|
_lhs(lhs),
|
||||||
_rhs(rhs)
|
_rhs(rhs)
|
||||||
{}
|
{}
|
||||||
@ -184,8 +178,8 @@ namespace sqlpp
|
|||||||
binary_expression_t& operator=(binary_expression_t&&) = default;
|
binary_expression_t& operator=(binary_expression_t&&) = default;
|
||||||
~binary_expression_t() = default;
|
~binary_expression_t() = default;
|
||||||
|
|
||||||
_lhs_t _lhs;
|
Lhs _lhs;
|
||||||
_rhs_t _rhs;
|
Rhs _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Lhs, typename O, typename Rhs>
|
template<typename Context, typename Lhs, typename O, typename Rhs>
|
||||||
@ -207,9 +201,8 @@ namespace sqlpp
|
|||||||
template<typename O, typename Rhs>
|
template<typename O, typename Rhs>
|
||||||
struct unary_expression_t: public O::_value_type::template expression_operators<unary_expression_t<O, Rhs>>
|
struct unary_expression_t: public O::_value_type::template expression_operators<unary_expression_t<O, Rhs>>
|
||||||
{
|
{
|
||||||
using _value_type = typename O::_value_type;
|
using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>;
|
||||||
using _parameter_tuple_t = std::tuple<Rhs>;
|
using _recursive_traits = make_recursive_traits<Rhs>;
|
||||||
using _table_set = typename Rhs::_table_set;
|
|
||||||
|
|
||||||
unary_expression_t(Rhs rhs):
|
unary_expression_t(Rhs rhs):
|
||||||
_rhs(rhs)
|
_rhs(rhs)
|
||||||
|
73
include/sqlpp11/vendor/expression_fwd.h
vendored
73
include/sqlpp11/vendor/expression_fwd.h
vendored
@ -29,105 +29,112 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
struct boolean;
|
||||||
|
struct integral;
|
||||||
|
struct floating_point;
|
||||||
|
}
|
||||||
|
|
||||||
namespace vendor
|
namespace vendor
|
||||||
{
|
{
|
||||||
namespace tag
|
namespace op
|
||||||
{
|
{
|
||||||
struct less
|
struct less
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||||
static constexpr const char* _name = "<";
|
static constexpr const char* _name = "<";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct less_equal
|
struct less_equal
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||||
static constexpr const char* _name = "<=";
|
static constexpr const char* _name = "<=";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct equal_to
|
struct equal_to
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct not_equal_to
|
struct not_equal_to
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct greater_equal
|
struct greater_equal
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||||
static constexpr const char* _name = ">=";
|
static constexpr const char* _name = ">=";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct greater
|
struct greater
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||||
static constexpr const char* _name = ">";
|
static constexpr const char* _name = ">";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct logical_or
|
struct logical_or
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||||
static constexpr const char* _name = " OR ";
|
static constexpr const char* _name = " OR ";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct logical_and
|
struct logical_and
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||||
static constexpr const char* _name = " AND ";
|
static constexpr const char* _name = " AND ";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct logical_not
|
struct logical_not
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::boolean;
|
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
struct plus
|
struct plus
|
||||||
{
|
{
|
||||||
using _value_type = ValueType;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "+";
|
static constexpr const char* _name = "+";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
struct minus
|
struct minus
|
||||||
{
|
{
|
||||||
using _value_type = ValueType;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "-";
|
static constexpr const char* _name = "-";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
struct multiplies
|
struct multiplies
|
||||||
{
|
{
|
||||||
using _value_type = ValueType;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "*";
|
static constexpr const char* _name = "*";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct divides
|
struct divides
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::floating_point;
|
using _traits = make_traits<::sqlpp::detail::floating_point>;
|
||||||
static constexpr const char* _name = "/";
|
static constexpr const char* _name = "/";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct modulus
|
struct modulus
|
||||||
{
|
{
|
||||||
using _value_type = ::sqlpp::detail::integral;
|
using _traits = make_traits<::sqlpp::detail::integral>;
|
||||||
static constexpr const char* _name = "%";
|
static constexpr const char* _name = "%";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
struct unary_minus
|
struct unary_minus
|
||||||
{
|
{
|
||||||
using _value_type = ValueType;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "-";
|
static constexpr const char* _name = "-";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template<typename ValueType>
|
||||||
struct unary_plus
|
struct unary_plus
|
||||||
{
|
{
|
||||||
using _value_type = ValueType;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "+";
|
static constexpr const char* _name = "+";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -139,52 +146,52 @@ namespace sqlpp
|
|||||||
struct unary_expression_t;
|
struct unary_expression_t;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using less_than_t = binary_expression_t<Lhs, tag::less, Rhs>;
|
using less_than_t = binary_expression_t<Lhs, op::less, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using less_equal_t = binary_expression_t<Lhs, tag::less_equal, Rhs>;
|
using less_equal_t = binary_expression_t<Lhs, op::less_equal, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using equal_to_t = binary_expression_t<Lhs, tag::equal_to, Rhs>;
|
using equal_to_t = binary_expression_t<Lhs, op::equal_to, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using not_equal_to_t = binary_expression_t<Lhs, tag::not_equal_to, Rhs>;
|
using not_equal_to_t = binary_expression_t<Lhs, op::not_equal_to, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using greater_than_t = binary_expression_t<Lhs, tag::greater, Rhs>;
|
using greater_than_t = binary_expression_t<Lhs, op::greater, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using greater_equal_t = binary_expression_t<Lhs, tag::greater_equal, Rhs>;
|
using greater_equal_t = binary_expression_t<Lhs, op::greater_equal, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using logical_and_t = binary_expression_t<Lhs, tag::logical_and, Rhs>;
|
using logical_and_t = binary_expression_t<Lhs, op::logical_and, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using logical_or_t = binary_expression_t<Lhs, tag::logical_or, Rhs>;
|
using logical_or_t = binary_expression_t<Lhs, op::logical_or, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename ValueType, typename Rhs>
|
template<typename Lhs, typename ValueType, typename Rhs>
|
||||||
using plus_t = binary_expression_t<Lhs, tag::plus<ValueType>, Rhs>;
|
using plus_t = binary_expression_t<Lhs, op::plus<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename ValueType, typename Rhs>
|
template<typename Lhs, typename ValueType, typename Rhs>
|
||||||
using minus_t = binary_expression_t<Lhs, tag::minus<ValueType>, Rhs>;
|
using minus_t = binary_expression_t<Lhs, op::minus<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename ValueType, typename Rhs>
|
template<typename Lhs, typename ValueType, typename Rhs>
|
||||||
using multiplies_t = binary_expression_t<Lhs, tag::multiplies<ValueType>, Rhs>;
|
using multiplies_t = binary_expression_t<Lhs, op::multiplies<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using divides_t = binary_expression_t<Lhs, tag::divides, Rhs>;
|
using divides_t = binary_expression_t<Lhs, op::divides, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template<typename Lhs, typename Rhs>
|
||||||
using modulus_t = binary_expression_t<Lhs, tag::modulus, Rhs>;
|
using modulus_t = binary_expression_t<Lhs, op::modulus, Rhs>;
|
||||||
|
|
||||||
template<typename Rhs>
|
template<typename Rhs>
|
||||||
using logical_not_t = unary_expression_t<tag::logical_not, Rhs>;
|
using logical_not_t = unary_expression_t<op::logical_not, Rhs>;
|
||||||
|
|
||||||
template<typename ValueType, typename Rhs>
|
template<typename ValueType, typename Rhs>
|
||||||
using unary_plus_t = unary_expression_t<tag::unary_plus<ValueType>, Rhs>;
|
using unary_plus_t = unary_expression_t<op::unary_plus<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename ValueType, typename Rhs>
|
template<typename ValueType, typename Rhs>
|
||||||
using unary_minus_t = unary_expression_t<tag::unary_minus<ValueType>, Rhs>;
|
using unary_minus_t = unary_expression_t<op::unary_minus<ValueType>, Rhs>;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
include/sqlpp11/vendor/extra_tables.h
vendored
22
include/sqlpp11/vendor/extra_tables.h
vendored
@ -39,17 +39,23 @@ namespace sqlpp
|
|||||||
template<typename... Tables>
|
template<typename... Tables>
|
||||||
struct extra_tables_t
|
struct extra_tables_t
|
||||||
{
|
{
|
||||||
using _is_extra_tables = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::extra_tables>;
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _parameters = std::tuple<>;
|
||||||
|
using _required_tables = ::sqlpp::detail::type_set<>;
|
||||||
|
using _provided_tables = ::sqlpp::detail::type_set<>;
|
||||||
|
using _extra_tables = ::sqlpp::detail::type_set<Tables...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
using _recursive_traits = make_recursive_traits<Tables...>;
|
||||||
|
|
||||||
|
// FIXME: extra_tables must not require tables!
|
||||||
|
|
||||||
static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()");
|
static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()");
|
||||||
|
|
||||||
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in extra_tables()");
|
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in extra_tables()");
|
||||||
|
|
||||||
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in extra_tables()");
|
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in extra_tables()");
|
||||||
|
|
||||||
using _table_set = ::sqlpp::detail::make_joined_set_t<typename Tables::_table_set...>;
|
|
||||||
|
|
||||||
|
|
||||||
extra_tables_t()
|
extra_tables_t()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -67,8 +73,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct no_extra_tables_t
|
struct no_extra_tables_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
6
include/sqlpp11/vendor/field.h
vendored
6
include/sqlpp11/vendor/field.h
vendored
@ -36,8 +36,10 @@ namespace sqlpp
|
|||||||
template<typename NameType, typename ValueType, bool TrivialValueIsNull>
|
template<typename NameType, typename ValueType, bool TrivialValueIsNull>
|
||||||
struct field_t
|
struct field_t
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<ValueType, tag::noop>;
|
||||||
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
using _name_t = NameType;
|
using _name_t = NameType;
|
||||||
using _value_type = ValueType;
|
|
||||||
static constexpr bool _trivial_value_is_null = TrivialValueIsNull;
|
static constexpr bool _trivial_value_is_null = TrivialValueIsNull;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ namespace sqlpp
|
|||||||
struct make_field_t_impl
|
struct make_field_t_impl
|
||||||
{
|
{
|
||||||
using type = field_t<typename NamedExpr::_name_t,
|
using type = field_t<typename NamedExpr::_name_t,
|
||||||
typename NamedExpr::_value_type::_base_value_type,
|
value_type_of<NamedExpr>,
|
||||||
trivial_value_is_null_t<NamedExpr>::value>;
|
trivial_value_is_null_t<NamedExpr>::value>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
13
include/sqlpp11/vendor/from.h
vendored
13
include/sqlpp11/vendor/from.h
vendored
@ -41,7 +41,9 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Tables>
|
template<typename Database, typename... Tables>
|
||||||
struct from_t
|
struct from_t
|
||||||
{
|
{
|
||||||
using _is_from = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::from>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Tables...>;
|
||||||
|
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table or join argument required in from()");
|
static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table or join argument required in from()");
|
||||||
@ -51,8 +53,9 @@ namespace sqlpp
|
|||||||
|
|
||||||
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(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in from()");
|
||||||
|
|
||||||
using _table_set = ::sqlpp::detail::make_joined_set_t<typename Tables::_table_set...>;
|
static_assert(required_tables_of<from_t>::size::value == 0, "at least one table depends on another table");
|
||||||
|
|
||||||
|
from_t& _from() { return *this; }
|
||||||
|
|
||||||
from_t(Tables... tables):
|
from_t(Tables... tables):
|
||||||
_tables(tables...)
|
_tables(tables...)
|
||||||
@ -82,7 +85,7 @@ namespace sqlpp
|
|||||||
template<typename Table>
|
template<typename Table>
|
||||||
void _add_from_impl(Table table, const std::true_type&)
|
void _add_from_impl(Table table, const std::true_type&)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_from._dynamic_tables.emplace_back(table);
|
return static_cast<typename Policies::_statement_t*>(this)->_from()._dynamic_tables.emplace_back(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Table>
|
template<typename Table>
|
||||||
@ -95,8 +98,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct no_from_t
|
struct no_from_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
18
include/sqlpp11/vendor/group_by.h
vendored
18
include/sqlpp11/vendor/group_by.h
vendored
@ -43,12 +43,10 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Expressions>
|
template<typename Database, typename... Expressions>
|
||||||
struct group_by_t
|
struct group_by_t
|
||||||
{
|
{
|
||||||
using _is_group_by = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::group_by>;
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _recursive_traits = make_recursive_traits<Expressions...>;
|
||||||
using _parameter_tuple_t = std::tuple<Expressions...>;
|
|
||||||
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
|
|
||||||
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
|
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
|
||||||
|
|
||||||
@ -56,6 +54,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()");
|
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()");
|
||||||
|
|
||||||
|
group_by_t& _group_by() { return *this; }
|
||||||
|
|
||||||
group_by_t(Expressions... expressions):
|
group_by_t(Expressions... expressions):
|
||||||
_expressions(expressions...)
|
_expressions(expressions...)
|
||||||
{}
|
{}
|
||||||
@ -91,7 +91,7 @@ namespace sqlpp
|
|||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
void _add_group_by_impl(Expression expression, const std::true_type&)
|
void _add_group_by_impl(Expression expression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_group_by._dynamic_expressions.emplace_back(expression);
|
return static_cast<typename Policies::_statement_t*>(this)->_group_by()._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
@ -99,14 +99,14 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
const group_by_t& _group_by() const { return *this; }
|
const group_by_t& _group_by() const { return *this; }
|
||||||
_parameter_tuple_t _expressions;
|
std::tuple<Expressions...> _expressions;
|
||||||
vendor::interpretable_list_t<Database> _dynamic_expressions;
|
vendor::interpretable_list_t<Database> _dynamic_expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct no_group_by_t
|
struct no_group_by_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
17
include/sqlpp11/vendor/having.h
vendored
17
include/sqlpp11/vendor/having.h
vendored
@ -42,16 +42,15 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Expressions>
|
template<typename Database, typename... Expressions>
|
||||||
struct having_t
|
struct having_t
|
||||||
{
|
{
|
||||||
using _is_having = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::having>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Expressions...>;
|
||||||
|
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
using _parameter_tuple_t = std::tuple<Expressions...>;
|
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()");
|
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()");
|
||||||
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()");
|
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()");
|
||||||
|
|
||||||
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
|
having_t& _having() { return *this; }
|
||||||
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
|
|
||||||
|
|
||||||
having_t(Expressions... expressions):
|
having_t(Expressions... expressions):
|
||||||
_expressions(expressions...)
|
_expressions(expressions...)
|
||||||
@ -88,21 +87,21 @@ namespace sqlpp
|
|||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
void _add_having_impl(Expression expression, const std::true_type&)
|
void _add_having_impl(Expression expression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_having._dynamic_expressions.emplace_back(expression);
|
return static_cast<typename Policies::_statement_t*>(this)->_having()._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
void _add_having_impl(Expression expression, const std::false_type&);
|
void _add_having_impl(Expression expression, const std::false_type&);
|
||||||
};
|
};
|
||||||
|
|
||||||
_parameter_tuple_t _expressions;
|
std::tuple<Expressions...> _expressions;
|
||||||
vendor::interpretable_list_t<Database> _dynamic_expressions;
|
vendor::interpretable_list_t<Database> _dynamic_expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct no_having_t
|
struct no_having_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
9
include/sqlpp11/vendor/in.h
vendored
9
include/sqlpp11/vendor/in.h
vendored
@ -39,14 +39,12 @@ namespace sqlpp
|
|||||||
template<bool NotInverted, typename Operand, typename... Args>
|
template<bool NotInverted, typename Operand, typename... Args>
|
||||||
struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>
|
struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Operand, Args...>;
|
||||||
|
|
||||||
static constexpr bool _inverted = not NotInverted;
|
static constexpr bool _inverted = not NotInverted;
|
||||||
static_assert(sizeof...(Args) > 0, "in() requires at least one argument");
|
static_assert(sizeof...(Args) > 0, "in() requires at least one argument");
|
||||||
|
|
||||||
struct _value_type: public boolean
|
|
||||||
{
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; }
|
static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; }
|
||||||
@ -56,7 +54,6 @@ namespace sqlpp
|
|||||||
T in;
|
T in;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Operand::_table_set, typename Args::_table_set...>::type;
|
|
||||||
|
|
||||||
in_t(Operand operand, Args... args):
|
in_t(Operand operand, Args... args):
|
||||||
_operand(operand),
|
_operand(operand),
|
||||||
|
6
include/sqlpp11/vendor/insert_value.h
vendored
6
include/sqlpp11/vendor/insert_value.h
vendored
@ -44,7 +44,6 @@ namespace sqlpp
|
|||||||
struct type_if
|
struct type_if
|
||||||
{
|
{
|
||||||
using type = Type;
|
using type = Type;
|
||||||
using _table_set = typename Type::_table_set;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
@ -52,7 +51,8 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct type
|
struct type
|
||||||
{
|
{
|
||||||
using _table_set = sqlpp::detail::type_set<>;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -61,7 +61,7 @@ namespace sqlpp
|
|||||||
struct insert_value_t
|
struct insert_value_t
|
||||||
{
|
{
|
||||||
using _is_insert_value = std::true_type;
|
using _is_insert_value = std::true_type;
|
||||||
using _pure_value_t = typename Column::_value_type::_cpp_value_type;
|
using _pure_value_t = typename value_type_of<Column>::_cpp_value_type;
|
||||||
using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type;
|
using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type;
|
||||||
using _tvin_t = typename detail::type_if<tvin_t<_wrapped_value_t>, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
|
using _tvin_t = typename detail::type_if<tvin_t<_wrapped_value_t>, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
|
||||||
using _null_t = typename detail::type_if<null_t, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
|
using _null_t = typename detail::type_if<null_t, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
|
||||||
|
63
include/sqlpp11/vendor/insert_value_list.h
vendored
63
include/sqlpp11/vendor/insert_value_list.h
vendored
@ -42,8 +42,8 @@ namespace sqlpp
|
|||||||
// COLUMN AND VALUE LIST
|
// COLUMN AND VALUE LIST
|
||||||
struct insert_default_values_t
|
struct insert_default_values_t
|
||||||
{
|
{
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _traits = make_traits<no_value_t>;
|
||||||
using _is_dynamic = std::false_type;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
@ -53,15 +53,17 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Assignments>
|
template<typename Database, typename... Assignments>
|
||||||
struct insert_list_t
|
struct insert_list_t
|
||||||
{
|
{
|
||||||
using _is_insert_list = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::insert_list>;
|
||||||
|
using _recursive_traits = make_recursive_traits<typename Assignments::_column_t..., typename Assignments::_value_t...>;
|
||||||
|
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
using _parameter_tuple_t = std::tuple<Assignments...>;
|
|
||||||
template<template<typename...> class Target>
|
template<template<typename...> class Target>
|
||||||
using copy_assignments_t = Target<Assignments...>; // FIXME: Nice idea to copy variadic template arguments?
|
using copy_assignments_t = Target<Assignments...>; // FIXME: Nice idea to copy variadic template arguments?
|
||||||
template<template<typename...> class Target, template<typename> class Wrap>
|
template<template<typename...> class Target, template<typename> class Wrap>
|
||||||
using copy_wrapped_assignments_t = Target<Wrap<Assignments>...>;
|
using copy_wrapped_assignments_t = Target<Wrap<Assignments>...>;
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one select expression required in set()");
|
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment required in set()");
|
||||||
|
|
||||||
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
|
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
|
||||||
|
|
||||||
@ -69,11 +71,17 @@ namespace sqlpp
|
|||||||
|
|
||||||
static_assert(sqlpp::detail::none_t<must_not_insert_t<typename Assignments::_column_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
|
static_assert(sqlpp::detail::none_t<must_not_insert_t<typename Assignments::_column_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
|
||||||
|
|
||||||
using _column_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::_column_t::_table_set...>::type;
|
#warning: Need to reactivate these checks
|
||||||
using _value_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::value_type::_table_set...>::type;
|
/*
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type;
|
using _column_required_tables = typename ::sqlpp::detail::make_joined_set<typename Assignments::_column_t::_required_tables...>::type;
|
||||||
static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns");
|
using _value_required_tables = typename ::sqlpp::detail::make_joined_set<typename Assignments::value_type::_required_tables...>::type;
|
||||||
static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables");
|
using _provided_tables = ::sqlpp::detail::type_set<>;
|
||||||
|
using _required_tables = typename ::sqlpp::detail::make_joined_set<_column_required_tables, _value_required_tables>::type;
|
||||||
|
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for tables from several columns");
|
||||||
|
static_assert(::sqlpp::detail::is_subset_of<_value_required_tables, _column_required_tables>::value, "set() contains values from foreign tables");
|
||||||
|
*/
|
||||||
|
|
||||||
|
insert_list_t& _insert_value_list() { return *this; }
|
||||||
|
|
||||||
insert_list_t(Assignments... assignment):
|
insert_list_t(Assignments... assignment):
|
||||||
_assignments(assignment...),
|
_assignments(assignment...),
|
||||||
@ -91,22 +99,24 @@ 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, "add_set() arguments require to be assigments");
|
static_assert(is_assignment_t<Assignment>::value, "add_set() arguments require to be assigments");
|
||||||
static_assert(not must_not_insert_t<typename Assignment::_column_t>::value, "add_set() argument must not be used in insert");
|
static_assert(not must_not_insert_t<typename Assignment::_column_t>::value, "add_set() argument must not be used in insert");
|
||||||
using _column_table_set = typename Assignment::_column_t::_table_set;
|
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add_set() contains a column from a foreign table");
|
||||||
using _value_table_set = typename Assignment::value_type::_table_set;
|
|
||||||
static_assert(::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>::value, "add_set() contains a column from a foreign table");
|
|
||||||
static_assert(::sqlpp::detail::is_subset_of<_column_table_set, typename Policies::_table_set>::value, "add_set() contains a value from a foreign table");
|
|
||||||
|
|
||||||
using ok = ::sqlpp::detail::all_t<
|
using ok = ::sqlpp::detail::all_t<
|
||||||
_is_dynamic::value,
|
_is_dynamic::value,
|
||||||
is_assignment_t<Assignment>::value,
|
is_assignment_t<Assignment>::value,
|
||||||
not must_not_insert_t<typename Assignment::_column_t>::value,
|
not must_not_insert_t<typename Assignment::_column_t>::value,
|
||||||
::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>::value,
|
(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value)>;
|
||||||
::sqlpp::detail::is_subset_of<_column_table_set, typename Policies::_table_set>::value>;
|
|
||||||
|
|
||||||
_add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
|
_add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
|
||||||
}
|
}
|
||||||
@ -115,8 +125,8 @@ namespace sqlpp
|
|||||||
template<typename Assignment>
|
template<typename Assignment>
|
||||||
void _add_set_impl(Assignment assignment, const std::true_type&)
|
void _add_set_impl(Assignment assignment, const std::true_type&)
|
||||||
{
|
{
|
||||||
static_cast<typename Policies::_statement_t*>(this)->_insert_value_list._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
|
static_cast<typename Policies::_statement_t*>(this)->_insert_value_list()._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
|
||||||
static_cast<typename Policies::_statement_t*>(this)->_insert_value_list._dynamic_values.emplace_back(assignment._rhs);
|
static_cast<typename Policies::_statement_t*>(this)->_insert_value_list()._dynamic_values.emplace_back(assignment._rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Assignment>
|
template<typename Assignment>
|
||||||
@ -126,7 +136,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
|
|
||||||
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
|
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
|
||||||
std::tuple<typename Assignments::value_type...> _values;
|
std::tuple<typename Assignments::_value_t...> _values;
|
||||||
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
|
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
|
||||||
typename vendor::interpretable_list_t<Database> _dynamic_columns;
|
typename vendor::interpretable_list_t<Database> _dynamic_columns;
|
||||||
typename vendor::interpretable_list_t<Database> _dynamic_values;
|
typename vendor::interpretable_list_t<Database> _dynamic_values;
|
||||||
@ -135,8 +145,8 @@ namespace sqlpp
|
|||||||
template<typename... Columns>
|
template<typename... Columns>
|
||||||
struct column_list_t
|
struct column_list_t
|
||||||
{
|
{
|
||||||
using _is_column_list = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::column_list>;
|
||||||
using _parameter_tuple_t = std::tuple<Columns...>;
|
using _recursive_traits = make_recursive_traits<Columns...>;
|
||||||
|
|
||||||
static_assert(sizeof...(Columns), "at least one column required in columns()");
|
static_assert(sizeof...(Columns), "at least one column required in columns()");
|
||||||
|
|
||||||
@ -147,9 +157,10 @@ namespace sqlpp
|
|||||||
static_assert(::sqlpp::detail::none_t<must_not_insert_t<Columns>::value...>::value, "at least one column argument has a must_not_insert flag in its definition");
|
static_assert(::sqlpp::detail::none_t<must_not_insert_t<Columns>::value...>::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 _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()");
|
static_assert(required_tables_of<column_list_t>::size::value == 1, "columns from multiple tables in columns()");
|
||||||
|
|
||||||
|
column_list_t& _insert_value_list() { return *this; }
|
||||||
|
|
||||||
column_list_t(Columns... columns):
|
column_list_t(Columns... columns):
|
||||||
_columns(simple_column_t<Columns>{columns}...)
|
_columns(simple_column_t<Columns>{columns}...)
|
||||||
@ -183,7 +194,7 @@ namespace sqlpp
|
|||||||
template<typename... Assignments>
|
template<typename... Assignments>
|
||||||
void _add_values_impl(const std::true_type&, Assignments... assignments)
|
void _add_values_impl(const std::true_type&, Assignments... assignments)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_insert_value_list._insert_values.emplace_back(vendor::insert_value_t<typename Assignments::_column_t>{assignments}...);
|
return static_cast<typename Policies::_statement_t*>(this)->_insert_value_list()._insert_values.emplace_back(vendor::insert_value_t<typename Assignments::_column_t>{assignments}...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Assignments>
|
template<typename... Assignments>
|
||||||
@ -202,8 +213,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct no_insert_value_list_t
|
struct no_insert_value_list_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
4
include/sqlpp11/vendor/is_null.h
vendored
4
include/sqlpp11/vendor/is_null.h
vendored
@ -38,8 +38,10 @@ namespace sqlpp
|
|||||||
template<bool NotInverted, typename Operand>
|
template<bool NotInverted, typename Operand>
|
||||||
struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>
|
struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Operand>;
|
||||||
|
|
||||||
static constexpr bool _inverted = not NotInverted;
|
static constexpr bool _inverted = not NotInverted;
|
||||||
using _table_set = typename Operand::_table_set;
|
|
||||||
|
|
||||||
struct _value_type: public boolean
|
struct _value_type: public boolean
|
||||||
{
|
{
|
||||||
|
10
include/sqlpp11/vendor/like.h
vendored
10
include/sqlpp11/vendor/like.h
vendored
@ -38,15 +38,11 @@ namespace sqlpp
|
|||||||
template<typename Operand, typename Pattern>
|
template<typename Operand, typename Pattern>
|
||||||
struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>
|
struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Operand, Pattern>;
|
||||||
|
|
||||||
static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text");
|
static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text");
|
||||||
static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text");
|
static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text");
|
||||||
using _parameter_tuple_t = std::tuple<Operand, Pattern>;
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Operand::_table_set, typename Pattern::_table_set>::type;
|
|
||||||
|
|
||||||
struct _value_type: public boolean
|
|
||||||
{
|
|
||||||
using _is_named_expression = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _name_t
|
struct _name_t
|
||||||
{
|
{
|
||||||
|
21
include/sqlpp11/vendor/limit.h
vendored
21
include/sqlpp11/vendor/limit.h
vendored
@ -39,10 +39,10 @@ namespace sqlpp
|
|||||||
template<typename Limit>
|
template<typename Limit>
|
||||||
struct limit_t
|
struct limit_t
|
||||||
{
|
{
|
||||||
using _is_limit = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Limit>;
|
||||||
|
|
||||||
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
|
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
|
||||||
// FIXME: Is this really always empty?
|
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
|
|
||||||
limit_t(Limit value):
|
limit_t(Limit value):
|
||||||
_value(value)
|
_value(value)
|
||||||
@ -65,9 +65,10 @@ namespace sqlpp
|
|||||||
template<typename Database>
|
template<typename Database>
|
||||||
struct dynamic_limit_t
|
struct dynamic_limit_t
|
||||||
{
|
{
|
||||||
using _is_limit = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>;
|
||||||
using _is_dynamic = std::true_type;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
|
dynamic_limit_t& _limit() { return *this; }
|
||||||
|
|
||||||
dynamic_limit_t():
|
dynamic_limit_t():
|
||||||
_value(noop())
|
_value(noop())
|
||||||
@ -95,8 +96,8 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
|
// 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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -106,8 +107,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct no_limit_t
|
struct no_limit_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
5
include/sqlpp11/vendor/noop.h
vendored
5
include/sqlpp11/vendor/noop.h
vendored
@ -28,6 +28,8 @@
|
|||||||
#define SQLPP_NOOP_H
|
#define SQLPP_NOOP_H
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <sqlpp11/no_value.h>
|
||||||
|
#include <sqlpp11/vendor/serializer.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -35,7 +37,8 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct noop
|
struct noop
|
||||||
{
|
{
|
||||||
using is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context>
|
template<typename Context>
|
||||||
|
20
include/sqlpp11/vendor/offset.h
vendored
20
include/sqlpp11/vendor/offset.h
vendored
@ -39,8 +39,9 @@ namespace sqlpp
|
|||||||
template<typename Offset>
|
template<typename Offset>
|
||||||
struct offset_t
|
struct offset_t
|
||||||
{
|
{
|
||||||
using _is_offset = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<Offset>;
|
||||||
|
|
||||||
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
|
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
|
||||||
|
|
||||||
offset_t(Offset value):
|
offset_t(Offset value):
|
||||||
@ -64,9 +65,10 @@ namespace sqlpp
|
|||||||
template<typename Database>
|
template<typename Database>
|
||||||
struct dynamic_offset_t
|
struct dynamic_offset_t
|
||||||
{
|
{
|
||||||
using _is_offset = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>;
|
||||||
using _is_dynamic = std::true_type;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
|
dynamic_offset_t& _offset() { return *this; }
|
||||||
|
|
||||||
dynamic_offset_t():
|
dynamic_offset_t():
|
||||||
_value(noop())
|
_value(noop())
|
||||||
@ -94,8 +96,8 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
|
// 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;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,8 +107,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct no_offset_t
|
struct no_offset_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
18
include/sqlpp11/vendor/order_by.h
vendored
18
include/sqlpp11/vendor/order_by.h
vendored
@ -42,12 +42,10 @@ namespace sqlpp
|
|||||||
template<typename Database,typename... Expressions>
|
template<typename Database,typename... Expressions>
|
||||||
struct order_by_t
|
struct order_by_t
|
||||||
{
|
{
|
||||||
using _is_order_by = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::group_by>;
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _recursive_traits = make_recursive_traits<Expressions...>;
|
||||||
using _parameter_tuple_t = std::tuple<Expressions...>;
|
|
||||||
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
|
|
||||||
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one sort-order expression required in order_by()");
|
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one sort-order expression required in order_by()");
|
||||||
|
|
||||||
@ -55,6 +53,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
static_assert(::sqlpp::detail::all_t<is_sort_order_t<Expressions>::value...>::value, "at least one argument is not a sort order expression in order_by()");
|
static_assert(::sqlpp::detail::all_t<is_sort_order_t<Expressions>::value...>::value, "at least one argument is not a sort order expression in order_by()");
|
||||||
|
|
||||||
|
order_by_t& _order_by() { return *this; }
|
||||||
|
|
||||||
order_by_t(Expressions... expressions):
|
order_by_t(Expressions... expressions):
|
||||||
_expressions(expressions...)
|
_expressions(expressions...)
|
||||||
{}
|
{}
|
||||||
@ -90,21 +90,21 @@ namespace sqlpp
|
|||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
void _add_order_by_impl(Expression expression, const std::true_type&)
|
void _add_order_by_impl(Expression expression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_order_by._dynamic_expressions.emplace_back(expression);
|
return static_cast<typename Policies::_statement_t*>(this)->_order_by()._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
void _add_order_by_impl(Expression expression, const std::false_type&);
|
void _add_order_by_impl(Expression expression, const std::false_type&);
|
||||||
};
|
};
|
||||||
|
|
||||||
_parameter_tuple_t _expressions;
|
std::tuple<Expressions...> _expressions;
|
||||||
vendor::interpretable_list_t<Database> _dynamic_expressions;
|
vendor::interpretable_list_t<Database> _dynamic_expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct no_order_by_t
|
struct no_order_by_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
41
include/sqlpp11/vendor/select_column_list.h
vendored
41
include/sqlpp11/vendor/select_column_list.h
vendored
@ -47,14 +47,14 @@ namespace sqlpp
|
|||||||
template<typename... Rest>
|
template<typename... Rest>
|
||||||
struct get_first_argument_if_unique
|
struct get_first_argument_if_unique
|
||||||
{
|
{
|
||||||
using _value_type = no_value_t;
|
using _traits = make_traits<no_value_t, tag::select_column_list, tag::return_value>;
|
||||||
struct _name_t {};
|
struct _name_t {};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct get_first_argument_if_unique<T>
|
struct get_first_argument_if_unique<T>
|
||||||
{
|
{
|
||||||
using _value_type = typename T::_value_type;
|
using _traits = make_traits<value_type_of<T>, tag::select_column_list, tag::return_value, tag::expression, tag::named_expression>;
|
||||||
using _name_t = typename T::_name_t;
|
using _name_t = typename T::_name_t;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -132,12 +132,13 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Columns>
|
template<typename Database, typename... Columns>
|
||||||
struct select_column_list_t
|
struct select_column_list_t
|
||||||
{
|
{
|
||||||
using _is_select_column_list = std::true_type;
|
// get_first_argument_if_unique is kind of ugly
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _traits = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_traits;
|
||||||
using _parameter_tuple_t = std::tuple<Columns...>;
|
using _recursive_traits = make_recursive_traits<Columns...>;
|
||||||
using size = std::tuple_size<_parameter_tuple_t>;
|
|
||||||
|
|
||||||
using _table_set = sqlpp::detail::make_joined_set_t<typename Columns::_table_set...>;
|
using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_name_t;
|
||||||
|
|
||||||
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
|
|
||||||
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected");
|
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected");
|
||||||
|
|
||||||
@ -148,13 +149,7 @@ namespace sqlpp
|
|||||||
static_assert(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected");
|
static_assert(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected");
|
||||||
|
|
||||||
struct _column_type {};
|
struct _column_type {};
|
||||||
struct _value_type: ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_value_type
|
|
||||||
{
|
|
||||||
using _is_expression = typename std::conditional<sizeof...(Columns) == 1, std::true_type, std::false_type>::type;
|
|
||||||
using _is_named_expression = typename std::conditional<sizeof...(Columns) == 1, std::true_type, std::false_type>::type;
|
|
||||||
using _is_alias = std::false_type;
|
|
||||||
};
|
|
||||||
using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_name_t;
|
|
||||||
|
|
||||||
template<typename Db>
|
template<typename Db>
|
||||||
using _result_row_t = typename std::conditional<_is_dynamic::value,
|
using _result_row_t = typename std::conditional<_is_dynamic::value,
|
||||||
@ -169,6 +164,8 @@ namespace sqlpp
|
|||||||
template <typename Db>
|
template <typename Db>
|
||||||
using _dynamic_t = select_column_list_t<Db, std::tuple<Columns...>>;
|
using _dynamic_t = select_column_list_t<Db, std::tuple<Columns...>>;
|
||||||
|
|
||||||
|
select_column_list_t& _select_column_list() { return *this; }
|
||||||
|
|
||||||
select_column_list_t(std::tuple<Columns...> columns):
|
select_column_list_t(std::tuple<Columns...> columns):
|
||||||
_columns(columns)
|
_columns(columns)
|
||||||
{}
|
{}
|
||||||
@ -185,7 +182,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
static constexpr size_t static_size()
|
static constexpr size_t static_size()
|
||||||
{
|
{
|
||||||
return size::value;
|
return sizeof...(Columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
@ -218,7 +215,7 @@ namespace sqlpp
|
|||||||
template<typename NamedExpression>
|
template<typename NamedExpression>
|
||||||
void _add_column_impl(NamedExpression namedExpression, const std::true_type&)
|
void _add_column_impl(NamedExpression namedExpression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_column_list._dynamic_columns.emplace_back(namedExpression);
|
return static_cast<typename Policies::_statement_t*>(this)->_select_column_list()._dynamic_columns.emplace_back(namedExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename NamedExpression>
|
template<typename NamedExpression>
|
||||||
@ -227,7 +224,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
|
|
||||||
const select_column_list_t& _column_list() const { return *this; }
|
const select_column_list_t& _column_list() const { return *this; }
|
||||||
_parameter_tuple_t _columns;
|
std::tuple<Columns...> _columns;
|
||||||
dynamic_select_column_list<Database> _dynamic_columns;
|
dynamic_select_column_list<Database> _dynamic_columns;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -244,12 +241,12 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct no_select_column_list_t
|
struct no_select_column_list_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop, ::sqlpp::tag::missing>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Db>
|
template<typename Db>
|
||||||
using _result_row_t = ::sqlpp::result_row_t<Db>;
|
using _result_row_t = ::sqlpp::result_row_t<Db>;
|
||||||
using _dynamic_names_t = typename dynamic_select_column_list<void>::_names_t;
|
using _dynamic_names_t = typename dynamic_select_column_list<void>::_names_t;
|
||||||
using _value_type = no_value_t;
|
|
||||||
struct _name_t {};
|
struct _name_t {};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -291,10 +288,10 @@ namespace sqlpp
|
|||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
// check for at least one expression
|
// check for at least one expression
|
||||||
static_assert(T::_is_dynamic::value or T::size::value, "at least one select expression required");
|
static_assert(T::_is_dynamic::value or sizeof...(Columns), "at least one select expression required");
|
||||||
|
|
||||||
interpret_tuple(t._columns, ',', context);
|
interpret_tuple(t._columns, ',', context);
|
||||||
if (T::size::value and not t._dynamic_columns.empty())
|
if (sizeof...(Columns) and not t._dynamic_columns.empty())
|
||||||
context << ',';
|
context << ',';
|
||||||
serialize(t._dynamic_columns, context);
|
serialize(t._dynamic_columns, context);
|
||||||
return context;
|
return context;
|
||||||
|
17
include/sqlpp11/vendor/select_flag_list.h
vendored
17
include/sqlpp11/vendor/select_flag_list.h
vendored
@ -42,16 +42,17 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Flags>
|
template<typename Database, typename... Flags>
|
||||||
struct select_flag_list_t
|
struct select_flag_list_t
|
||||||
{
|
{
|
||||||
using _is_select_flag_list = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::select_flag_list>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Flags...>;
|
||||||
|
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
using _parameter_tuple_t = std::tuple<Flags...>;
|
|
||||||
using size = std::tuple_size<_parameter_tuple_t>;
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Flags::_table_set...>::type;
|
|
||||||
|
|
||||||
static_assert(not ::sqlpp::detail::has_duplicates<Flags...>::value, "at least one duplicate argument detected in select flag list");
|
static_assert(not ::sqlpp::detail::has_duplicates<Flags...>::value, "at least one duplicate argument detected in select flag list");
|
||||||
|
|
||||||
static_assert(::sqlpp::detail::all_t<is_select_flag_t<Flags>::value...>::value, "at least one argument is not a select flag in select flag list");
|
static_assert(::sqlpp::detail::all_t<is_select_flag_t<Flags>::value...>::value, "at least one argument is not a select flag in select flag list");
|
||||||
|
|
||||||
|
select_flag_list_t& _select_flag_list() { return *this; }
|
||||||
|
|
||||||
select_flag_list_t(Flags... flags):
|
select_flag_list_t(Flags... flags):
|
||||||
_flags(flags...)
|
_flags(flags...)
|
||||||
{}
|
{}
|
||||||
@ -87,7 +88,7 @@ namespace sqlpp
|
|||||||
template<typename Flag>
|
template<typename Flag>
|
||||||
void _add_flag_impl(Flag flag, const std::true_type&)
|
void _add_flag_impl(Flag flag, const std::true_type&)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_flag_list._dynamic_flags.emplace_back(flag);
|
return static_cast<typename Policies::_statement_t*>(this)->_select_flag_list()._dynamic_flags.emplace_back(flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Flag>
|
template<typename Flag>
|
||||||
@ -95,14 +96,14 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
const select_flag_list_t& _flag_list() const { return *this; }
|
const select_flag_list_t& _flag_list() const { return *this; }
|
||||||
_parameter_tuple_t _flags;
|
std::tuple<Flags...> _flags;
|
||||||
vendor::interpretable_list_t<Database> _dynamic_flags;
|
vendor::interpretable_list_t<Database> _dynamic_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct no_select_flag_list_t
|
struct no_select_flag_list_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
5
include/sqlpp11/vendor/select_pseudo_table.h
vendored
5
include/sqlpp11/vendor/select_pseudo_table.h
vendored
@ -35,8 +35,11 @@ namespace sqlpp
|
|||||||
template<typename Expr>
|
template<typename Expr>
|
||||||
struct select_column_spec_t
|
struct select_column_spec_t
|
||||||
{
|
{
|
||||||
|
using _traits = make_traits<value_type_of<Expr>>;
|
||||||
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
using _value_type = value_type_of<Expr>; // FIXME: column specs probably should use _traits, too
|
||||||
|
|
||||||
using _name_t = typename Expr::_name_t;
|
using _name_t = typename Expr::_name_t;
|
||||||
using _value_type = typename Expr::_value_type;
|
|
||||||
struct _column_type
|
struct _column_type
|
||||||
{
|
{
|
||||||
using _must_not_insert = std::true_type;
|
using _must_not_insert = std::true_type;
|
||||||
|
38
include/sqlpp11/vendor/single_table.h
vendored
38
include/sqlpp11/vendor/single_table.h
vendored
@ -28,6 +28,8 @@
|
|||||||
#define SQLPP_VENDOR_SINGLE_TABLE_H
|
#define SQLPP_VENDOR_SINGLE_TABLE_H
|
||||||
|
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/no_value.h>
|
||||||
|
#include <sqlpp11/vendor/serializer.h>
|
||||||
#include <sqlpp11/detail/type_set.h>
|
#include <sqlpp11/detail/type_set.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
@ -38,9 +40,11 @@ namespace sqlpp
|
|||||||
template<typename Database, typename Table>
|
template<typename Database, typename Table>
|
||||||
struct single_table_t
|
struct single_table_t
|
||||||
{
|
{
|
||||||
using _is_single_table = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::single_table>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Table>;
|
||||||
|
|
||||||
static_assert(is_table_t<Table>::value, "argument has to be a table");
|
static_assert(is_table_t<Table>::value, "argument has to be a table");
|
||||||
|
static_assert(required_tables_of<Table>::size::value == 0, "table depends on another table");
|
||||||
|
|
||||||
single_table_t(Table table):
|
single_table_t(Table table):
|
||||||
_table(table)
|
_table(table)
|
||||||
@ -52,13 +56,41 @@ namespace sqlpp
|
|||||||
single_table_t& operator=(single_table_t&&) = default;
|
single_table_t& operator=(single_table_t&&) = default;
|
||||||
~single_table_t() = default;
|
~single_table_t() = default;
|
||||||
|
|
||||||
using _table_set = typename Table::_table_set;
|
template<typename Policies>
|
||||||
|
struct _methods_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
Table _table;
|
Table _table;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct no_single_table_t
|
struct no_single_table_t
|
||||||
{
|
{
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
|
||||||
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
|
template<typename Policies>
|
||||||
|
struct _methods_t
|
||||||
|
{
|
||||||
|
using _database_t = typename Policies::_database_t;
|
||||||
|
template<typename T>
|
||||||
|
using _new_statement_t = typename Policies::template _new_statement_t<no_single_table_t, T>;
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
auto into(Args... args)
|
||||||
|
-> _new_statement_t<single_table_t<void, Args...>>
|
||||||
|
{
|
||||||
|
return { *static_cast<typename Policies::_statement_t*>(this), single_table_t<void, Args...>{args...} };
|
||||||
|
}
|
||||||
|
|
||||||
|
#warning: remove can operate on several tables at once, so it should not use single_table anyway
|
||||||
|
template<typename... Args>
|
||||||
|
auto from(Args... args)
|
||||||
|
-> _new_statement_t<single_table_t<void, Args...>>
|
||||||
|
{
|
||||||
|
return { *static_cast<typename Policies::_statement_t*>(this), single_table_t<void, Args...>{args...} };
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Interpreters
|
// Interpreters
|
||||||
|
17
include/sqlpp11/vendor/update_list.h
vendored
17
include/sqlpp11/vendor/update_list.h
vendored
@ -40,9 +40,9 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Assignments>
|
template<typename Database, typename... Assignments>
|
||||||
struct update_list_t
|
struct update_list_t
|
||||||
{
|
{
|
||||||
using _is_update_list = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::update_list>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Assignments...>;
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
using _parameter_tuple_t = std::tuple<Assignments...>;
|
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment expression required in set()");
|
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment expression required in set()");
|
||||||
|
|
||||||
@ -52,11 +52,16 @@ namespace sqlpp
|
|||||||
|
|
||||||
static_assert(::sqlpp::detail::none_t<must_not_update_t<typename Assignments::_column_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
|
static_assert(::sqlpp::detail::none_t<must_not_update_t<typename Assignments::_column_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
|
||||||
|
|
||||||
|
#warning reactivate tests
|
||||||
|
/*
|
||||||
using _column_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::_column_t::_table_set...>::type;
|
using _column_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::_column_t::_table_set...>::type;
|
||||||
using _value_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::value_type::_table_set...>::type;
|
using _value_table_set = typename ::sqlpp::detail::make_joined_set<typename Assignments::value_type::_table_set...>::type;
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type;
|
using _table_set = typename ::sqlpp::detail::make_joined_set<_column_table_set, _value_table_set>::type;
|
||||||
static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns");
|
static_assert(sizeof...(Assignments) ? (_column_table_set::size::value == 1) : true, "set() contains assignments for tables from several columns");
|
||||||
static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables");
|
static_assert(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables");
|
||||||
|
*/
|
||||||
|
|
||||||
|
update_list_t& _update_list() { return *this; }
|
||||||
|
|
||||||
update_list_t(Assignments... assignments):
|
update_list_t(Assignments... assignments):
|
||||||
_assignments(assignments...)
|
_assignments(assignments...)
|
||||||
@ -97,7 +102,7 @@ namespace sqlpp
|
|||||||
template<typename Assignment>
|
template<typename Assignment>
|
||||||
void _add_set_impl(Assignment assignment, const std::true_type&)
|
void _add_set_impl(Assignment assignment, const std::true_type&)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_update_list._dynamic_assignments.emplace_back(assignment);
|
return static_cast<typename Policies::_statement_t*>(this)->_update_list()._dynamic_assignments.emplace_back(assignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Assignment>
|
template<typename Assignment>
|
||||||
@ -105,14 +110,14 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
_parameter_tuple_t _assignments;
|
std::tuple<Assignments...> _assignments;
|
||||||
typename vendor::interpretable_list_t<Database> _dynamic_assignments;
|
typename vendor::interpretable_list_t<Database> _dynamic_assignments;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct no_update_list_t
|
struct no_update_list_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
15
include/sqlpp11/vendor/using.h
vendored
15
include/sqlpp11/vendor/using.h
vendored
@ -41,9 +41,10 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Tables>
|
template<typename Database, typename... Tables>
|
||||||
struct using_t
|
struct using_t
|
||||||
{
|
{
|
||||||
using _is_using = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::using_>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Tables...>;
|
||||||
|
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
using _parameter_tuple_t = std::tuple<Tables...>;
|
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()");
|
static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()");
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not an table in using()");
|
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::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& _using() { return *this; }
|
||||||
|
|
||||||
using_t(Tables... tables):
|
using_t(Tables... tables):
|
||||||
_tables(tables...)
|
_tables(tables...)
|
||||||
@ -81,7 +82,7 @@ namespace sqlpp
|
|||||||
template<typename Table>
|
template<typename Table>
|
||||||
void _add_using_impl(Table table, const std::true_type&)
|
void _add_using_impl(Table table, const std::true_type&)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_using._dynamic_tables.emplace_back(table);
|
return static_cast<typename Policies::_statement_t*>(this)->_using()._dynamic_tables.emplace_back(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Table>
|
template<typename Table>
|
||||||
@ -89,14 +90,14 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
_parameter_tuple_t _tables;
|
std::tuple<Tables...> _tables;
|
||||||
vendor::interpretable_list_t<Database> _dynamic_tables;
|
vendor::interpretable_list_t<Database> _dynamic_tables;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct no_using_t
|
struct no_using_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
2
include/sqlpp11/vendor/value_type.h
vendored
2
include/sqlpp11/vendor/value_type.h
vendored
@ -35,7 +35,7 @@ namespace sqlpp
|
|||||||
namespace vendor
|
namespace vendor
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using value_type_t = typename wrap_operand<T>::type::_value_type;
|
using value_type_t = value_type_of<wrap_operand_t<T>>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
24
include/sqlpp11/vendor/where.h
vendored
24
include/sqlpp11/vendor/where.h
vendored
@ -42,17 +42,16 @@ namespace sqlpp
|
|||||||
template<typename Database, typename... Expressions>
|
template<typename Database, typename... Expressions>
|
||||||
struct where_t
|
struct where_t
|
||||||
{
|
{
|
||||||
using _is_where = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
|
||||||
|
using _recursive_traits = make_recursive_traits<Expressions...>;
|
||||||
|
|
||||||
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
|
||||||
using _parameter_tuple_t = std::tuple<Expressions...>;
|
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()");
|
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()");
|
||||||
static_assert(sqlpp::detail::none_t<is_assignment_t<Expressions>::value...>::value, "at least one argument is an assignment in where()");
|
static_assert(sqlpp::detail::none_t<is_assignment_t<Expressions>::value...>::value, "at least one argument is an assignment in where()");
|
||||||
static_assert(sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()");
|
static_assert(sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()");
|
||||||
|
|
||||||
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
|
where_t& _where() { return *this; }
|
||||||
|
|
||||||
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
|
|
||||||
|
|
||||||
where_t(Expressions... expressions):
|
where_t(Expressions... expressions):
|
||||||
_expressions(expressions...)
|
_expressions(expressions...)
|
||||||
@ -78,7 +77,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
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()");
|
static_assert(not 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<_is_dynamic::value, is_expression_t<Expression>::value>;
|
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
|
||||||
|
|
||||||
@ -89,23 +88,22 @@ namespace sqlpp
|
|||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
void _add_where_impl(Expression expression, const std::true_type&)
|
void _add_where_impl(Expression expression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return static_cast<typename Policies::_statement_t*>(this)->_where._dynamic_expressions.emplace_back(expression);
|
return static_cast<typename Policies::_statement_t*>(this)->_where()._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
void _add_where_impl(Expression expression, const std::false_type&);
|
void _add_where_impl(Expression expression, const std::false_type&);
|
||||||
};
|
};
|
||||||
|
|
||||||
_parameter_tuple_t _expressions;
|
std::tuple<Expressions...> _expressions;
|
||||||
vendor::interpretable_list_t<Database> _dynamic_expressions;
|
vendor::interpretable_list_t<Database> _dynamic_expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct where_t<void, bool>
|
struct where_t<void, bool>
|
||||||
{
|
{
|
||||||
using _is_where = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
|
||||||
using _is_dynamic = std::false_type;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
|
|
||||||
where_t(bool condition):
|
where_t(bool condition):
|
||||||
_condition(condition)
|
_condition(condition)
|
||||||
@ -127,8 +125,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct no_where_t
|
struct no_where_t
|
||||||
{
|
{
|
||||||
using _is_noop = std::true_type;
|
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
template<typename Policies>
|
template<typename Policies>
|
||||||
struct _methods_t
|
struct _methods_t
|
||||||
|
26
include/sqlpp11/vendor/wrap_operand.h
vendored
26
include/sqlpp11/vendor/wrap_operand.h
vendored
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sqlpp11/vendor/serializer.h>
|
#include <sqlpp11/vendor/serializer.h>
|
||||||
#include <sqlpp11/detail/type_set.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -45,10 +45,10 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct boolean_operand
|
struct boolean_operand
|
||||||
{
|
{
|
||||||
static constexpr bool _is_expression = true;
|
using _traits = make_traits<::sqlpp::detail::boolean, ::sqlpp::tag::expression>;
|
||||||
using _value_type = sqlpp::detail::boolean;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
using _value_t = bool;
|
using _value_t = bool;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
|
|
||||||
boolean_operand():
|
boolean_operand():
|
||||||
_t{}
|
_t{}
|
||||||
@ -83,10 +83,10 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct integral_operand
|
struct integral_operand
|
||||||
{
|
{
|
||||||
static constexpr bool _is_expression = true;
|
using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression>;
|
||||||
using _value_type = ::sqlpp::detail::integral;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
using _value_t = int64_t;
|
using _value_t = int64_t;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
|
|
||||||
integral_operand():
|
integral_operand():
|
||||||
_t{}
|
_t{}
|
||||||
@ -122,10 +122,10 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct floating_point_operand
|
struct floating_point_operand
|
||||||
{
|
{
|
||||||
static constexpr bool _is_expression = true;
|
using _traits = make_traits<::sqlpp::detail::floating_point, ::sqlpp::tag::expression>;
|
||||||
using _value_type = ::sqlpp::detail::floating_point;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
using _value_t = double;
|
using _value_t = double;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
|
|
||||||
floating_point_operand():
|
floating_point_operand():
|
||||||
_t{}
|
_t{}
|
||||||
@ -160,10 +160,10 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct text_operand
|
struct text_operand
|
||||||
{
|
{
|
||||||
static constexpr bool _is_expression = true;
|
using _traits = make_traits<::sqlpp::detail::text, ::sqlpp::tag::expression>;
|
||||||
using _value_type = ::sqlpp::detail::text;
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
using _value_t = std::string;
|
using _value_t = std::string;
|
||||||
using _table_set = ::sqlpp::detail::type_set<>;
|
|
||||||
|
|
||||||
text_operand():
|
text_operand():
|
||||||
_t{}
|
_t{}
|
||||||
|
@ -49,8 +49,6 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct verbatim_table_t: public sqlpp::table_t<verbatim_table_t, detail::unusable_pseudo_column_t>
|
struct verbatim_table_t: public sqlpp::table_t<verbatim_table_t, detail::unusable_pseudo_column_t>
|
||||||
{
|
{
|
||||||
using _value_type = no_value_t;
|
|
||||||
|
|
||||||
verbatim_table_t(std::string name):
|
verbatim_table_t(std::string name):
|
||||||
_name(name)
|
_name(name)
|
||||||
{
|
{
|
||||||
|
@ -6,14 +6,14 @@ macro (build_and_run arg)
|
|||||||
add_test(${arg} ${arg})
|
add_test(${arg} ${arg})
|
||||||
endmacro ()
|
endmacro ()
|
||||||
|
|
||||||
build_and_run(InterpretTest)
|
#build_and_run(InterpretTest)
|
||||||
build_and_run(InsertTest)
|
#build_and_run(InsertTest)
|
||||||
build_and_run(RemoveTest)
|
#build_and_run(RemoveTest)
|
||||||
build_and_run(UpdateTest)
|
build_and_run(UpdateTest)
|
||||||
build_and_run(SelectTest)
|
#build_and_run(SelectTest)
|
||||||
build_and_run(SelectTypeTest)
|
#build_and_run(SelectTypeTest)
|
||||||
build_and_run(FunctionTest)
|
#build_and_run(FunctionTest)
|
||||||
build_and_run(PreparedTest)
|
#build_and_run(PreparedTest)
|
||||||
|
|
||||||
find_package(PythonInterp REQUIRED)
|
find_package(PythonInterp REQUIRED)
|
||||||
|
|
||||||
|
@ -188,6 +188,8 @@ int main()
|
|||||||
|
|
||||||
// Test any
|
// Test any
|
||||||
{
|
{
|
||||||
|
using S = decltype(select(t.alpha).from(t));
|
||||||
|
static_assert(sqlpp::is_numeric_t<S>::value, "type requirement");
|
||||||
|
|
||||||
using TI = decltype(any(select(t.alpha).from(t)));
|
using TI = decltype(any(select(t.alpha).from(t)));
|
||||||
using TT = decltype(any(select(t.beta).from(t)));
|
using TT = decltype(any(select(t.beta).from(t)));
|
||||||
|
@ -158,10 +158,10 @@ int main()
|
|||||||
|
|
||||||
// Test a select of a single column without a from
|
// Test a select of a single column without a from
|
||||||
{
|
{
|
||||||
using T = decltype(select(t.alpha)); // Hint: The current rule is pretty crude (a from is required), but certainly better than nothing
|
using T = decltype(select(t.alpha));
|
||||||
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
|
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
|
static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
|
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
|
||||||
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
|
static_assert(not sqlpp::require_insert_t<T>::value, "type requirement");
|
||||||
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
|
static_assert(not sqlpp::must_not_insert_t<T>::value, "type requirement");
|
||||||
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
|
static_assert(not sqlpp::must_not_update_t<T>::value, "type requirement");
|
||||||
@ -175,8 +175,8 @@ int main()
|
|||||||
// Test a select of a single numeric table column
|
// Test a select of a single numeric table column
|
||||||
{
|
{
|
||||||
using T = decltype(select(t.alpha).from(t));
|
using T = decltype(select(t.alpha).from(t));
|
||||||
static_assert(sqlpp::is_select_column_list_t<decltype(T::_column_list)>::value, "Must not be noop");
|
//static_assert(sqlpp::is_select_column_list_t<decltype(T::_column_list)>::value, "Must not be noop");
|
||||||
static_assert(sqlpp::is_from_t<decltype(T::_from)>::value, "Must not be noop");
|
//static_assert(sqlpp::is_from_t<decltype(T::_from)>::value, "Must not be noop");
|
||||||
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
|
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
|
static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
|
||||||
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
|
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
|
||||||
@ -290,7 +290,7 @@ int main()
|
|||||||
{
|
{
|
||||||
auto m = multi_column(t.alpha, t.beta).as(alias::a);
|
auto m = multi_column(t.alpha, t.beta).as(alias::a);
|
||||||
auto a = select(m).from(t).as(alias::b).a;
|
auto a = select(m).from(t).as(alias::b).a;
|
||||||
static_assert(not sqlpp::is_value_t<decltype(a)>::value, "a multi_column is not a value");
|
// FIXME: Do we really need that test? multi_column is a no_value static_assert(not sqlpp::is_expression_t<decltype(a)>::value, "a multi_column is not a value");
|
||||||
}
|
}
|
||||||
// Test that result sets with identical name/value combinations have identical types
|
// Test that result sets with identical name/value combinations have identical types
|
||||||
{
|
{
|
||||||
@ -299,8 +299,8 @@ int main()
|
|||||||
using A = typename decltype(a)::_result_row_t<MockDb>;
|
using A = typename decltype(a)::_result_row_t<MockDb>;
|
||||||
using B = typename decltype(b)::_result_row_t<MockDb>;
|
using B = typename decltype(b)::_result_row_t<MockDb>;
|
||||||
static_assert(std::is_same<
|
static_assert(std::is_same<
|
||||||
decltype(t.alpha)::_value_type::_base_value_type,
|
sqlpp::value_type_of<decltype(t.alpha)>,
|
||||||
decltype(f.epsilon)::_value_type::_base_value_type>::value, "Two bigint columns must have identical base_value_type");
|
sqlpp::value_type_of<decltype(f.epsilon)>>::value, "Two bigint columns must have identical base_value_type");
|
||||||
static_assert(std::is_same<A, B>::value, "select with identical columns(name/value_type) need to have identical result_types");
|
static_assert(std::is_same<A, B>::value, "select with identical columns(name/value_type) need to have identical result_types");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,9 +339,8 @@ int main()
|
|||||||
static_assert(sqlpp::is_select_flag_t<decltype(sqlpp::all)>::value, "sqlpp::all has to be a select_flag");
|
static_assert(sqlpp::is_select_flag_t<decltype(sqlpp::all)>::value, "sqlpp::all has to be a select_flag");
|
||||||
using T = sqlpp::vendor::wrap_operand<int>::type;
|
using T = sqlpp::vendor::wrap_operand<int>::type;
|
||||||
static_assert(sqlpp::is_regular<T>::value, "type requirement");
|
static_assert(sqlpp::is_regular<T>::value, "type requirement");
|
||||||
static_assert(T::_is_expression, "T has to be an expression");
|
static_assert(sqlpp::is_expression_t<T>::value, "T has to be an expression");
|
||||||
static_assert(std::is_same<typename T::_value_type::_is_numeric, std::true_type>::value, "T has to be a numeric");
|
static_assert(sqlpp::is_numeric_t<T>::value, "T has to be numeric");
|
||||||
static_assert(sqlpp::is_numeric_t<T>::value, "T has to be a numeric");
|
|
||||||
static_assert(sqlpp::is_numeric_t<decltype(t.alpha)>::value, "TabBar.alpha has to be a numeric");
|
static_assert(sqlpp::is_numeric_t<decltype(t.alpha)>::value, "TabBar.alpha has to be a numeric");
|
||||||
((t.alpha + 7) + 4).asc();
|
((t.alpha + 7) + 4).asc();
|
||||||
static_assert(sqlpp::is_boolean_t<decltype(t.gamma == t.gamma)>::value, "Comparison expression have to be boolean");
|
static_assert(sqlpp::is_boolean_t<decltype(t.gamma == t.gamma)>::value, "Comparison expression have to be boolean");
|
||||||
@ -353,7 +352,6 @@ int main()
|
|||||||
static_assert(sqlpp::must_not_insert_t<decltype(t.alpha)>::value, "alpha must not be inserted");
|
static_assert(sqlpp::must_not_insert_t<decltype(t.alpha)>::value, "alpha must not be inserted");
|
||||||
serialize(t.alpha, printer).str();
|
serialize(t.alpha, printer).str();
|
||||||
std::cerr << "\n" << sizeof(test::TabBar) << std::endl;
|
std::cerr << "\n" << sizeof(test::TabBar) << std::endl;
|
||||||
static_assert(std::is_same<typename decltype(t.alpha)::_value_type::_is_named_expression, std::true_type>::value, "alpha should be a named expression");
|
|
||||||
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha)>::value, "alpha should be a named expression");
|
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha)>::value, "alpha should be a named expression");
|
||||||
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be a named expression");
|
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be a named expression");
|
||||||
static_assert(sqlpp::is_alias_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be an alias");
|
static_assert(sqlpp::is_alias_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be an alias");
|
||||||
@ -366,6 +364,7 @@ int main()
|
|||||||
auto s = select(r.a).from(r);
|
auto s = select(r.a).from(r);
|
||||||
using RA = decltype(r.a);
|
using RA = decltype(r.a);
|
||||||
using S = decltype(s);
|
using S = decltype(s);
|
||||||
|
/*
|
||||||
using SCL = typename S::_column_list_t;
|
using SCL = typename S::_column_list_t;
|
||||||
using SF = typename S::_from_t;
|
using SF = typename S::_from_t;
|
||||||
static_assert(sqlpp::is_select_column_list_t<SCL>::value, "no column list");
|
static_assert(sqlpp::is_select_column_list_t<SCL>::value, "no column list");
|
||||||
@ -375,6 +374,7 @@ int main()
|
|||||||
static_assert(SCL_T::size::value == 1, "unexpected table_set in column_list");
|
static_assert(SCL_T::size::value == 1, "unexpected table_set in column_list");
|
||||||
static_assert(SF_T::size::value == 1, "unexpected table_set in from");
|
static_assert(SF_T::size::value == 1, "unexpected table_set in from");
|
||||||
static_assert(std::is_same<SCL_T, SF_T>::value, "should be the same");
|
static_assert(std::is_same<SCL_T, SF_T>::value, "should be the same");
|
||||||
|
*/
|
||||||
static_assert(sqlpp::is_boolean_t<decltype(select(r.a).from(r))>::value, "select(bool) has to be a bool");
|
static_assert(sqlpp::is_boolean_t<decltype(select(r.a).from(r))>::value, "select(bool) has to be a bool");
|
||||||
auto s1 = sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r))
|
auto s1 = sqlpp::select().flags(sqlpp::distinct, sqlpp::straight_join).columns(l.alpha, l.beta, select(r.a).from(r))
|
||||||
.from(r,t,l)
|
.from(r,t,l)
|
||||||
|
Loading…
Reference in New Issue
Block a user