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

Merge branch 'release/0.14'

This commit is contained in:
rbock 2014-04-24 14:10:59 +02:00
commit 40d2a48134
118 changed files with 4396 additions and 2713 deletions

View File

@ -1,4 +1,4 @@
# Copyright (c) 2013, Roland Bock
# Copyright (c) 2013-2014, Roland Bock
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,4 +1,4 @@
Copyright (c) 2013, Roland Bock
Copyright (c) 2013-2014, Roland Bock
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -33,6 +33,9 @@ namespace sqlpp
template<typename Expression, typename AliasProvider>
struct expression_alias_t
{
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");
struct _value_type: Expression::_value_type
{
using _is_expression = std::false_type;
@ -41,6 +44,7 @@ namespace sqlpp
};
using _name_t = typename AliasProvider::_name_t;
using _table_set = typename Expression::_table_set;
Expression _expression;
};
@ -48,14 +52,14 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Expression, typename AliasProvider>
struct interpreter_t<Context, expression_alias_t<Expression, AliasProvider>>
struct serializer_t<Context, expression_alias_t<Expression, AliasProvider>>
{
using T = expression_alias_t<Expression, AliasProvider>;
static Context& _(const T& t, Context& context)
{
context << '(';
interpret(t._expression, context);
serialize(t._expression, context);
context << ") AS ";
context << T::_name_t::_get_name();
return context;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,6 +27,8 @@
#ifndef SQLPP_ALIAS_PROVIDER_H
#define SQLPP_ALIAS_PROVIDER_H
#include <type_traits>
#define SQLPP_ALIAS_PROVIDER(name) \
struct name##_t\
{\
@ -46,6 +48,18 @@
namespace sqlpp
{
template<typename T, typename Enable = void>
struct is_alias_provider_t
{
static constexpr bool value = false;
};
template<typename T>
struct is_alias_provider_t<T, typename std::enable_if<std::is_class<typename T::_name_t::template _member_t<int>>::value, void>::type>
{
static constexpr bool value = true;
};
namespace alias
{
SQLPP_ALIAS_PROVIDER(a);

71
include/sqlpp11/all_of.h Normal file
View File

@ -0,0 +1,71 @@
/*
* 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_ALL_OF_H
#define SQLPP_ALL_OF_H
#include <sqlpp11/interpret.h>
#include <sqlpp11/alias.h>
#include <sqlpp11/multi_column.h>
namespace sqlpp
{
template<typename Table>
struct all_of_t
{
using _column_tuple_t = typename Table::_column_tuple_t;
template<typename AliasProvider>
detail::copy_tuple_args_t<multi_column_alias_t, AliasProvider, _column_tuple_t> as(const AliasProvider& alias)
{
return ::sqlpp::multi_column(_column_tuple_t{}).as(alias);
}
};
template<typename Table>
auto all_of(Table t) -> all_of_t<Table>
{
return {};
}
namespace vendor
{
template<typename Context, typename Table>
struct serializer_t<Context, all_of_t<Table>>
{
using T = all_of_t<Table>;
static Context& _(const T& t, const Context&)
{
static_assert(wrong_t<T>::value, "all_of(table) does not seem to be used in select");
}
};
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,22 +27,20 @@
#ifndef SQLPP_ANY_H
#define SQLPP_ANY_H
#include <sstream>
#include <sqlpp11/boolean.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
namespace vendor
{
template<typename Select>
struct any_t: public boolean::template operators<any_t<Select>>
struct any_t
{
static_assert(is_select_t<Select>::value, "any() requires a single column select expression as argument");
static_assert(is_value_t<Select>::value, "any() requires a single column select expression as argument");
struct _value_type: public Select::_value_type::_base_value_type
{
using _is_multi_expression = std::true_type; // must not be named
using _is_expression = std::false_type;
using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc
};
struct _name_t
@ -57,6 +55,8 @@ namespace sqlpp
};
};
using _table_set = typename Select::_table_set;
any_t(Select select):
_select(select)
{}
@ -74,22 +74,24 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Select>
struct interpreter_t<Context, vendor::any_t<Select>>
struct serializer_t<Context, vendor::any_t<Select>>
{
using T = vendor::any_t<Select>;
static Context& _(const T& t, Context& context)
{
context << "ANY(";
interpret(t._select, context);
serialize(t._select, context);
context << ")";
return context;
}
};
template<typename T>
auto any(T t) -> typename vendor::any_t<typename operand_t<T, is_select_t>::type>
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_value_t<vendor::wrap_operand_t<T>>::value, "any() requires a single column select expression as argument");
return { t };
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,7 +27,6 @@
#ifndef SQLPP_AVG_H
#define SQLPP_AVG_H
#include <sstream>
#include <sqlpp11/type_traits.h>
namespace sqlpp
@ -35,7 +34,7 @@ namespace sqlpp
namespace vendor
{
template<typename Flag, typename Expr>
struct avg_t: public floating_point::template operators<avg_t<Flag, Expr>>
struct avg_t: public floating_point::template expression_operators<avg_t<Flag, 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_numeric_t<Expr>::value, "avg() requires a value expression as argument");
@ -45,6 +44,8 @@ namespace sqlpp
using _is_named_expression = std::true_type;
};
using _table_set = typename Expr::_table_set;
struct _name_t
{
static constexpr const char* _get_name() { return "AVG"; }
@ -74,7 +75,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Flag, typename Expr>
struct interpreter_t<Context, vendor::avg_t<Flag, Expr>>
struct serializer_t<Context, vendor::avg_t<Flag, Expr>>
{
using T = vendor::avg_t<Flag, Expr>;
@ -83,10 +84,10 @@ namespace sqlpp
context << "AVG(";
if (std::is_same<sqlpp::distinct_t, Flag>::value)
{
interpret(Flag(), context);
serialize(Flag(), context);
context << ' ';
}
interpret(t._expr, context);
serialize(t._expr, context);
context << ")";
return context;
}
@ -94,14 +95,16 @@ namespace sqlpp
}
template<typename T>
auto avg(T t) -> typename vendor::avg_t<vendor::noop, typename operand_t<T, is_value_t>::type>
auto avg(T t) -> typename vendor::avg_t<vendor::noop, vendor::wrap_operand_t<T>>
{
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
return { t };
}
template<typename T>
auto avg(const sqlpp::distinct_t&, T t) -> typename vendor::avg_t<sqlpp::distinct_t, typename operand_t<T, is_value_t>::type>
auto avg(const sqlpp::distinct_t&, T t) -> typename vendor::avg_t<sqlpp::distinct_t, vendor::wrap_operand_t<T>>
{
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
return { t };
}

View File

@ -0,0 +1,156 @@
/*
* 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_BASIC_EXPRESSION_OPERATORS_H
#define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H
#include <sqlpp11/alias.h>
#include <sqlpp11/sort_order.h>
#include <sqlpp11/vendor/expression_fwd.h>
#include <sqlpp11/vendor/in_fwd.h>
#include <sqlpp11/vendor/is_null_fwd.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
namespace detail
{
struct boolean;
}
// basic operators
template<typename Base, template<typename> class IsCorrectValueType>
struct basic_expression_operators
{
template<typename T>
struct _is_valid_comparison_operand
{
static constexpr bool value =
(is_expression_t<T>::value // expressions are OK
or is_multi_expression_t<T>::value) // multi-expressions like ANY are OK for comparisons, too
and IsCorrectValueType<T>::value // the correct value type is required, of course
;
};
template<typename T>
vendor::equal_to_t<Base, vendor::wrap_operand_t<T>> operator==(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::not_equal_to_t<Base, vendor::wrap_operand_t<T>> operator!=(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::less_than_t<Base, vendor::wrap_operand_t<T>> operator<(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::less_equal_t<Base, vendor::wrap_operand_t<T>> operator<=(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::greater_than_t<Base, vendor::wrap_operand_t<T>> operator>(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::greater_equal_t<Base, vendor::wrap_operand_t<T>> operator>=(T t) const
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} };
}
vendor::is_null_t<true, Base> is_null() const
{
return { *static_cast<const Base*>(this) };
}
vendor::is_null_t<false, Base> is_not_null() const
{
return { *static_cast<const Base*>(this) };
}
sort_order_t<Base, sort_type::asc> asc()
{
return { *static_cast<const Base*>(this) };
}
sort_order_t<Base, sort_type::desc> desc()
{
return { *static_cast<const Base*>(this) };
}
// Hint: use value_list wrapper for containers...
template<typename... T>
vendor::in_t<true, Base, vendor::wrap_operand_t<T>...> in(T... t) const
{
static_assert(detail::all_t<_is_valid_comparison_operand, vendor::wrap_operand_t<T>...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Base*>(this), vendor::wrap_operand_t<T>{t}... };
}
template<typename... T>
vendor::in_t<false, Base, vendor::wrap_operand_t<T>...> not_in(T... t) const
{
static_assert(detail::all_t<_is_valid_comparison_operand, vendor::wrap_operand_t<T>...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Base*>(this), vendor::wrap_operand_t<T>{t}... };
}
template<typename alias_provider>
expression_alias_t<Base, alias_provider> as(const alias_provider&)
{
return { *static_cast<const Base*>(this) };
}
};
}
#endif

View File

@ -1,137 +0,0 @@
/*
* Copyright (c) 2013, 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_BASIC_OPERATORS_H
#define SQLPP_DETAIL_BASIC_OPERATORS_H
#include <sqlpp11/alias.h>
#include <sqlpp11/sort_order.h>
#include <sqlpp11/vendor/expression_fwd.h>
#include <sqlpp11/vendor/in_fwd.h>
#include <sqlpp11/vendor/is_null_fwd.h>
namespace sqlpp
{
namespace detail
{
struct boolean;
}
// basic operators
template<typename Base, template<typename> class Constraint>
struct basic_operators
{
template<typename T>
vendor::equal_t<Base, typename Constraint<T>::type> operator==(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::not_equal_t<Base, typename Constraint<T>::type> operator!=(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::less_than_t<Base, typename Constraint<T>::type> operator<(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::less_equal_t<Base, typename Constraint<T>::type> operator<=(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::greater_than_t<Base, typename Constraint<T>::type> operator>(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::greater_equal_t<Base, typename Constraint<T>::type> operator>=(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
}
vendor::is_null_t<true, Base> is_null() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with is_null()");
return { *static_cast<const Base*>(this) };
}
vendor::is_null_t<false, Base> is_not_null() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with is_not_null()");
return { *static_cast<const Base*>(this) };
}
sort_order_t<Base, sort_type::asc> asc()
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used for sorting");
return { *static_cast<const Base*>(this) };
}
sort_order_t<Base, sort_type::desc> desc()
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used for sorting");
return { *static_cast<const Base*>(this) };
}
// Hint: use value_list wrapper for containers...
template<typename... T>
vendor::in_t<true, Base, typename Constraint<T>::type...> in(T... t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with in()");
return { *static_cast<const Base*>(this), {t}... };
}
template<typename... T>
vendor::in_t<false, Base, typename Constraint<T>::type...> not_in(T... t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot with be used with not_in()");
return { *static_cast<const Base*>(this), {t}... };
}
template<typename alias_provider>
expression_alias_t<Base, alias_provider> as(const alias_provider&)
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot have a name");
return { *static_cast<const Base*>(this) };
}
};
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,8 +28,9 @@
#define SQLPP_BOOLEAN_H
#include <cstdlib>
#include <cassert>
#include <ostream>
#include <sqlpp11/basic_operators.h>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
@ -41,6 +42,7 @@ namespace sqlpp
// boolean value type
struct boolean
{
using _value_type = boolean;
using _base_value_type = boolean;
using _is_boolean = std::true_type;
using _is_value = std::true_type;
@ -98,6 +100,7 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
_result_entry_t():
@ -133,15 +136,28 @@ namespace sqlpp
bool is_null() const
{
if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _is_null;
}
_cpp_value_type value() const
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
const bool null_value = _is_null and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value;
if (connector_assert_result_validity_t<Db>::value)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field");
}
return _value;
}
@ -160,36 +176,49 @@ namespace sqlpp
};
template<typename T>
using _operand_t = operand_t<T, is_boolean_t>;
template<typename T>
using _constraint = is_boolean_t<T>;
struct _is_valid_operand
{
static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_boolean_t<T>::value // the correct value type is required, of course
;
};
template<typename Base>
struct operators: public basic_operators<Base, _operand_t>
struct expression_operators: public basic_expression_operators<Base, is_boolean_t>
{
template<typename T>
vendor::logical_and_t<Base, typename _operand_t<T>::type> operator and(T t) const
vendor::logical_and_t<Base, vendor::wrap_operand_t<T>> operator and(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::logical_or_t<Base, typename _operand_t<T>::type> operator or(T t) const
vendor::logical_or_t<Base, vendor::wrap_operand_t<T>> operator or(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
}
vendor::logical_not_t<Base> operator not() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be as operand for operator not");
return { *static_cast<const Base*>(this) };
}
};
template<typename Base>
struct column_operators
{
};
};
inline std::ostream& operator<<(std::ostream& os, const boolean::_result_entry_t& e)
template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const boolean::_result_entry_t<Db, TrivialIsNull>& e)
{
return os << e.value();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -35,17 +35,20 @@
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/assignment.h>
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/vendor/wrong.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
template<typename Table, typename ColumnSpec>
struct column_t: public ColumnSpec::_value_type::template 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>>
{
using _is_column = std::true_type;
using _spec_t = ColumnSpec;
using _table = Table;
using _table_set = detail::type_set<_table>;
using _column_type = typename ColumnSpec::_column_type;
struct _value_type: ColumnSpec::_value_type
{
@ -53,6 +56,8 @@ namespace sqlpp
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;
@ -75,10 +80,11 @@ namespace sqlpp
}
template<typename T>
auto operator =(T t) const
-> typename std::enable_if<_value_type::template _constraint<typename vendor::wrap_operand<T>::type>::value and not std::is_same<column_t, T>::value,
vendor::assignment_t<column_t, typename vendor::wrap_operand<T>::type>>::type
auto operator =(T t) const -> vendor::assignment_t<column_t, typename vendor::wrap_operand<T>::type>
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand assignment operand");
return { *this, {t} };
}
@ -99,7 +105,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename... Args>
struct interpreter_t<Context, column_t<Args...>>
struct serializer_t<Context, column_t<Args...>>
{
using T = column_t<Args...>;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -35,16 +35,18 @@ namespace sqlpp
namespace vendor
{
template<typename Flag, typename Expr>
struct count_t: public sqlpp::detail::integral::template operators<count_t<Flag, Expr>>
struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, 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_value_t<Expr>::value, "count() requires a sql value 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
{
static constexpr const char* _get_name() { return "COUNT"; }
@ -74,7 +76,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Flag, typename Expr>
struct interpreter_t<Context, vendor::count_t<Flag, Expr>>
struct serializer_t<Context, vendor::count_t<Flag, Expr>>
{
using T = vendor::count_t<Flag, Expr>;
@ -83,10 +85,10 @@ namespace sqlpp
context << "COUNT(";
if (std::is_same<sqlpp::distinct_t, Flag>::value)
{
interpret(Flag(), context);
serialize(Flag(), context);
context << ' ';
}
interpret(t._expr, context);
serialize(t._expr, context);
context << ")";
return context;
}
@ -94,14 +96,16 @@ namespace sqlpp
}
template<typename T>
auto count(T t) -> typename vendor::count_t<vendor::noop, typename operand_t<T, is_value_t>::type>
auto count(T t) -> typename vendor::count_t<vendor::noop, vendor::wrap_operand_t<T>>
{
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "count() requires an expression as argument");
return { t };
}
template<typename T>
auto count(const sqlpp::distinct_t&, T t) -> typename vendor::count_t<sqlpp::distinct_t, typename operand_t<T, is_value_t>::type>
auto count(const sqlpp::distinct_t&, T t) -> typename vendor::count_t<sqlpp::distinct_t, vendor::wrap_operand_t<T>>
{
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "count() requires an expression as argument");
return { t };
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -35,6 +35,7 @@ namespace sqlpp
{
static constexpr bool _is_expression = true;
using _value_type = no_value_t;
using _table_set = ::sqlpp::detail::type_set<>;
static constexpr bool _is_trivial() { return false; }
};
@ -42,7 +43,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context>
struct interpreter_t<Context, default_value_t>
struct serializer_t<Context, default_value_t>
{
using Operand = default_value_t;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -24,41 +24,26 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_DETAIL_MAKE_EXPRESSION_TUPLE_H
#define SQLPP_DETAIL_MAKE_EXPRESSION_TUPLE_H
#ifndef SQLPP_DETAIL_ARG_SELECTOR_H
#define SQLPP_DETAIL_ARG_SELECTOR_H
namespace sqlpp
{
namespace detail
{
template<typename Expr>
auto make_single_expression_tuple(Expr expr)
-> typename std::enable_if<is_named_expression_t<Expr>::value, decltype(std::make_tuple(expr))>::type
template<typename Target>
struct arg_selector
{
return std::make_tuple(expr);
};
static Target _(Target, Target t) { return t; }
template<typename Expr>
auto make_single_expression_tuple(Expr expr)
-> typename std::enable_if<is_select_flag_t<Expr>::value, std::tuple<>>::type
{
return {};
};
template<typename X>
static Target _(X, Target t) { return t; }
template<typename... Expr>
auto make_single_expression_tuple(std::tuple<Expr...> t)
-> std::tuple<Expr...>
{
return t;
template<typename X>
static Target _(Target t, X) { return t; }
};
template<typename... Expr>
auto make_expression_tuple(Expr... expr)
-> decltype(std::tuple_cat(make_single_expression_tuple(expr)...))
{
return std::tuple_cat(make_single_expression_tuple(expr)...);
};
}
}
#endif

View File

@ -0,0 +1,76 @@
/*
* 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_COPY_TUPLE_ARGS_H
#define SQLPP_DETAIL_COPY_TUPLE_ARGS_H
#include <tuple>
namespace sqlpp
{
template<typename Table>
struct all_of_t;
namespace detail
{
template<typename T>
struct as_tuple
{
static std::tuple<T> _(T t) { return std::tuple<T>{ t }; }
};
template<typename T>
struct as_tuple<::sqlpp::all_of_t<T>>
{
static typename ::sqlpp::all_of_t<T>::_column_tuple_t _(::sqlpp::all_of_t<T>) { return { }; }
};
template<typename... Args>
struct as_tuple<std::tuple<Args...>>
{
static std::tuple<Args...> _(std::tuple<Args...> t) { return t; }
};
template<template<typename, typename...> class Target, typename First, typename T>
struct copy_tuple_args_impl
{
static_assert(vendor::wrong_t<T>::value, "copy_tuple_args must be called with a tuple");
};
template<template<typename First, typename...> class Target, typename First, typename... Args>
struct copy_tuple_args_impl<Target, First, std::tuple<Args...>>
{
using type = Target<First, Args...>;
};
template<template<typename First, typename...> class Target, typename First, typename T>
using copy_tuple_args_t = typename copy_tuple_args_impl<Target, First, T>::type;
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -34,53 +34,75 @@ namespace sqlpp
namespace detail
{
template<bool... b>
struct and_impl;
struct all_impl;
template<>
struct and_impl<>
struct all_impl<>
{
static constexpr bool value = true;
using type = std::true_type;
};
template<bool... Rest>
struct and_impl<true, Rest...>
struct all_impl<true, Rest...>
{
static constexpr bool value = and_impl<Rest...>::value;
using type = typename all_impl<Rest...>::type;
};
template<bool... Rest>
struct and_impl<false, Rest...>
struct all_impl<false, Rest...>
{
static constexpr bool value = false;
using type = std::false_type;
};
template<template<typename> class Predicate, typename... T>
using and_t = and_impl<Predicate<T>::value...>;
using all_t = typename all_impl<Predicate<T>::value...>::type;
template<bool... b>
struct or_impl;
struct any_impl;
template<>
struct or_impl<>
struct any_impl<>
{
static constexpr bool value = false;
using type = std::false_type;
};
template<bool... Rest>
struct or_impl<false, Rest...>
struct any_impl<false, Rest...>
{
static constexpr bool value = or_impl<Rest...>::value;
using type = typename any_impl<Rest...>::type;
};
template<bool... Rest>
struct or_impl<true, Rest...>
struct any_impl<true, Rest...>
{
static constexpr bool value = true;
using type = std::true_type;
};
template<template<typename> class Predicate, typename... T>
using or_t = or_impl<Predicate<T>::value...>;
using any_t = typename any_impl<Predicate<T>::value...>::type;
template<bool>
struct not_impl;
template<>
struct not_impl<true>
{
using type = std::false_type;
};
template<>
struct not_impl<false>
{
using type = std::true_type;
};
template<template<typename> class Predicate, typename... T>
using not_t = typename not_impl<Predicate<T>::value...>::type;
template<typename T>
using identity_t = T;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,6 +27,7 @@
#ifndef SQLPP_DETAIL_TYPE_SET_H
#define SQLPP_DETAIL_TYPE_SET_H
#include <tuple>
#include <type_traits>
#include <sqlpp11/vendor/wrong.h>
#include <sqlpp11/detail/logic.h>
@ -37,120 +38,181 @@ namespace sqlpp
{
// some forward declarations and helpers
template<typename... T>
struct make_set;
struct make_type_set;
template<typename T>
class type_set_element {};
template<typename E, typename SET>
struct is_element_of;
// A type set
template<typename... Element>
struct type_set: type_set_element<Element>...
template<typename... Elements>
struct type_set
{
using size = std::integral_constant<size_t, sizeof...(Element)>;
using size = std::integral_constant<size_t, sizeof...(Elements)>;
using _is_type_set = std::true_type;
static_assert(std::is_same<type_set, typename make_type_set<Elements...>::type>::value, "use make_type_set to construct a set");
template<typename T>
using count = std::is_base_of<type_set_element<T>, type_set>;
template<typename T>
struct is_superset_of
{
static_assert(::sqlpp::vendor::wrong_t<T>::value, "invalid argument for is_superset_of");
};
template<typename... T>
struct is_superset_of<type_set<T...>>
: and_t<count, T...> {};
template<typename T>
struct join
{
static_assert(::sqlpp::vendor::wrong_t<T>::value, "invalid argument for type_set::join");
};
template<typename... T>
struct join<type_set<T...>>
: make_set<Element..., T...> {};
template<typename T>
struct is_subset_of
{
static_assert(::sqlpp::vendor::wrong_t<T>::value, "invalid argument for is_subset_of");
};
template<typename... T>
struct is_subset_of<type_set<T...>>
: type_set<T...>::template is_superset_of<type_set>{};
template<typename T>
struct is_disjunct_from
{
static_assert(::sqlpp::vendor::wrong_t<T>::value, "invalid argument for is_disjunct_from");
};
template<typename... T>
struct is_disjunct_from<type_set<T...>>
{
static constexpr bool value = not(or_t<type_set::count, T...>::value or or_t<type_set<T...>::template count, Element...>::value);
};
template<typename T, typename Enable = void>
struct insert
{
using type = type_set;
};
template<typename T>
struct insert<T, typename std::enable_if<not type_set::template count<T>::value>::type>
{
using type = type_set<Element..., T>;
using type = typename std::conditional<not is_element_of<T, type_set>::value,
type_set<T, Elements...>,
type_set>::type;
};
template<template<typename A> class Predicate, typename T>
struct insert_if
{
using type = typename std::conditional<Predicate<T>::value,
type_set<Element..., T>,
using type = typename std::conditional<Predicate<T>::value and not is_element_of<T, type_set>::value,
type_set<Elements..., T>,
type_set>::type;
};
};
template<typename E, typename SET>
struct is_element_of
{
static_assert(::sqlpp::vendor::wrong_t<E, SET>::value, "SET has to be a type set");
};
template<typename E, typename... Elements>
struct is_element_of<E, type_set<Elements...>>
{
template<typename X>
using matchE = std::is_same<E, X>;
static constexpr bool value = any_t<matchE, Elements...>::value;
};
template<typename L, typename R>
struct is_superset_of
{
static_assert(::sqlpp::vendor::wrong_t<L, R>::value, "L and R have to be type sets");
};
template<typename... LElements, typename... RElements>
struct is_superset_of<type_set<LElements...>, type_set<RElements...>>
{
template<typename X>
using is_element_of_L = is_element_of<X, type_set<LElements...>>;
static constexpr bool value = all_t<is_element_of_L, RElements...>::value;
};
template<typename L, typename R>
struct is_subset_of
{
static constexpr bool value = is_superset_of<R, L>::value;
};
template<typename L, typename R>
struct joined_set
{
static_assert(::sqlpp::vendor::wrong_t<L, R>::value, "L and R have to be type sets");
};
template<typename... LElements, typename... RElements>
struct joined_set<type_set<LElements...>, type_set<RElements...>>
{
using type = typename make_type_set<LElements..., RElements...>::type;
};
template<typename L, typename R>
struct is_disjunct_from
{
static_assert(::sqlpp::vendor::wrong_t<L, R>::value, "invalid argument for is_disjunct_from");
};
template<typename... LElements, typename... RElements>
struct is_disjunct_from<type_set<LElements...>, type_set<RElements...>>
{
template<typename X>
using is_element_of_L = is_element_of<X, type_set<LElements...>>;
template<typename X>
using is_element_of_R = is_element_of<X, type_set<RElements...>>;
static constexpr bool value =
not(any_t<is_element_of_L, RElements...>::value or any_t<is_element_of_R, LElements...>::value);
};
template<>
struct make_set<>
struct make_type_set<>
{
using type = type_set<>;
};
template<typename T, typename... Rest>
struct make_set<T, Rest...>
struct make_type_set<T, Rest...>
{
using type = typename make_set<Rest...>::type::template insert<T>::type;
using type = typename make_type_set<Rest...>::type::template insert<T>::type;
};
template<typename... T>
using make_type_set_t = typename make_type_set<T...>::type;
template<template<typename> class Predicate, typename... T>
struct make_set_if;
struct make_type_set_if;
template<template<typename> class Predicate>
struct make_set_if<Predicate>
struct make_type_set_if<Predicate>
{
using type = type_set<>;
};
template<template<typename> class Predicate, typename T, typename... Rest>
struct make_set_if<Predicate, T, Rest...>
struct make_type_set_if<Predicate, T, Rest...>
{
using type = typename make_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>
struct make_set_if_not
struct make_type_set_if_not
{
template<typename X>
using InversePredicate = std::integral_constant<bool, not Predicate<X>::value>;
using type = typename make_set_if<InversePredicate, T...>::type;
using type = typename make_type_set_if<InversePredicate, T...>::type;
};
template<typename... T>
using has_duplicates = std::integral_constant<bool, make_set<T...>::type::size::value != sizeof...(T)>;
using has_duplicates = std::integral_constant<bool, make_type_set<T...>::type::size::value != sizeof...(T)>;
template<typename... T>
struct make_joined_set
{
static_assert(::sqlpp::vendor::wrong_t<T...>::value, "invalid argument for joined set");
};
template<>
struct make_joined_set<>
{
using type = type_set<>;
};
template<typename... E, typename... T>
struct make_joined_set<type_set<E...>, T...>
{
using _rest = typename make_joined_set<T...>::type;
using type = typename joined_set<type_set<E...>, _rest>::type;
};
template<typename... Sets>
using make_joined_set_t = typename make_joined_set<Sets...>::type;
template<typename Minuend, typename Subtrahend>
struct make_difference_set
{
static_assert(::sqlpp::vendor::wrong_t<Minuend, Subtrahend>::value, "invalid argument for difference set");
};
template<typename... Minuends, typename... Subtrahends>
struct make_difference_set<type_set<Minuends...>, type_set<Subtrahends...>>
{
template<typename E>
using is_subtrahend = is_element_of<E, type_set<Subtrahends...>>;
using type = typename make_type_set_if_not<is_subtrahend, Minuends...>::type;
};
template<typename Minuend, typename Subtrahend>
using make_difference_set_t = typename make_difference_set<Minuend, Subtrahend>::type;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -34,7 +34,7 @@ namespace sqlpp
namespace vendor
{
template<typename Select>
struct exists_t: public boolean::template operators<exists_t<Select>>
struct exists_t: public boolean::template expression_operators<exists_t<Select>>
{
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");
@ -43,6 +43,8 @@ namespace sqlpp
using _is_named_expression = std::true_type;
};
using _table_set = typename Select::_table_set;
struct _name_t
{
static constexpr const char* _get_name() { return "EXISTS"; }
@ -72,14 +74,14 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Select>
struct interpreter_t<Context, vendor::exists_t<Select>>
struct serializer_t<Context, vendor::exists_t<Select>>
{
using T = vendor::exists_t<Select>;
static Context& _(const T& t, Context& context)
{
context << "EXISTS(";
interpret(t._select, context);
serialize(t._select, context);
context << ")";
return context;
}
@ -88,8 +90,9 @@ namespace sqlpp
template<typename T>
auto exists(T t) -> typename vendor::exists_t<typename operand_t<T, is_select_t>::type>
auto exists(T t) -> typename vendor::exists_t<vendor::wrap_operand_t<T>>
{
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "exists() requires a select expression as argument");
return { t };
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,7 +28,8 @@
#define SQLPP_FLOATING_POINT_H
#include <cstdlib>
#include <sqlpp11/basic_operators.h>
#include <cassert>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
@ -40,6 +41,7 @@ namespace sqlpp
// floating_point value type
struct floating_point
{
using _value_type = floating_point;
using _base_value_type = floating_point;
using _is_numeric = std::true_type;
using _is_floating_point = std::true_type;
@ -98,6 +100,7 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
using _value_type = integral;
@ -135,15 +138,28 @@ namespace sqlpp
bool is_null() const
{
if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _is_null;
}
_cpp_value_type value() const
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
const bool null_value = _is_null and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value;
if (connector_assert_result_validity_t<Db>::value)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field");
}
return _value;
}
@ -162,82 +178,105 @@ namespace sqlpp
};
template<typename T>
using _operand_t = operand_t<T, is_numeric_t>;
template<typename T>
using _constraint = is_numeric_t<T>;
struct _is_valid_operand
{
static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_numeric_t<T>::value // the correct value type is required, of course
;
};
template<typename Base>
struct operators: public basic_operators<Base, _operand_t>
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
{
template<typename T>
vendor::plus_t<Base, floating_point, typename _operand_t<T>::type> operator +(T t) const
vendor::plus_t<Base, floating_point, vendor::wrap_operand_t<T>> operator +(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::minus_t<Base, floating_point, typename _operand_t<T>::type> operator -(T t) const
vendor::minus_t<Base, floating_point, vendor::wrap_operand_t<T>> operator -(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::multiplies_t<Base, floating_point, typename _operand_t<T>::type> operator *(T t) const
vendor::multiplies_t<Base, floating_point, vendor::wrap_operand_t<T>> operator *(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
using rhs = vendor::wrap_operand_t<T>;
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
vendor::divides_t<Base, typename _operand_t<T>::type> operator /(T t) const
vendor::divides_t<Base, vendor::wrap_operand_t<T>> operator /(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {t} };
using rhs = vendor::wrap_operand_t<T>;
return { *static_cast<const Base*>(this), rhs{t} };
}
vendor::unary_plus_t<floating_point, Base> operator +() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) };
}
vendor::unary_minus_t<floating_point, Base> operator -() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) };
}
};
template<typename Base>
struct column_operators
{
template<typename T>
auto operator +=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() + t)
auto operator +=(T t) const -> vendor::assignment_t<Base, vendor::plus_t<Base, floating_point, vendor::wrap_operand_t<T>>>
{
return *static_cast<const Base*>(this) = operator +(t);
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
template<typename T>
auto operator -=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() - t)
auto operator -=(T t) const -> vendor::assignment_t<Base, vendor::minus_t<Base, floating_point, vendor::wrap_operand_t<T>>>
{
return *static_cast<const Base*>(this) = operator -(t);
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
template<typename T>
auto operator /=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() / t)
auto operator /=(T t) const -> vendor::assignment_t<Base, vendor::divides_t<Base, vendor::wrap_operand_t<T>>>
{
return *static_cast<const Base*>(this) = operator /(t);
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
template<typename T>
auto operator *=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() * t)
auto operator *=(T t) const -> vendor::assignment_t<Base, vendor::multiplies_t<Base, floating_point, vendor::wrap_operand_t<T>>>
{
return *static_cast<const Base*>(this) = operator *(t);
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
};
};
inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_entry_t& e)
template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_entry_t<Db, TrivialIsNull>& e)
{
return os << e.value();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -32,6 +32,7 @@
#include <sqlpp11/column_types.h>
#include <sqlpp11/vendor/in.h>
#include <sqlpp11/vendor/is_null.h>
#include <sqlpp11/vendor/value_type.h>
#include <sqlpp11/exists.h>
#include <sqlpp11/any.h>
#include <sqlpp11/some.h>
@ -45,16 +46,18 @@
namespace sqlpp
{
template<typename T>
auto value(T t) -> typename operand_t<T, is_value_t>::type
auto value(T t) -> vendor::wrap_operand_t<T>
{
using _table_set = ::sqlpp::detail::type_set<>;
static_assert(not is_value_t<T>::value, "value() is to be called with non-sql-type like int, or string");
return { t };
}
template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim
struct verbatim_t: public ValueType::template operators<verbatim_t<ValueType>>
struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>
{
using _value_type = ValueType;
using _table_set = ::sqlpp::detail::type_set<>;
verbatim_t(std::string verbatim): _verbatim(verbatim) {}
verbatim_t(const verbatim_t&) = default;
@ -69,7 +72,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename ValueType>
struct interpreter_t<Context, verbatim_t<ValueType>>
struct serializer_t<Context, verbatim_t<ValueType>>
{
using T = verbatim_t<ValueType>;
@ -92,7 +95,7 @@ namespace sqlpp
{
static_assert(not make_parameter_list_t<Expression>::type::size::value, "parameters not supported in flattened expressions");
context.clear();
interpret(exp, context);
serialize(exp, context);
return { context.str() };
}
@ -100,7 +103,8 @@ namespace sqlpp
struct value_list_t // to be used in .in() method
{
using _container_t = Container;
using _value_type = typename operand_t<typename _container_t::value_type, is_value_t>::type::_value_type;
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):
_container(container)
@ -118,7 +122,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Container>
struct interpreter_t<Context, value_list_t<Container>>
struct serializer_t<Context, value_list_t<Container>>
{
using T = value_list_t<Container>;
@ -132,7 +136,7 @@ namespace sqlpp
else
context << ',';
interpret(value(entry), context);
serialize(value(entry), context);
}
return context;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -31,115 +31,91 @@
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_insert.h>
#include <sqlpp11/default_value.h>
#include <sqlpp11/vendor/column_list.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/insert_list.h>
#include <sqlpp11/vendor/assignment.h>
#include <sqlpp11/vendor/single_table.h>
#include <sqlpp11/vendor/insert_value_list.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/arg_selector.h>
namespace sqlpp
{
template<typename Db,
typename... Policies
>
struct insert_t;
template<
typename Database = void,
typename Table = vendor::noop,
typename InsertList = vendor::noop,
typename ColumnList = vendor::noop,
typename ValueList = vendor::insert_value_list_t<vendor::noop>
>
struct insert_t
namespace detail
{
template<typename Db,
typename Table = vendor::no_single_table_t,
typename InsertValueList = vendor::no_insert_value_list_t
>
struct insert_policies_t
{
using _database_t = Db;
using _table_t = Table;
using _insert_value_list_t = InsertValueList;
using _statement_t = insert_t<Db, Table, InsertValueList>;
struct _methods_t:
public _insert_value_list_t::template _methods_t<insert_policies_t>
{};
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_insert_t
{
using type = insert_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_insert_t<Needle, Replacement, Table, InsertValueList>::type;
using _table_set = typename _table_t::_table_set;
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
};
}
// INSERT
template<typename Db,
typename... Policies
>
struct insert_t:
public detail::insert_policies_t<Db, Policies...>::_methods_t
{
static_assert(vendor::is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument");
static_assert(vendor::is_noop<InsertList>::value or is_insert_list_t<InsertList>::value, "invalid 'InsertList' argument");
static_assert(vendor::is_noop<ColumnList>::value or is_column_list_t<ColumnList>::value, "invalid 'ColumnList' argument");
static_assert(vendor::is_noop<ValueList>::value or is_insert_value_list_t<ValueList>::value, "invalid 'ValueList' argument");
using _policies_t = typename detail::insert_policies_t<Db, Policies...>;
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 use_default_values_t = insert_t<Database, Table, vendor::insert_default_values_t>;
template<typename AssignmentT>
using set_insert_list_t = insert_t<Database, Table, AssignmentT>;
template<typename ColumnT, typename ValueT>
using set_column_value_list_t = insert_t<Database, Table, InsertList, ColumnT, ValueT>;
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<Table, InsertList>;
using _parameter_tuple_t = std::tuple<Policies...>;
using _parameter_list_t = typename make_parameter_list_t<insert_t>::type;
auto default_values()
-> use_default_values_t
{
static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call default_values() after set() or default_values()");
static_assert(vendor::is_noop<ColumnList>::value, "cannot call default_values() after columns()");
static_assert(Table::_required_insert_columns::size::value == 0, "cannot use default_values, because some columns are configured to require values");
return {
_table,
{},
_column_list,
_value_list,
};
}
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");
template<typename... Assignment>
auto set(Assignment... assignment)
-> set_insert_list_t<vendor::insert_list_t<void, Assignment...>>
{
static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call set() after set() or default_values()");
static_assert(vendor::is_noop<ColumnList>::value, "cannot call set() after columns()");
// FIXME: Need to check if all required columns are set
return {
_table,
vendor::insert_list_t<void, Assignment...>{assignment...},
_column_list,
_value_list,
};
}
// Constructors
insert_t()
{}
template<typename... Assignment>
auto dynamic_set(Assignment... assignment)
-> set_insert_list_t<vendor::insert_list_t<Database, Assignment...>>
{
static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call set() after set() or default_values()");
static_assert(vendor::is_noop<ColumnList>::value, "cannot call set() after columns()");
return {
_table,
vendor::insert_list_t<Database, Assignment...>{assignment...},
_column_list,
_value_list,
};
}
template<typename Statement, typename T>
insert_t(Statement s, T t):
_table(detail::arg_selector<_table_t>::_(s._table, t)),
_insert_value_list(detail::arg_selector<_insert_value_list_t>::_(s._insert_value_list, t))
{}
template<typename Assignment>
insert_t add_set(Assignment assignment)
{
static_assert(is_dynamic_t<InsertList>::value, "cannot call add_set() in a non-dynamic set");
_insert_list.add(assignment);
return *this;
}
template<typename... Column>
auto columns(Column... columns)
-> set_column_value_list_t<vendor::column_list_t<Column...>, vendor::insert_value_list_t<vendor::insert_value_t<Column>...>>
{
static_assert(vendor::is_noop<ColumnList>::value, "cannot call columns() twice");
static_assert(vendor::is_noop<InsertList>::value, "cannot call columns() after set() or dynamic_set()");
// FIXME: Need to check if all required columns are set
return {
_table,
_insert_list,
{std::tuple<vendor::simple_column_t<Column>...>{{columns}...}},
vendor::insert_value_list_t<vendor::insert_value_t<Column>...>{},
};
}
template<typename... Value>
insert_t& add_values(Value... values)
{
static_assert(is_insert_value_list_t<ValueList>::value, "cannot call add_values() before columns()");
_value_list.add(typename ValueList::_value_tuple_t{values...});
return *this;
};
insert_t(const insert_t&) = default;
insert_t(insert_t&&) = default;
insert_t& operator=(const insert_t&) = default;
insert_t& operator=(insert_t&&) = default;
~insert_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
@ -150,72 +126,71 @@ namespace sqlpp
return _parameter_list_t::size::value;
}
template<typename Db>
std::size_t _run(Db& db) const
template<typename A>
struct is_table_subset_of_table
{
static_assert(not (vendor::is_noop<InsertList>::value and vendor::is_noop<ColumnList>::value) , "calling set() or default_values()");
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _table_t::_table_set>::value;
};
void _check_consistency() const
{
// FIXME: Read up on what is allowed/prohibited in INSERT
}
template<typename Database>
std::size_t _run(Database& db) const
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
return db.insert(*this);
}
template<typename Db>
auto _prepare(Db& db) const
-> prepared_insert_t<Db, insert_t>
template<typename Database>
auto _prepare(Database& db) const
-> prepared_insert_t<Database, insert_t>
{
constexpr bool calledSet = not vendor::is_noop<InsertList>::value;
constexpr bool requireSet = Table::_required_insert_columns::size::value > 0;
static_assert(calledSet or not requireSet, "calling set() required for given table");
_check_consistency();
return {{}, db.prepare_insert(*this)};
}
Table _table;
InsertList _insert_list;
ColumnList _column_list;
ValueList _value_list;
_insert_value_list_t _insert_value_list;
_table_t _table;
};
namespace vendor
{
template<typename Context, typename Database, typename Table, typename InsertList, typename ColumnList, typename ValueList>
struct interpreter_t<Context, insert_t<Database, Table, InsertList, ColumnList, ValueList>>
template<typename Context, typename Database, typename... Policies>
struct serializer_t<Context, insert_t<Database, Policies...>>
{
using T = insert_t<Database, Table, InsertList, ColumnList, ValueList>;
using T = insert_t<Database, Policies...>;
static Context& _(const T& t, Context& context)
{
if (not vendor::is_noop<decltype(t._insert_list)>::value)
{
context << "INSERT INTO ";
interpret(t._table, context);
interpret(t._insert_list, context);
}
else if (not t._value_list.empty())
{
context << "INSERT INTO ";
interpret(t._table, context);
interpret(t._column_list, context);
interpret(t._value_list, context);
}
else
{
context << "# empty insert";
}
context << "INSERT INTO ";
serialize(t._table, context);
serialize(t._insert_value_list, context);
return context;
}
};
}
template<typename Database, typename... Policies>
using make_insert_t = typename detail::insert_policies_t<Database, Policies...>::_statement_t;
template<typename Table>
insert_t<void, Table> insert_into(Table table)
constexpr auto insert_into(Table table)
-> make_insert_t<void, vendor::single_table_t<void, Table>>
{
return {table};
return { make_insert_t<void>(), vendor::single_table_t<void, Table>{table} };
}
template<typename Database, typename Table>
insert_t<Database, Table> dynamic_insert_into(const Database& db, Table table)
constexpr auto dynamic_insert_into(const Database&, Table table)
-> make_insert_t<Database, vendor::single_table_t<void, Table>>
{
return {table};
return { make_insert_t<Database>(), vendor::single_table_t<void, Table>{table} };
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,7 +28,8 @@
#define SQLPP_INTEGRAL_H
#include <cstdlib>
#include <sqlpp11/basic_operators.h>
#include <cassert>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
#include <sqlpp11/vendor/value_type.h>
@ -41,6 +42,7 @@ namespace sqlpp
// integral value type
struct integral
{
using _value_type = integral;
using _base_value_type = integral;
using _is_numeric = std::true_type;
using _is_integral = std::true_type;
@ -48,6 +50,7 @@ namespace sqlpp
using _is_expression = std::true_type;
using _cpp_value_type = int64_t;
struct _parameter_t
{
using _value_type = integral;
@ -98,6 +101,7 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
using _value_type = integral;
@ -135,15 +139,28 @@ namespace sqlpp
bool is_null() const
{
if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _is_null;
}
_cpp_value_type value() const
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
const bool null_value = _is_null and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value;
if (connector_assert_result_validity_t<Db>::value)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field");
}
return _value;
}
@ -162,89 +179,116 @@ namespace sqlpp
};
template<typename T>
using _operand_t = operand_t<T, is_numeric_t>;
template<typename T>
using _constraint = is_numeric_t<T>;
struct _is_valid_operand
{
static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_numeric_t<T>::value // the correct value type is required, of course
;
};
template<typename Base>
struct operators: public basic_operators<Base, _operand_t>
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
{
template<typename T>
vendor::plus_t<Base, vendor::value_type_t<T>, typename _operand_t<T>::type> operator +(T t) const
vendor::plus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>> operator +(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::minus_t<Base, vendor::value_type_t<T>, typename _operand_t<T>::type> operator -(T t) const
vendor::minus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>> operator -(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::multiplies_t<Base, vendor::value_type_t<T>, typename _operand_t<T>::type> operator *(T t) const
vendor::multiplies_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>> operator *(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::divides_t<Base, typename _operand_t<T>::type> operator /(T t) const
vendor::divides_t<Base, vendor::wrap_operand_t<T>> operator /(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::modulus_t<Base, typename _operand_t<T>::type> operator %(T t) const
vendor::modulus_t<Base, vendor::wrap_operand_t<T>> operator %(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
vendor::unary_plus_t<integral, Base> operator +() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) };
}
vendor::unary_minus_t<integral, Base> operator -() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) };
}
};
template<typename Base>
struct column_operators
{
template<typename T>
auto operator +=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() + t)
auto operator +=(T t) const -> vendor::assignment_t<Base, vendor::plus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>>>
{
return *static_cast<const Base*>(this) = operator +(t);
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
template<typename T>
auto operator -=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() - t)
auto operator -=(T t) const -> vendor::assignment_t<Base, vendor::minus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>>>
{
return *static_cast<const Base*>(this) = operator -(t);
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
template<typename T>
auto operator /=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() / t)
auto operator /=(T t) const -> vendor::assignment_t<Base, vendor::divides_t<Base, vendor::wrap_operand_t<T>>>
{
return *static_cast<const Base*>(this) = operator /(t);
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
template<typename T>
auto operator *=(T t) const -> decltype(std::declval<Base>() = std::declval<Base>() * t)
auto operator *=(T t) const -> vendor::assignment_t<Base, vendor::multiplies_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>>>
{
return *static_cast<const Base*>(this) = operator *(t);
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
};
};
inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t& e)
template<typename Db, bool NullIsTrivial>
inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t<Db, NullIsTrivial>& e)
{
return os << e.value();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -82,11 +82,11 @@ namespace sqlpp
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(Lhs::_table_set::template is_disjunct_from<typename Rhs::_table_set>::value, "joined tables must not be identical");
static_assert(::sqlpp::detail::is_disjunct_from<typename Lhs::_table_set, typename Rhs::_table_set>::value, "joined tables must not be identical");
using _is_table = std::true_type;
using _is_join = std::true_type;
using _table_set = typename Lhs::_table_set::template join<typename Rhs::_table_set>::type;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
template<typename OnT>
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
@ -145,18 +145,18 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename JoinType, typename Lhs, typename Rhs, typename On>
struct interpreter_t<Context, join_t<JoinType, Lhs, Rhs, On>>
struct serializer_t<Context, join_t<JoinType, Lhs, Rhs, On>>
{
using T = join_t<JoinType, Lhs, Rhs, On>;
static Context& _(const T& t, Context& context)
{
static_assert(not vendor::is_noop<On>::value, "joined tables require on()");
interpret(t._lhs, context);
serialize(t._lhs, context);
context << JoinType::_name;
context << " JOIN ";
interpret(t._rhs, context);
interpret(t._on, context);
serialize(t._rhs, context);
serialize(t._on, context);
return context;
}
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,7 +27,6 @@
#ifndef SQLPP_MAX_H
#define SQLPP_MAX_H
#include <sstream>
#include <sqlpp11/type_traits.h>
namespace sqlpp
@ -35,7 +34,7 @@ namespace sqlpp
namespace vendor
{
template<typename Expr>
struct max_t: public boolean::template operators<max_t<Expr>>
struct max_t: public Expr::_value_type::template expression_operators<max_t<Expr>>
{
static_assert(is_value_t<Expr>::value, "max() requires a value expression as argument");
@ -44,6 +43,8 @@ namespace sqlpp
using _is_named_expression = std::true_type;
};
using _table_set = typename Expr::_table_set;
struct _name_t
{
static constexpr const char* _get_name() { return "MAX"; }
@ -73,14 +74,14 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Expr>
struct interpreter_t<Context, vendor::max_t<Expr>>
struct serializer_t<Context, vendor::max_t<Expr>>
{
using T = vendor::max_t<Expr>;
static Context& _(const T& t, Context& context)
{
context << "MAX(";
interpret(t._expr, context);
serialize(t._expr, context);
context << ")";
return context;
}
@ -88,8 +89,9 @@ namespace sqlpp
}
template<typename T>
auto max(T t) -> typename vendor::max_t<typename operand_t<T, is_value_t>::type>
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");
return { t };
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,7 +27,6 @@
#ifndef SQLPP_MIN_H
#define SQLPP_MIN_H
#include <sstream>
#include <sqlpp11/type_traits.h>
namespace sqlpp
@ -35,7 +34,7 @@ namespace sqlpp
namespace vendor
{
template<typename Expr>
struct min_t: public boolean::template operators<min_t<Expr>>
struct min_t: public Expr::_value_type::template expression_operators<min_t<Expr>>
{
static_assert(is_value_t<Expr>::value, "min() requires a value expression as argument");
@ -44,6 +43,8 @@ namespace sqlpp
using _is_named_expression = std::true_type;
};
using _table_set = typename Expr::_table_set;
struct _name_t
{
static constexpr const char* _get_name() { return "MIN"; }
@ -73,14 +74,14 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Expr>
struct interpreter_t<Context, vendor::min_t<Expr>>
struct serializer_t<Context, vendor::min_t<Expr>>
{
using T = vendor::min_t<Expr>;
static Context& _(const T& t, Context& context)
{
context << "MIN(";
interpret(t._expr, context);
serialize(t._expr, context);
context << ")";
return context;
}
@ -88,8 +89,9 @@ namespace sqlpp
}
template<typename T>
auto min(T t) -> typename vendor::min_t<typename operand_t<T, is_value_t>::type>
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");
return { t };
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,23 +28,75 @@
#define SQLPP_MULTI_COLUMN_H
#include <sqlpp11/no_value.h>
#include <sqlpp11/detail/make_expression_tuple.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/detail/copy_tuple_args.h>
namespace sqlpp
{
template<typename AliasProvider, typename T>
template<typename AliasProvider, typename... Columns>
struct multi_column_alias_t;
template<typename Unused, typename... Columns>
struct multi_column_t
{
static_assert(vendor::wrong_t<T>::value, "invalid argument for multicolumn_t");
static_assert(detail::all_t<is_named_expression_t, Columns...>::value, "multi_column parameters need to be named expressions");
using _table_set = sqlpp::detail::make_joined_set_t<typename Columns::_table_set...>;
multi_column_t(std::tuple<Columns...> columns):
_columns(columns)
{}
multi_column_t(Columns... columns):
_columns(columns...)
{}
multi_column_t(const multi_column_t&) = default;
multi_column_t(multi_column_t&&) = default;
multi_column_t& operator=(const multi_column_t&) = default;
multi_column_t& operator=(multi_column_t&&) = default;
~multi_column_t() = default;
template<typename AliasProvider>
multi_column_alias_t<AliasProvider, Columns...> as(const AliasProvider&)
{
return { *this };
}
using _value_type = no_value_t;
using _is_multi_column = std::true_type;
std::tuple<Columns...> _columns;
};
template<typename AliasProvider, typename... NamedExpr>
struct multi_column_t<AliasProvider, std::tuple<NamedExpr...>>
template<typename AliasProvider, typename... Columns>
struct multi_column_alias_t
{
static_assert(detail::and_t<is_named_expression_t, NamedExpr...>::value, "multi_column parameters need to be named expressions");
static_assert(detail::all_t<is_named_expression_t, Columns...>::value, "multi_column parameters need to be named expressions");
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):
_columns(multi_column._columns)
{}
multi_column_alias_t(std::tuple<Columns...> columns):
_columns(columns)
{}
multi_column_alias_t(Columns... columns):
_columns(columns...)
{}
multi_column_alias_t(const multi_column_alias_t&) = default;
multi_column_alias_t(multi_column_alias_t&&) = default;
multi_column_alias_t& operator=(const multi_column_alias_t&) = default;
multi_column_alias_t& operator=(multi_column_alias_t&&) = default;
~multi_column_alias_t() = default;
struct _value_type: public no_value_t
{
@ -52,15 +104,26 @@ namespace sqlpp
};
using _is_multi_column = std::true_type;
std::tuple<NamedExpr...> _columns;
std::tuple<Columns...> _columns;
};
namespace vendor
{
template<typename Context, typename AliasProvider, typename... NamedExpr>
struct interpreter_t<Context, multi_column_t<AliasProvider, NamedExpr...>>
template<typename Context, typename... Columns>
struct serializer_t<Context, multi_column_t<void, Columns...>>
{
using T = multi_column_t<AliasProvider, NamedExpr...>;
using T = multi_column_t<void, Columns...>;
static void _(const T& t, Context& context)
{
static_assert(wrong_t<Columns...>::value, "multi_column must be used with an alias");
}
};
template<typename Context, typename AliasProvider, typename... Columns>
struct serializer_t<Context, multi_column_alias_t<AliasProvider, Columns...>>
{
using T = multi_column_alias_t<AliasProvider, Columns...>;
static Context& _(const T& t, Context& context)
{
@ -72,17 +135,20 @@ namespace sqlpp
namespace detail
{
template<typename AliasProvider, typename... Expr>
template<typename... Columns>
using make_multi_column_t =
multi_column_t<AliasProvider, decltype(make_expression_tuple(std::declval<Expr>()...))>;
detail::copy_tuple_args_t<multi_column_t, void,
decltype(std::tuple_cat(detail::as_tuple<Columns>::_(std::declval<Columns>())...))>;
}
template<typename AliasProvider, typename... NamedExpr>
detail::make_multi_column_t<AliasProvider, NamedExpr...> multi_column(const AliasProvider& aliasProvider, NamedExpr... namedExpr)
template<typename... Columns>
auto multi_column(Columns... columns)
-> detail::make_multi_column_t<Columns...>
{
return { detail::make_expression_tuple(namedExpr...)};
return detail::make_multi_column_t<Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...));
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -36,8 +36,21 @@ namespace sqlpp
template<typename T>
using _constraint = std::false_type;
using _base_value_type = no_value_t;
template<typename T>
struct _is_valid_operand
{
static constexpr bool value = false;
};
template<typename Base>
struct operators
struct expression_operators
{
};
template<typename Base>
struct column_operators
{
};
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -35,14 +35,13 @@ namespace sqlpp
{
static constexpr bool _is_expression = true;
using _value_type = no_value_t;
static constexpr bool _is_trivial() { return false; }
using _table_set = ::sqlpp::detail::type_set<>;
};
namespace vendor
{
template<typename Context>
struct interpreter_t<Context, null_t>
struct serializer_t<Context, null_t>
{
using Operand = null_t;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -41,7 +41,7 @@ namespace sqlpp
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(detail::and_t<is_expression_t, Expr...>::value, "at least one argument is not an expression in on()");
static_assert(detail::all_t<is_expression_t, Expr...>::value, "at least one argument is not an expression in on()");
template<typename E>
void add(E expr)
@ -57,7 +57,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Database, typename... Expr>
struct interpreter_t<Context, on_t<Database, Expr...>>
struct serializer_t<Context, on_t<Database, Expr...>>
{
using T = on_t<Database, Expr...>;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,16 +28,22 @@
#define SQLPP_PARAMETER_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/alias_provider.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
template<typename ValueType, typename NameType>
struct parameter_t: public ValueType::template operators<parameter_t<ValueType, NameType>>
struct parameter_t: public ValueType::template expression_operators<parameter_t<ValueType, NameType>>
{
using _value_type = ValueType;
struct _value_type: public ValueType
{
using _is_expression = std::true_type;
using _is_alias = std::false_type;
};
using _is_parameter = std::true_type;
using _is_expression_t = std::true_type;
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>;
using _table_set = sqlpp::detail::type_set<>;
parameter_t()
{}
@ -52,7 +58,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename ValueType, typename NameType>
struct interpreter_t<Context, parameter_t<ValueType, NameType>>
struct serializer_t<Context, parameter_t<ValueType, NameType>>
{
using T = parameter_t<ValueType, NameType>;
@ -68,6 +74,7 @@ namespace sqlpp
auto parameter(const NamedExpr&)
-> parameter_t<typename NamedExpr::_value_type, NamedExpr>
{
static_assert(is_named_expression_t<NamedExpr>::value, "not a named expression");
return {};
}
@ -75,6 +82,8 @@ namespace sqlpp
auto parameter(const ValueType&, const AliasProvider&)
-> parameter_t<ValueType, AliasProvider>
{
static_assert(is_value_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");
return {};
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -32,15 +32,15 @@
namespace sqlpp
{
template<typename Db, typename Select>
template<typename Database, typename Select>
struct prepared_select_t
{
using _result_row_t = typename Select::_result_row_t;
using _result_row_t = typename Select::template _result_row_t<Database>;
using _parameter_list_t = typename Select::_parameter_list_t;
using _dynamic_names_t = typename Select::_dynamic_names_t;
using _prepared_statement_t = typename Db::_prepared_statement_t;
using _prepared_statement_t = typename Database::_prepared_statement_t;
auto _run(Db& db) const
auto _run(Database& db) const
-> result_t<decltype(db.run_prepared_select(*this)), _result_row_t>
{
return {db.run_prepared_select(*this), _dynamic_names};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -31,108 +31,97 @@
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_remove.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/single_table.h>
#include <sqlpp11/vendor/extra_tables.h>
#include <sqlpp11/vendor/using.h>
#include <sqlpp11/vendor/where.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/arg_selector.h>
namespace sqlpp
{
template<
typename Database,
typename Table,
typename Using = vendor::noop,
typename Where = vendor::noop
>
struct remove_t;
template<typename Db,
typename... Policies
>
struct remove_t;
template<
typename Database,
typename Table,
typename Using,
typename Where
>
struct remove_t
namespace detail
{
template<typename Db = void,
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
{
using _database_t = Db;
using _table_t = Table;
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 _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>
struct _policies_update_t
{
using type = remove_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement, Table, Using, ExtraTables, Where>::type;
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set, typename _using_t::_table_set, typename _extra_tables_t::_table_set>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
};
}
// REMOVE
template<typename Db,
typename... Policies
>
struct remove_t:
public detail::remove_policies_t<Db, Policies...>::_methods_t
{
static_assert(vendor::is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument");
static_assert(vendor::is_noop<Using>::value or is_using_t<Using>::value, "invalid 'Using' argument");
static_assert(vendor::is_noop<Where>::value or is_where_t<Where>::value, "invalid 'Where' argument");
using _policies_t = typename detail::remove_policies_t<Db, Policies...>;
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;
template<typename UsingT>
using set_using_t = remove_t<Database, Table, UsingT, Where>;
template<typename WhereT>
using set_where_t = remove_t<Database, Table, Using, WhereT>;
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<Table, Using, Where>;
using _parameter_tuple_t = std::tuple<Policies...>;
using _parameter_list_t = typename make_parameter_list_t<remove_t>::type;
template<typename... Tab>
auto using_(Tab... tab)
-> set_using_t<vendor::using_t<void, Tab...>>
{
static_assert(vendor::is_noop<Using>::value, "cannot call using() twice");
static_assert(vendor::is_noop<Where>::value, "cannot call using() after where()");
return {
_table,
{std::tuple<Tab...>{tab...}},
_where
};
}
// Constructors
remove_t()
{}
template<typename... Tab>
auto dynamic_using_(Tab... tab)
-> set_using_t<vendor::using_t<Database, Tab...>>
{
static_assert(vendor::is_noop<Using>::value, "cannot call using() twice");
static_assert(vendor::is_noop<Where>::value, "cannot call using() after where()");
return {
_table,
{std::tuple<Tab...>{tab...}},
_where
};
}
template<typename Statement, typename T>
remove_t(Statement s, T t):
_table(detail::arg_selector<_table_t>::_(s._table, t)),
_using(detail::arg_selector<_using_t>::_(s._using, t)),
_where(detail::arg_selector<_where_t>::_(s._where, t))
{}
template<typename Tab>
remove_t& add_using_(Tab table)
{
static_assert(is_dynamic_t<Using>::value, "cannot call add_using() in a non-dynamic using");
_using.add(table);
return *this;
}
template<typename... Expr>
auto where(Expr... expr)
-> set_where_t<vendor::where_t<void, Expr...>>
{
static_assert(vendor::is_noop<Where>::value, "cannot call where() twice");
return {
_table,
_using,
{std::tuple<Expr...>{expr...}},
};
}
template<typename... Expr>
auto dynamic_where(Expr... expr)
-> set_where_t<vendor::where_t<Database, Expr...>>
{
static_assert(vendor::is_noop<Where>::value, "cannot call where() twice");
return {
_table,
_using,
{std::tuple<Expr...>{expr...}},
};
}
template<typename Expr>
remove_t& add_where(Expr expr)
{
static_assert(is_dynamic_t<Where>::value, "cannot call add_where() in a non-dynamic where");
_where.add(expr);
return *this;
}
remove_t(const remove_t&) = default;
remove_t(remove_t&&) = default;
remove_t& operator=(const remove_t&) = default;
remove_t& operator=(remove_t&&) = default;
~remove_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
@ -143,54 +132,76 @@ namespace sqlpp
return _parameter_list_t::size::value;
}
template<typename Db>
std::size_t _run(Db& db) const
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
{
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
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
}
template<typename Database>
std::size_t _run(Database& db) const
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead");
static_assert(is_where_t<Where>::value, "cannot run update without having a where condition, use .where(true) to remove all rows");
return db.remove(*this);
}
template<typename Db>
auto _prepare(Db& db) const
-> prepared_remove_t<Db, remove_t>
template<typename Database>
auto _prepare(Database& db) const
-> prepared_remove_t<Database, remove_t>
{
_check_consistency();
return {{}, db.prepare_remove(*this)};
}
Table _table;
Using _using;
Where _where;
_table_t _table;
_using_t _using;
_where_t _where;
};
namespace vendor
{
template<typename Context, typename Database, typename Table, typename Using, typename Where>
struct interpreter_t<Context, remove_t<Database, Table, Using, Where>>
template<typename Context, typename Database, typename... Policies>
struct serializer_t<Context, remove_t<Database, Policies...>>
{
using T = remove_t<Database, Table, Using, Where>;
using T = remove_t<Database, Policies...>;
static Context& _(const T& t, Context& context)
{
context << "DELETE FROM ";
interpret(t._table, context);
interpret(t._using, context);
interpret(t._where, context);
serialize(t._table, context);
serialize(t._using, context);
serialize(t._where, context);
return context;
}
};
}
template<typename Database, typename... Policies>
using make_remove_t = typename detail::remove_policies_t<Database, Policies...>::_statement_t;
template<typename Table>
constexpr remove_t<void, Table> remove_from(Table table)
constexpr auto remove_from(Table table)
-> make_remove_t<void, vendor::single_table_t<void, Table>>
{
return {table};
return { make_remove_t<void>(), vendor::single_table_t<void, Table>{table} };
}
template<typename Db, typename Table>
constexpr remove_t<Db, Table> dynamic_remove_from(const Db&, Table table)
template<typename Database, typename Table>
constexpr auto dynamic_remove_from(const Database&, Table table)
-> make_remove_t<Database, vendor::single_table_t<void, Table>>
{
return {table};
return { make_remove_t<Database>(), vendor::single_table_t<void, Table>{table} };
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -41,13 +41,13 @@ namespace sqlpp
template<size_t level, size_t index, typename... NamedExpr>
struct result_row_impl;
template<size_t level, size_t index, typename NamedExpr, typename... Rest>
struct result_row_impl<level, index, NamedExpr, Rest...>:
public NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::_result_entry_t>,
public result_row_impl<level, index + 1, Rest...>
template<size_t level, size_t index, typename Db, typename NamedExpr, typename... Rest>
struct result_row_impl<level, index, Db, NamedExpr, Rest...>:
public NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>,
public result_row_impl<level, index + 1, Db, Rest...>
{
using _field = typename NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::_result_entry_t>;
using _rest = result_row_impl<level, index + 1, Rest...>;
using _field = typename NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>;
using _rest = result_row_impl<level, index + 1, Db, Rest...>;
static constexpr size_t _last_index = _rest::_last_index;
result_row_impl() = default;
@ -84,13 +84,13 @@ namespace sqlpp
}
};
template<size_t level, size_t index, typename AliasProvider, typename... Col, typename... Rest>
struct result_row_impl<level, index, vendor::multi_field_t<AliasProvider, std::tuple<Col...>>, Rest...>:
public AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Col...>>, // level prevents identical closures to be present twice in the inheritance tree
public result_row_impl<level, index + sizeof...(Col), Rest...>
template<size_t level, size_t index, typename AliasProvider, typename Db, typename... Col, typename... Rest>
struct result_row_impl<level, index, Db, vendor::multi_field_t<AliasProvider, std::tuple<Col...>>, Rest...>:
public AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Db, Col...>>, // level prevents identical closures to be present twice in the inheritance tree
public result_row_impl<level, index + sizeof...(Col), Db, Rest...>
{
using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Col...>>;
using _rest = result_row_impl<level, index + sizeof...(Col), Rest...>;
using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Db, Col...>>;
using _rest = result_row_impl<level, index + sizeof...(Col), Db, Rest...>;
static constexpr size_t _last_index = _rest::_last_index;
result_row_impl() = default;
@ -126,8 +126,8 @@ namespace sqlpp
}
};
template<size_t level, size_t index>
struct result_row_impl<level, index>
template<size_t level, size_t index, typename Db>
struct result_row_impl<level, index, Db>
{
static constexpr size_t _last_index = index;
result_row_impl() = default;
@ -155,10 +155,10 @@ namespace sqlpp
};
}
template<typename... NamedExpr>
struct result_row_t: public detail::result_row_impl<0, 0, NamedExpr...>
template<typename Db, typename... NamedExpr>
struct result_row_t: public detail::result_row_impl<0, 0, Db, NamedExpr...>
{
using _impl = detail::result_row_impl<0, 0, NamedExpr...>;
using _impl = detail::result_row_impl<0, 0, Db, NamedExpr...>;
bool _is_valid;
static constexpr size_t _last_static_index = _impl::_last_index;
@ -221,11 +221,11 @@ namespace sqlpp
}
};
template<typename... NamedExpr>
struct dynamic_result_row_t: public detail::result_row_impl<0, 0, NamedExpr...>
template<typename Db, typename... NamedExpr>
struct dynamic_result_row_t: public detail::result_row_impl<0, 0, Db, NamedExpr...>
{
using _impl = detail::result_row_impl<0, 0, NamedExpr...>;
using _field_type = detail::text::_result_entry_t;
using _impl = detail::result_row_impl<0, 0, Db, NamedExpr...>;
using _field_type = detail::text::_result_entry_t<Db, false>;
static constexpr size_t _last_static_index = _impl::_last_index;
bool _is_valid;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,7 +28,6 @@
#define SQLPP_SELECT_H
#include <sqlpp11/result.h>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_select.h>
@ -36,6 +35,7 @@
#include <sqlpp11/vendor/select_flag_list.h>
#include <sqlpp11/vendor/select_column_list.h>
#include <sqlpp11/vendor/from.h>
#include <sqlpp11/vendor/extra_tables.h>
#include <sqlpp11/vendor/where.h>
#include <sqlpp11/vendor/group_by.h>
#include <sqlpp11/vendor/having.h>
@ -43,559 +43,194 @@
#include <sqlpp11/vendor/limit.h>
#include <sqlpp11/vendor/offset.h>
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/vendor/wrong.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/make_flag_tuple.h>
#include <sqlpp11/detail/make_expression_tuple.h>
#include <sstream>
#include <sqlpp11/detail/arg_selector.h>
namespace sqlpp
{
template<
typename Database,
typename FlagList,
typename ColumnList,
typename From,
typename Where,
typename GroupBy,
typename Having,
typename OrderBy,
typename Limit,
typename Offset
>
struct select_t
: public ColumnList::_value_type::template operators<select_t<
Database,
FlagList,
ColumnList,
From,
Where,
GroupBy,
Having,
OrderBy,
Limit,
Offset>>
{
using _Database = Database;
using _From = From;
template<typename Db,
typename... Policies
>
struct select_t;
static_assert(is_select_flag_list_t<FlagList>::value, "invalid list of select flags");
static_assert(is_select_column_list_t<ColumnList>::value, "invalid list of select expressions");
static_assert(vendor::is_noop<From>::value or is_from_t<From>::value, "invalid 'from' argument");
static_assert(vendor::is_noop<Where>::value or is_where_t<Where>::value, "invalid 'where' argument");
static_assert(vendor::is_noop<GroupBy>::value or is_group_by_t<GroupBy>::value, "invalid 'group by' arguments");
static_assert(vendor::is_noop<Having>::value or is_having_t<Having>::value, "invalid 'having' arguments");
static_assert(vendor::is_noop<OrderBy>::value or is_order_by_t<OrderBy>::value, "invalid 'order by' arguments");
static_assert(vendor::is_noop<Limit>::value or is_limit_t<Limit>::value, "invalid 'limit' arguments");
static_assert(vendor::is_noop<Offset>::value or is_offset_t<Offset>::value, "invalid 'offset' arguments");
namespace detail
{
template<typename Db = void,
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
{
using _database_t = Db;
using _flag_list_t = FlagList;
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 _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>
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 = select_t<Db, vendor::policy_update_t<Policies, Needle, 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;
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");
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 _known_tables = detail::make_joined_set_t<typename _from_t::_table_set, typename _extra_tables_t::_table_set>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
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.
using _table_set = detail::make_difference_set_t<
_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
>;
// A select can be used as a pseudo table if
// - at least one column is selected
// - the select is complete (leaks no tables)
using _can_be_used_as_table = typename std::conditional<
is_select_column_list_t<_column_list_t>::value and _table_set::size::value == 0,
std::true_type,
std::false_type
>::type;
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,
typename ColumnList::_value_type,
no_value_t // If something is selected that requires a table, then we require a from for this to be a value
>::type;
};
}
// SELECT
template<typename Db,
typename... Policies
>
struct select_t:
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
{
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 _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<select_t>::type;
using _table_set = typename _policies_t::_table_set;
template<typename Database>
using _result_row_t = typename _column_list_t::template _result_row_t<Database>;
using _dynamic_names_t = typename _column_list_t::_dynamic_names_t;
using _is_select = std::true_type;
using _requires_braces = std::true_type;
template<typename FlagListT>
using set_flag_list_t = select_t<Database, FlagListT, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, Offset>;
template<typename ColumnListT>
using set_column_list_t = select_t<Database, FlagList, ColumnListT, From, Where, GroupBy, Having, OrderBy, Limit, Offset>;
template<typename FromT>
using set_from_t = select_t<Database, FlagList, ColumnList, FromT, Where, GroupBy, Having, OrderBy, Limit, Offset>;
template<typename WhereT>
using set_where_t = select_t<Database, FlagList, ColumnList, From, WhereT, GroupBy, Having, OrderBy, Limit, Offset>;
template<typename GroupByT>
using set_group_by_t = select_t<Database, FlagList, ColumnList, From, Where, GroupByT, Having, OrderBy, Limit, Offset>;
template<typename HavingT>
using set_having_t = select_t<Database, FlagList, ColumnList, From, Where, GroupBy, HavingT, OrderBy, Limit, Offset>;
template<typename OrderByT>
using set_order_by_t = select_t<Database, FlagList, ColumnList, From, Where, GroupBy, Having, OrderByT, Limit, Offset>;
template<typename LimitT>
using set_limit_t = select_t<Database, FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, LimitT, Offset>;
template<typename OffsetT>
using set_offset_t = select_t<Database, FlagList, ColumnList, From, Where, GroupBy, Having, OrderBy, Limit, OffsetT>;
using _value_type = typename detail::select_policies_t<Db, Policies...>::_value_type;
using _name_t = typename _column_list_t::_name_t;
using _result_row_t = typename ColumnList::_result_row_t;
using _dynamic_names_t = typename ColumnList::_dynamic_names_t;
using _parameter_tuple_t = std::tuple<ColumnList, Where, GroupBy, Having, OrderBy, Limit, Offset>;
using _parameter_list_t = typename make_parameter_list_t<select_t>::type;
// Constructors
select_t()
{}
// Indicators
using _value_type = typename std::conditional<
vendor::is_noop<From>::value,
no_value_t, // If there is no from, the select is not complete (this logic is a bit simple, but better than nothing)
typename ColumnList::_value_type>::type;
template<typename Statement, typename T>
select_t(Statement s, T t):
_flag_list(detail::arg_selector<_flag_list_t>::_(s._flag_list, t)),
_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))
{}
using _name_t = typename ColumnList::_name_t;
// The standard constructors, assigment operators and destructor
constexpr select_t(FlagList flag_list, ColumnList column_list, From from,
Where where, GroupBy group_by, Having having,
OrderBy order_by, Limit limit, Offset offset):
_flags(flag_list),
_columns(column_list),
_from(from),
_where(where),
_group_by(group_by),
_having(having),
_order_by(order_by),
_limit(limit),
_offset(offset)
{
}
select_t(const select_t& rhs) = default;
select_t(select_t&& rhs) = default;
select_t& operator=(const select_t& rhs) = default;
select_t& operator=(select_t&& rhs) = default;
select_t(const select_t& r) = default;
select_t(select_t&& r) = default;
select_t& operator=(const select_t& r) = default;
select_t& operator=(select_t&& r) = default;
~select_t() = default;
// select functions
template<typename... Flag>
auto flags(Flag... flag)
-> set_flag_list_t<vendor::select_flag_list_t<void, std::tuple<Flag...>>>
{
static_assert(not FlagList::size::value, "cannot call dynamic_flags() after specifying them the first time");
static_assert(not ColumnList::size::value, "cannot call columns() after specifying them the first time");
return {
{std::tuple<Flag...>{flag...}},
_columns,
_from,
_where,
_group_by,
_having,
_order_by,
_limit,
_offset
};
}
template<typename... Flag>
auto dynamic_flags(Flag... flag)
-> set_flag_list_t<vendor::select_flag_list_t<Database, std::tuple<Flag...>>>
{
static_assert(not std::is_same<Database, void>::value, "cannot call dynamic_flags() in a non-dynamic select");
static_assert(not FlagList::size::value, "cannot call dynamic_flags() after specifying them the first time");
static_assert(not ColumnList::size::value, "cannot call columns() after specifying them the first time");
return {
{std::tuple<Flag...>{flag...}},
_columns,
_from,
_where,
_group_by,
_having,
_order_by,
_limit,
_offset
};
}
template<typename Flag>
select_t& add_flag(Flag flag)
{
static_assert(is_dynamic_t<FlagList>::value, "cannot call add_flag() in a non-dynamic column list");
_flags.add(flag);
return *this;
}
template<typename... Column>
auto columns(Column... column)
-> set_column_list_t<vendor::select_column_list_t<void, std::tuple<Column...>>>
{
static_assert(not ColumnList::size::value, "cannot call columns() after specifying them the first time");
return {
_flags,
{std::tuple<Column...>{column...}},
_from,
_where,
_group_by,
_having,
_order_by,
_limit,
_offset
};
}
template<typename... Column>
auto dynamic_columns(Column... column)
-> set_column_list_t<vendor::select_column_list_t<Database, std::tuple<Column...>>>
{
static_assert(not std::is_same<Database, void>::value, "cannot call dynamic_columns() in a non-dynamic select");
static_assert(not ColumnList::size::value, "cannot call dynamic_columns() after specifying them the first time");
return {
_flags,
{std::tuple<Column...>{column...}},
_from,
_where,
_group_by,
_having,
_order_by,
_limit,
_offset
};
}
template<typename NamedExpr>
select_t& add_column(NamedExpr namedExpr)
{
static_assert(is_dynamic_t<ColumnList>::value, "cannot call add_column() in a non-dynamic column list");
_columns.add(namedExpr);
return *this;
}
template<typename... Table>
auto from(Table... table)
-> set_from_t<vendor::from_t<void, Table...>>
{
static_assert(not vendor::is_noop<ColumnList>::value, "cannot call from() without having selected anything");
static_assert(vendor::is_noop<From>::value, "cannot call from() twice for a single select");
return {
_flags,
_columns,
{std::tuple<Table...>{table...}},
_where,
_group_by,
_having,
_order_by,
_limit,
_offset
};
}
template<typename... Table>
auto dynamic_from(Table... table)
-> set_from_t<vendor::from_t<Database, Table...>>
{
static_assert(not std::is_same<Database, void>::value, "cannot call dynamic_from() in a non-dynamic select");
static_assert(not vendor::is_noop<ColumnList>::value, "cannot call from() without having selected anything");
static_assert(vendor::is_noop<From>::value, "cannot call from() twice for a single select");
return {
_flags,
_columns,
{std::tuple<Table...>{table...}},
_where,
_group_by,
_having,
_order_by,
_limit,
_offset
};
}
template<typename Table>
select_t& add_from(Table table)
{
static_assert(not vendor::is_noop<ColumnList>::value, "cannot call add_from() without having selected anything");
static_assert(is_dynamic_t<From>::value, "cannot call add_from() in a non-dynamic from");
_from.add(table);
return *this;
}
template<typename... Expr>
auto where(Expr... expr)
-> set_where_t<vendor::where_t<void, Expr...>>
{
static_assert(not vendor::is_noop<From>::value, "cannot call where() without a from()");
static_assert(vendor::is_noop<Where>::value, "cannot call where() or dynamic_where() twice for a single select");
return {
_flags,
_columns,
_from,
{std::tuple<Expr...>{expr...}},
_group_by,
_having,
_order_by,
_limit,
_offset,
};
}
template<typename... Expr>
auto dynamic_where(Expr... expr)
-> set_where_t<vendor::where_t<Database, Expr...>>
{
static_assert(not vendor::is_noop<From>::value, "cannot call dynamic_where() without a from()");
static_assert(vendor::is_noop<Where>::value, "cannot call where() or dynamic_where() twice for a single select");
return {
_flags,
_columns,
_from,
{std::tuple<Expr...>{expr...}},
_group_by,
_having,
_order_by,
_limit,
_offset,
};
}
template<typename Expr>
select_t& add_where(Expr expr)
{
static_assert(is_dynamic_t<Where>::value, "cannot call add_where() with a non-dynamic where");
_where.add(expr);
return *this;
}
template<typename... Col>
auto group_by(Col... column)
-> set_group_by_t<vendor::group_by_t<void, Col...>>
{
static_assert(not vendor::is_noop<From>::value, "cannot call group_by() without a from()");
static_assert(vendor::is_noop<GroupBy>::value, "cannot call group_by() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
{std::tuple<Col...>{column...}},
_having,
_order_by,
_limit,
_offset,
};
}
template<typename... Col>
auto dynamic_group_by(Col... column)
-> set_group_by_t<vendor::group_by_t<Database, Col...>>
{
static_assert(not vendor::is_noop<From>::value, "cannot call group_by() without a from()");
static_assert(vendor::is_noop<GroupBy>::value, "cannot call group_by() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
{std::tuple<Col...>{column...}},
_having,
_order_by,
_limit,
_offset,
};
}
template<typename Expr>
select_t& add_group_by(Expr expr)
{
static_assert(is_dynamic_t<GroupBy>::value, "cannot call add_group_by() in a non-dynamic group_by");
_group_by.add(expr);
return *this;
}
template<typename... Expr>
auto having(Expr... expr)
-> set_having_t<vendor::having_t<void, Expr...>>
{
static_assert(not vendor::is_noop<GroupBy>::value, "cannot call having() without a group_by");
static_assert(vendor::is_noop<Having>::value, "cannot call having() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
_group_by,
{std::tuple<Expr...>{expr...}},
_order_by,
_limit,
_offset,
};
}
template<typename... Expr>
auto dynamic_having(Expr... expr)
-> set_having_t<vendor::having_t<Database, Expr...>>
{
static_assert(not vendor::is_noop<GroupBy>::value, "cannot call having() without a group_by");
static_assert(vendor::is_noop<Having>::value, "cannot call having() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
_group_by,
{std::tuple<Expr...>{expr...}},
_order_by,
_limit,
_offset,
};
}
template<typename Expr>
select_t& add_having(Expr expr)
{
static_assert(is_dynamic_t<Having>::value, "cannot call add_having() in a non-dynamic having");
_having.add(expr);
return *this;
}
template<typename... OrderExpr>
auto order_by(OrderExpr... expr)
-> set_order_by_t<vendor::order_by_t<void, OrderExpr...>>
{
static_assert(not vendor::is_noop<From>::value, "cannot call order_by() without a from()");
static_assert(vendor::is_noop<OrderBy>::value, "cannot call order_by() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
_group_by,
_having,
{std::tuple<OrderExpr...>{expr...}},
_limit,
_offset,
};
}
template<typename... OrderExpr>
auto dynamic_order_by(OrderExpr... expr)
-> set_order_by_t<vendor::order_by_t<Database, OrderExpr...>>
{
static_assert(not vendor::is_noop<From>::value, "cannot call order_by() without a from()");
static_assert(vendor::is_noop<OrderBy>::value, "cannot call order_by() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
_group_by,
_having,
{std::tuple<OrderExpr...>{expr...}},
_limit,
_offset,
};
}
template<typename Expr>
select_t& add_order_by(Expr expr)
{
static_assert(is_dynamic_t<OrderBy>::value, "cannot call add_order_by() in a non-dynamic order_by");
_order_by.add(expr);
return *this;
}
template<typename Expr>
auto limit(Expr limit)
-> set_limit_t<vendor::limit_t<typename vendor::wrap_operand<Expr>::type>>
{
static_assert(not vendor::is_noop<From>::value, "cannot call limit() without a from()");
static_assert(vendor::is_noop<Limit>::value, "cannot call limit() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
_group_by,
_having,
_order_by,
{limit},
_offset,
};
}
auto dynamic_limit(std::size_t limit = 0)
->set_limit_t<vendor::dynamic_limit_t>
{
static_assert(not vendor::is_noop<From>::value, "cannot call limit() without a from()");
static_assert(vendor::is_noop<Limit>::value, "cannot call limit() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
_group_by,
_having,
_order_by,
{limit},
_offset,
};
}
select_t& set_limit(std::size_t limit)
{
static_assert(is_dynamic_t<Limit>::value, "cannot call set_limit() in a non-dynamic limit");
_limit.set(limit);
return *this;
}
template<typename Expr>
auto offset(Expr offset)
-> set_offset_t<vendor::offset_t<typename vendor::wrap_operand<Expr>::type>>
{
static_assert(not vendor::is_noop<Limit>::value, "cannot call offset() without a limit");
static_assert(vendor::is_noop<Offset>::value, "cannot call offset() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
_group_by,
_having,
_order_by,
_limit,
{offset},
};
}
auto dynamic_offset(std::size_t offset = 0)
-> set_offset_t<vendor::dynamic_offset_t>
{
static_assert(not vendor::is_noop<Limit>::value, "cannot call offset() without a limit");
static_assert(vendor::is_noop<Offset>::value, "cannot call offset() twice for a single select");
return {
_flags,
_columns,
_from,
_where,
_group_by,
_having,
_order_by,
_limit,
{offset},
};
}
select_t& set_offset(std::size_t offset)
{
static_assert(is_dynamic_t<Offset>::value, "cannot call set_offset() in a non-dynamic limit");
_offset.set(offset);
return *this;
}
// PseudoTable
template<typename AliasProvider>
struct _pseudo_table_t
{
using table = typename ColumnList::template _pseudo_table_t<select_t>;
using table = typename _column_list_t::template _pseudo_table_t<select_t>;
using alias = typename table::template _alias_t<AliasProvider>;
};
template<typename AliasProvider>
typename _pseudo_table_t<AliasProvider>::alias as(const AliasProvider& aliasProvider) const
{
static_assert(_policies_t::_can_be_used_as_table::value, "select cannot be used as table, incomplete from()");
return typename _pseudo_table_t<AliasProvider>::table(
*this).as(aliasProvider);
}
const typename ColumnList::_dynamic_names_t& get_dynamic_names() const
const _dynamic_names_t& get_dynamic_names() const
{
return _columns._dynamic_columns._dynamic_expression_names;
return _column_list._dynamic_columns._dynamic_expression_names;
}
static constexpr size_t _get_static_no_of_parameters()
@ -610,146 +245,114 @@ namespace sqlpp
size_t get_no_of_result_columns() const
{
return _result_row_t::static_size() + get_dynamic_names().size();
return _column_list_t::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
{
static_assert(is_select_column_list_t<_column_list_t>::value, "no columns selected");
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
template<typename Db>
auto _run(Db& db) const
-> result_t<decltype(db.select(*this)), _result_row_t>
template<typename Database>
auto _run(Database& db) const
-> result_t<decltype(db.select(*this)), _result_row_t<Database>>
{
static_assert(not vendor::is_noop<ColumnList>::value, "cannot run select without having selected anything");
static_assert(is_from_t<From>::value, "cannot run select without a from()");
static_assert(is_where_t<Where>::value, "cannot run select without having a where condition, use .where(true) to select all rows");
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
// FIXME: Check for missing aliases (if references are used)
// FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc.
return {db.select(*this), get_dynamic_names()};
}
// Prepare
template<typename Db>
auto _prepare(Db& db) const
-> prepared_select_t<Db, select_t>
template<typename Database>
auto _prepare(Database& db) const
-> prepared_select_t<Database, select_t>
{
static_assert(not vendor::is_noop<ColumnList>::value, "cannot run select without having selected anything");
static_assert(is_from_t<From>::value, "cannot run select without a from()");
// FIXME: Check for missing aliases (if references are used)
// FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc.
_check_consistency();
return {{}, get_dynamic_names(), db.prepare_select(*this)};
}
FlagList _flags;
ColumnList _columns;
From _from;
Where _where;
GroupBy _group_by;
Having _having;
OrderBy _order_by;
Limit _limit;
Offset _offset;
_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
{
template<typename Context,
typename Database,
typename FlagList,
typename ColumnList,
typename From,
typename Where,
typename GroupBy,
typename Having,
typename OrderBy,
typename Limit,
typename Offset
>
struct interpreter_t<Context, select_t<Database,
FlagList,
ColumnList,
From,
Where,
GroupBy,
Having,
OrderBy,
Limit,
Offset>>
template<typename Context, typename Database, typename... Policies>
struct serializer_t<Context, select_t<Database, Policies...>>
{
using T = select_t<Database,
FlagList,
ColumnList,
From,
Where,
GroupBy,
Having,
OrderBy,
Limit,
Offset>;
using T = select_t<Database, Policies...>;
static Context& _(const T& t, Context& context)
{
context << "SELECT ";
interpret(t._flags, context);
interpret(t._columns, context);
interpret(t._from, context);
interpret(t._where, context);
interpret(t._group_by, context);
interpret(t._having, context);
interpret(t._order_by, context);
interpret(t._limit, context);
interpret(t._offset, context);
serialize(t._flag_list, context);
serialize(t._column_list, context);
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;
}
};
}
template<typename Database, typename... Policies>
using make_select_t = typename detail::select_policies_t<Database, Policies...>::_statement_t;
// construct select flag list
namespace detail
make_select_t<void> select() // FIXME: These should be constexpr
{
template<typename Database, typename... Expr>
using make_select_flag_list_t =
vendor::select_flag_list_t<Database, decltype(make_flag_tuple(std::declval<Expr>()...))>;
return { };
}
// construct select expression list
namespace detail
{
template<typename Database, typename... Expr>
using make_select_column_list_t =
vendor::select_column_list_t<Database, decltype(make_expression_tuple(std::declval<Expr>()...))>;
}
auto select()
-> select_t<void, vendor::select_flag_list_t<void, std::tuple<>>, vendor::select_column_list_t<void, std::tuple<>>>
template<typename... Columns>
auto select(Columns... columns)
-> make_select_t<void, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>>
{
return { {}, vendor::select_column_list_t<void, std::tuple<>>{}, {}, {}, {}, {}, {}, {}, {} };
return { make_select_t<void>(), detail::make_select_column_list_t<void, Columns...>{std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)} };
}
template<typename... NamedExpr>
auto select(NamedExpr... namedExpr)
-> select_t<void, detail::make_select_flag_list_t<void, NamedExpr...>, detail::make_select_column_list_t<void, NamedExpr...>>
template<typename Database>
make_select_t<Database> dynamic_select(const Database&)
{
return {
{ detail::make_flag_tuple(namedExpr...) },
{ detail::make_expression_tuple(namedExpr...) },
{}, {}, {}, {}, {}, {}, {}
};
return { make_select_t<Database>() };
}
template<typename Db, typename... NamedExpr>
auto dynamic_select(const Db& db, NamedExpr... namedExpr)
-> select_t<Db, detail::make_select_flag_list_t<Db, NamedExpr...>, detail::make_select_column_list_t<Db, NamedExpr...>>
template<typename Database, typename... 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...>>
{
return {
{ detail::make_flag_tuple(namedExpr...) },
{ detail::make_expression_tuple(namedExpr...) },
{}, {}, {}, {}, {}, {}, {}
};
return { make_select_t<Database>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) };
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,7 +27,6 @@
#ifndef SQLPP_SELECT_FLAGS_H
#define SQLPP_SELECT_FLAGS_H
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/vendor/interpret_tuple.h>
@ -42,13 +41,14 @@ namespace sqlpp
{
using _is_select_flag = std::true_type;
};
using _table_set = detail::type_set<>;
};
static constexpr all_t all = {};
namespace vendor
{
template<typename Context>
struct interpreter_t<Context, all_t>
struct serializer_t<Context, all_t>
{
static Context& _(const all_t&, Context& context)
{
@ -64,13 +64,14 @@ namespace sqlpp
{
using _is_select_flag = std::true_type;
};
using _table_set = detail::type_set<>;
};
static constexpr distinct_t distinct = {};
namespace vendor
{
template<typename Context>
struct interpreter_t<Context, distinct_t>
struct serializer_t<Context, distinct_t>
{
static Context& _(const distinct_t&, Context& context)
{
@ -86,13 +87,14 @@ namespace sqlpp
{
using _is_select_flag = std::true_type;
};
using _table_set = detail::type_set<>;
};
static constexpr straight_join_t straight_join = {};
namespace vendor
{
template<typename Context>
struct interpreter_t<Context, straight_join_t>
struct serializer_t<Context, straight_join_t>
{
static Context& _(const straight_join_t&, Context& context)
{

View File

@ -0,0 +1,55 @@
/*
* 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_SERIALIZE_H
#define SQLPP_SERIALIZE_H
#include <sqlpp11/vendor/serializer.h>
namespace sqlpp
{
template<typename T, typename Context>
auto serialize(const T& t, Context& context)
-> decltype(vendor::serializer_t<Context, T>::_(t, context))
{
return vendor::serializer_t<Context, T>::_(t, context);
}
/*
namespace vendor // Required if you want to call serialize(sqlpp::value(7), printer), for instance
{
template<typename T, typename Context>
auto serialize(const T& t, Context& context)
-> decltype(vendor::serializer_t<Context, T>::_(t, context))
{
return vendor::serializer_t<Context, T>::_(t, context);
}
}
*/
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -23,16 +23,16 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_SERIALIZER_H
#define SQLPP_SERIALIZER_H
#ifndef SQLPP_SERIALIZER_CONTEXT_H
#define SQLPP_SERIALIZER_CONTEXT_H
#include <ostream>
namespace sqlpp
{
struct serializer_t
struct serializer_context_t
{
serializer_t(std::ostream& os):
serializer_context_t(std::ostream& os):
_os(os)
{}
@ -42,14 +42,21 @@ namespace sqlpp
return _os << t;
}
void flush()
static std::string escape(std::string arg)
{
_os << std::endl;
}
std::string escape(std::string arg)
{
return arg;
if (arg.find('\''))
{
std::string retVal;
for (const auto c : arg)
{
if (c == '\'')
retVal.push_back(c);
retVal.push_back(c);
}
return retVal;
}
else
return arg;
}
std::ostream& _os;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,22 +27,20 @@
#ifndef SQLPP_SOME_H
#define SQLPP_SOME_H
#include <sstream>
#include <sqlpp11/boolean.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
namespace vendor
{
template<typename Select>
struct some_t: public boolean::template operators<some_t<Select>>
struct some_t
{
static_assert(is_select_t<Select>::value, "some() requires a single column select expression as argument");
static_assert(is_value_t<Select>::value, "some() requires a single column select expression as argument");
struct _value_type: public Select::_value_type::_base_value_type
{
using _is_multi_expression = std::true_type; // must not be named
using _is_expression = std::false_type;
using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc
};
struct _name_t
@ -56,6 +54,7 @@ namespace sqlpp
const T& operator()() const { return some; }
};
};
using _table_set = typename Select::_table_set;
some_t(Select select):
_select(select)
@ -74,14 +73,14 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Select>
struct interpreter_t<Context, vendor::some_t<Select>>
struct serializer_t<Context, vendor::some_t<Select>>
{
using T = vendor::some_t<Select>;
static Context& _(const T& t, Context& context)
{
context << "SOME(";
interpret(t._select, context);
serialize(t._select, context);
context << ")";
return context;
}
@ -89,8 +88,10 @@ namespace sqlpp
}
template<typename T>
auto some(T t) -> typename vendor::some_t<typename operand_t<T, is_select_t>::type>
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_value_t<vendor::wrap_operand_t<T>>::value, "some() requires a single column select expression as argument");
return { t };
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,6 +27,8 @@
#ifndef SQLPP_SORT_ORDER_H
#define SQLPP_SORT_ORDER_H
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
enum class sort_type
@ -39,6 +41,7 @@ namespace sqlpp
struct sort_order_t
{
using _is_sort_order = std::true_type;
using _table_set = typename Expression::_table_set;
Expression _expression;
};
@ -46,13 +49,13 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Expression, sort_type SortType>
struct interpreter_t<Context, sort_order_t<Expression, SortType>>
struct serializer_t<Context, sort_order_t<Expression, SortType>>
{
using T = sort_order_t<Expression, SortType>;
static Context& _(const T& t, Context& context)
{
interpret(t._expression, context);
serialize(t._expression, context);
switch(SortType)
{
case sort_type::asc:

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,7 +27,6 @@
#ifndef SQLPP_SUM_H
#define SQLPP_SUM_H
#include <sstream>
#include <sqlpp11/type_traits.h>
namespace sqlpp
@ -35,7 +34,7 @@ namespace sqlpp
namespace vendor
{
template<typename Flag, typename Expr>
struct sum_t: public boolean::template operators<sum_t<Flag, Expr>>
struct sum_t: public Expr::_value_type::template expression_operators<sum_t<Flag, 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_numeric_t<Expr>::value, "sum() requires a numeric expression as argument");
@ -74,7 +73,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Flag, typename Expr>
struct interpreter_t<Context, vendor::sum_t<Flag, Expr>>
struct serializer_t<Context, vendor::sum_t<Flag, Expr>>
{
using T = vendor::sum_t<Flag, Expr>;
@ -83,10 +82,10 @@ namespace sqlpp
context << "SUM(";
if (std::is_same<sqlpp::distinct_t, Flag>::value)
{
interpret(Flag(), context);
serialize(Flag(), context);
context << ' ';
}
interpret(t._expr, context);
serialize(t._expr, context);
context << ")";
return context;
}
@ -94,14 +93,16 @@ namespace sqlpp
}
template<typename T>
auto sum(T t) -> typename vendor::sum_t<vendor::noop, typename operand_t<T, is_value_t>::type>
auto sum(T t) -> typename vendor::sum_t<vendor::noop, vendor::wrap_operand_t<T>>
{
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument");
return { t };
}
template<typename T>
auto sum(const sqlpp::distinct_t&, T t) -> typename vendor::sum_t<sqlpp::distinct_t, typename operand_t<T, is_value_t>::type>
auto sum(const sqlpp::distinct_t&, T t) -> typename vendor::sum_t<sqlpp::distinct_t, vendor::wrap_operand_t<T>>
{
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument");
return { t };
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -29,6 +29,7 @@
#include <sqlpp11/type_traits.h>
#include <sqlpp11/table_alias.h>
#include <sqlpp11/all_of.h>
#include <sqlpp11/column.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/join.h>
@ -42,10 +43,9 @@ namespace sqlpp
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 _all_columns = typename detail::make_set<column_t<Table, ColumnSpec>...>::type;
static_assert(_all_columns::size::value, "at least one column required per table");
using _required_insert_columns = typename detail::make_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type;
using _all_of_t = std::tuple<column_t<Table, ColumnSpec>...>;
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 _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
template<typename AliasProvider>
using _alias_t = table_alias_t<AliasProvider, Table, ColumnSpec...>;
@ -93,16 +93,10 @@ namespace sqlpp
}
};
template<typename Table>
auto all_of(Table t) -> typename Table::_all_of_t
{
return {};
}
namespace vendor
{
template<typename Context, typename X>
struct interpreter_t<Context, X, typename std::enable_if<std::is_base_of<table_base_t, X>::value and not is_pseudo_table_t<X>::value, void>::type>
struct serializer_t<Context, X, typename std::enable_if<std::is_base_of<table_base_t, X>::value and not is_pseudo_table_t<X>::value, void>::type>
{
using T = X;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -42,7 +42,7 @@ namespace sqlpp
{
//FIXME: Need to add join functionality
using _is_table = std::true_type;
using _table_set = detail::type_set<table_alias_t>;
using _table_set = detail::type_set<AliasProvider>;
struct _value_type: Table::_value_type
{
@ -52,7 +52,7 @@ namespace sqlpp
};
using _name_t = typename AliasProvider::_name_t;
using _all_of_t = std::tuple<column_t<AliasProvider, ColumnSpec>...>;
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
table_alias_t(Table table):
_table(table)
@ -64,14 +64,14 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename X>
struct interpreter_t<Context, X, typename std::enable_if<std::is_base_of<table_alias_base_t, X>::value, void>::type>
struct serializer_t<Context, X, typename std::enable_if<std::is_base_of<table_alias_base_t, X>::value, void>::type>
{
using T = X;
static Context& _(const T& t, Context& context)
{
context << "(";
interpret(t._table, context);
serialize(t._table, context);
context << ") AS " << T::_name_t::_get_name();
return context;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,7 +27,8 @@
#ifndef SQLPP_TEXT_H
#define SQLPP_TEXT_H
#include <sqlpp11/basic_operators.h>
#include <cassert>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h>
#include <sqlpp11/vendor/concat.h>
@ -40,6 +41,7 @@ namespace sqlpp
// text value type
struct text
{
using _value_type = text;
using _base_value_type = text;
using _is_text = std::true_type;
using _is_value = std::true_type;
@ -97,6 +99,7 @@ namespace sqlpp
bool _is_null;
};
template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t
{
_result_entry_t():
@ -135,15 +138,28 @@ namespace sqlpp
bool is_null() const
{
if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row");
return _value_ptr == nullptr;
}
_cpp_value_type value() const
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
const bool null_value = _value_ptr == nullptr and not NullIsTrivial and not connector_null_result_is_trivial_value_t<Db>::value;
if (connector_assert_result_validity_t<Db>::value)
{
assert(_is_valid);
assert(not null_value);
}
else
{
if (not _is_valid)
throw exception("accessing value in non-existing row");
if (null_value)
throw exception("accessing value of NULL field");
}
if (_value_ptr)
return std::string(_value_ptr, _value_ptr + _len);
else
@ -165,31 +181,52 @@ namespace sqlpp
};
template<typename T>
using _operand_t = operand_t<T, is_text_t>;
template<typename T>
using _constraint = is_text_t<T>;
struct _is_valid_operand
{
static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_text_t<T>::value // the correct value type is required, of course
;
};
template<typename Base>
struct operators: public basic_operators<Base, _operand_t>
struct expression_operators: public basic_expression_operators<Base, is_text_t>
{
template<typename T>
vendor::concat_t<Base, typename _operand_t<T>::type> operator+(T t) const
vendor::concat_t<Base, vendor::wrap_operand_t<T>> operator+(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
vendor::like_t<Base, typename _operand_t<T>::type> like(T t) const
vendor::like_t<Base, vendor::wrap_operand_t<T>> like(T t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid argument for like()");
return { *static_cast<const Base*>(this), {t} };
}
};
template<typename Base>
struct column_operators
{
template<typename T>
auto operator +=(T t) const -> vendor::assignment_t<Base, vendor::concat_t<Base, vendor::wrap_operand_t<T>>>
{
using rhs = vendor::wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
};
};
inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t& e)
template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t<Db, TrivialIsNull>& e)
{
return os << e.value();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -30,7 +30,8 @@
// TVIN: Trivial value is NULL
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/vendor/serializer.h>
namespace sqlpp
{
@ -39,6 +40,7 @@ namespace sqlpp
{
using _operand_t = Operand;
using _value_type = typename _operand_t::_value_type;
using _table_set = typename _operand_t::_table_set;
tvin_t(Operand operand):
_value(operand)
@ -60,7 +62,7 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Operand>
struct interpreter_t<Context, tvin_t<Operand>>
struct serializer_t<Context, tvin_t<Operand>>
{
using T = tvin_t<Operand>;
@ -72,41 +74,43 @@ namespace sqlpp
}
template<typename T>
struct tvin_wrap_t
struct maybe_tvin_t
{
using _table_set = typename T::_table_set;
static constexpr bool _is_trivial()
{
return false;
}
tvin_wrap_t(T t):
maybe_tvin_t(T t):
_value(t)
{}
tvin_wrap_t(const tvin_wrap_t&) = default;
tvin_wrap_t(tvin_wrap_t&&) = default;
tvin_wrap_t& operator=(const tvin_wrap_t&) = default;
tvin_wrap_t& operator=(tvin_wrap_t&&) = default;
~tvin_wrap_t() = default;
maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default;
maybe_tvin_t& operator=(const maybe_tvin_t&) = default;
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default;
T _value;
};
template<typename T>
struct tvin_wrap_t<tvin_t<T>>
struct maybe_tvin_t<tvin_t<T>>
{
using _table_set = typename T::_table_set;
bool _is_trivial() const
{
return _value._is_trivial();
};
tvin_wrap_t(tvin_t<T> t):
maybe_tvin_t(tvin_t<T> t):
_value(t._value)
{}
tvin_wrap_t(const tvin_wrap_t&) = default;
tvin_wrap_t(tvin_wrap_t&&) = default;
tvin_wrap_t& operator=(const tvin_wrap_t&) = default;
tvin_wrap_t& operator=(tvin_wrap_t&&) = default;
~tvin_wrap_t() = default;
maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default;
maybe_tvin_t& operator=(const maybe_tvin_t&) = default;
maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default;
typename tvin_t<T>::_operand_t _value;
};
@ -114,9 +118,9 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Operand>
struct interpreter_t<Context, tvin_wrap_t<Operand>>
struct serializer_t<Context, maybe_tvin_t<Operand>>
{
using T = tvin_wrap_t<Operand>;
using T = maybe_tvin_t<Operand>;
static Context& _(const T& t, Context& context)
{
@ -126,7 +130,7 @@ namespace sqlpp
}
else
{
interpret(t._value, context);
serialize(t._value, context);
}
return context;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -92,7 +92,9 @@ namespace sqlpp
SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_update);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null);
SQLPP_TYPE_TRAIT_GENERATOR(is_noop);
SQLPP_TYPE_TRAIT_GENERATOR(is_table);
SQLPP_TYPE_TRAIT_GENERATOR(is_join);
SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table);
@ -122,20 +124,11 @@ namespace sqlpp
SQLPP_TYPE_TRAIT_GENERATOR(requires_braces);
SQLPP_TYPE_TRAIT_GENERATOR(is_parameter);
SQLPP_CONNECTOR_TRAIT_GENERATOR(has_empty_list_insert);
SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value);
SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity);
template<typename T, template<typename> class IsTag>
using copy_type_trait = typename std::conditional<IsTag<T>::value, std::true_type, std::false_type>::type;
template<typename T, template<typename> class IsCorrectType>
struct operand_t
{
using type = typename vendor::wrap_operand<T>::type;
static_assert(not is_alias_t<type>::value, "expression operand must not be an alias");
static_assert(is_expression_t<type>::value, "expression required");
static_assert(IsCorrectType<type>::value, "invalid operand type");
};
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -30,110 +30,96 @@
#include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_update.h>
#include <sqlpp11/vendor/single_table.h>
#include <sqlpp11/vendor/update_list.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/where.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/arg_selector.h>
namespace sqlpp
{
template<
typename Database = void,
typename Table = vendor::noop,
typename Assignments = vendor::noop,
typename Where = vendor::noop
>
struct update_t;
template<typename Db,
typename... Policies
>
struct update_t;
template<
typename Database,
typename Table,
typename Assignments,
typename Where
>
struct update_t
namespace detail
{
template<typename Db = void,
typename Table = vendor::no_single_table_t,
typename UpdateList = vendor::no_update_list_t,
typename Where = vendor::no_where_t
>
struct update_policies_t
{
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>;
struct _methods_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>
struct _policies_update_t
{
using type = update_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement, Table, UpdateList, Where>::type;
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
};
}
template<typename Db,
typename... Policies
>
struct update_t:
public detail::update_policies_t<Db, Policies...>::_methods_t
{
static_assert(vendor::is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument");
static_assert(vendor::is_noop<Assignments>::value or is_update_list_t<Assignments>::value, "invalid 'Assignments' arguments");
static_assert(vendor::is_noop<Where>::value or is_where_t<Where>::value, "invalid 'Where' argument");
using _policies_t = typename detail::update_policies_t<Db, Policies...>;
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;
template<typename AssignmentsT>
using set_assignments_t = update_t<Database, Table, AssignmentsT, Where>;
template<typename WhereT>
using set_where_t = update_t<Database, Table, Assignments, WhereT>;
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<Table, Assignments, Where>;
using _parameter_tuple_t = std::tuple<Policies...>;
using _parameter_list_t = typename make_parameter_list_t<update_t>::type;
template<typename... Assignment>
auto set(Assignment... assignment)
-> set_assignments_t<vendor::update_list_t<void, Assignment...>>
{
static_assert(vendor::is_noop<Assignments>::value, "cannot call set() twice");
return {
_table,
{std::tuple<Assignment...>{assignment...}},
_where,
};
}
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");
template<typename... Assignment>
auto dynamic_set(Assignment... assignment)
-> set_assignments_t<vendor::update_list_t<Database, Assignment...>>
{
static_assert(vendor::is_noop<Assignments>::value, "cannot call set() twice");
return {
_table,
{std::tuple<Assignment...>{assignment...}},
_where,
};
}
// Constructors
update_t()
{}
template<typename Assignment>
update_t& add_set(Assignment assignment)
{
static_assert(is_dynamic_t<Assignments>::value, "cannot call add_set() in a non-dynamic set");
template<typename Statement, typename T>
update_t(Statement s, T t):
_table(detail::arg_selector<_table_t>::_(s._table, t)),
_update_list(detail::arg_selector<_update_list_t>::_(s._update_list, t)),
_where(detail::arg_selector<_where_t>::_(s._where, t))
{}
_assignments.add(assignment);
return *this;
}
template<typename... Expr>
auto where(Expr... expr)
-> set_where_t<vendor::where_t<void, Expr...>>
{
static_assert(not vendor::is_noop<Assignments>::value, "cannot call where() if set() hasn't been called yet");
static_assert(vendor::is_noop<Where>::value, "cannot call where() twice");
return {
_table,
_assignments,
{std::tuple<Expr...>{expr...}},
};
}
template<typename... Expr>
auto dynamic_where(Expr... expr)
-> set_where_t<vendor::where_t<Database, Expr...>>
{
static_assert(not vendor::is_noop<Assignments>::value, "cannot call where() if set() hasn't been called yet");
static_assert(vendor::is_noop<Where>::value, "cannot call where() twice");
return {
_table,
_assignments,
{std::tuple<Expr...>{expr...}},
};
}
template<typename Expr>
update_t& add_where(Expr expr)
{
static_assert(is_dynamic_t<Where>::value, "cannot call add_where() in a non-dynamic where");
_where.add(expr);
return *this;
}
update_t(const update_t&) = default;
update_t(update_t&&) = default;
update_t& operator=(const update_t&) = default;
update_t& operator=(update_t&&) = default;
~update_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
@ -144,62 +130,76 @@ namespace sqlpp
return _parameter_list_t::size::value;
}
template<typename Db>
std::size_t _run(Db& db) const
template<typename A>
struct is_table_subset_of_table
{
static_assert(not vendor::is_noop<Assignments>::value, "calling set() required before running update");
static_assert(is_where_t<Where>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _table_t::_table_set>::value;
};
void _check_consistency() const
{
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<_where_t>::value, "where requires additional tables");
}
template<typename Database>
std::size_t _run(Database& db) const
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead");
return db.update(*this);
}
template<typename Db>
auto _prepare(Db& db) const
-> prepared_update_t<Db, update_t>
template<typename Database>
auto _prepare(Database& db) const
-> prepared_update_t<Database, update_t>
{
static_assert(not vendor::is_noop<Assignments>::value, "calling set() required before running update");
_check_consistency();
return {{}, db.prepare_update(*this)};
}
Table _table;
Assignments _assignments;
Where _where;
_table_t _table;
_update_list_t _update_list;
_where_t _where;
};
namespace vendor
{
template<typename Context,
typename Database,
typename Table,
typename Assignments,
typename Where
>
struct interpreter_t<Context, update_t<Database, Table, Assignments, Where>>
{
using T = update_t<Database, Table, Assignments, Where>;
template<typename Context, typename Database, typename... Policies>
struct serializer_t<Context, update_t<Database, Policies...>>
{
using T = update_t<Database, Policies...>;
static Context& _(const T& t, Context& context)
{
context << "UPDATE ";
interpret(t._table, context);
interpret(t._assignments, context);
interpret(t._where, context);
return context;
}
};
static Context& _(const T& t, Context& context)
{
context << "UPDATE ";
serialize(t._table, context);
serialize(t._update_list, context);
serialize(t._where, context);
return context;
}
};
}
template<typename Database, typename... Policies>
using make_update_t = typename detail::update_policies_t<Database, Policies...>::_statement_t;
template<typename Table>
constexpr update_t<void, Table> update(Table table)
constexpr auto update(Table table)
-> make_update_t<void, vendor::single_table_t<void, Table>>
{
return {table};
return { update_t<void>(), vendor::single_table_t<void, Table>{table} };
}
template<typename Db, typename Table>
constexpr update_t<Db, Table> dynamic_update(const Db&, Table table)
template<typename Database, typename Table>
constexpr auto dynamic_update(const Database&, Table table)
-> make_update_t<Database, vendor::single_table_t<void, Table>>
{
return {table};
return { update_t<Database>(), vendor::single_table_t<void, Table>{table} };
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -30,13 +30,38 @@
#include <sqlpp11/default_value.h>
#include <sqlpp11/null.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/vendor/simple_column.h>
namespace sqlpp
{
namespace vendor
{
template<typename T, typename Enable = void>
struct is_trivial_t
{
static constexpr bool _(const T&)
{
return false;
}
};
template<typename T>
struct is_trivial_t<T, typename std::enable_if<std::is_member_function_pointer<decltype(&T::_is_trivial)>::value, void>::type>
{
static bool _(const T& t)
{
return t._is_trivial();
}
};
template<typename T>
bool is_trivial(const T& t)
{
return is_trivial_t<typename T::value_type>::_(t);
}
template<typename Lhs, typename Rhs>
struct assignment_t
{
@ -44,8 +69,9 @@ namespace sqlpp
using _column_t = Lhs;
using value_type = 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(not std::is_same<Rhs, null_t>::value or can_be_null_t<_column_t>::value, "column cannot be null");
static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same<Rhs, null_t>::value, "column must not be null");
assignment_t(_column_t lhs, value_type rhs):
_lhs(lhs),
@ -63,15 +89,25 @@ namespace sqlpp
};
template<typename Context, typename Lhs, typename Rhs>
struct interpreter_t<Context, assignment_t<Lhs, Rhs>>
struct serializer_t<Context, assignment_t<Lhs, Rhs>>
{
using T = assignment_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
interpret(simple_column(t._lhs), context);
context << "=";
interpret(t._rhs, context);
if ((trivial_value_is_null_t<typename T::_column_t>::value
and is_trivial_t<typename T::value_type>::_(t._rhs))
or (std::is_same<Rhs, null_t>::value))
{
serialize(simple_column(t._lhs), context);
context << "=NULL";
}
else
{
serialize(simple_column(t._lhs), context);
context << "=";
serialize(t._rhs, context);
}
return context;
}
};
@ -83,6 +119,7 @@ namespace sqlpp
using _column_t = Lhs;
using value_type = 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");
@ -102,13 +139,13 @@ namespace sqlpp
};
template<typename Context, typename Lhs, typename Rhs>
struct interpreter_t<Context, assignment_t<Lhs, tvin_t<Rhs>>>
struct serializer_t<Context, assignment_t<Lhs, tvin_t<Rhs>>>
{
using T = assignment_t<Lhs, tvin_t<Rhs>>;
static Context& _(const T& t, Context& context)
{
interpret(simple_column(t._lhs), context);
serialize(simple_column(t._lhs), context);
if (t._rhs._value._is_trivial())
{
context << "=NULL";
@ -116,7 +153,7 @@ namespace sqlpp
else
{
context << "=";
interpret(t._rhs._value, context);
serialize(t._rhs._value, context);
}
return context;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -36,10 +36,11 @@ namespace sqlpp
namespace vendor
{
template<typename First, typename... Args>
struct concat_t: public First::_value_type::template operators<concat_t<First, Args...>>
struct concat_t: public First::_value_type::template expression_operators<concat_t<First, Args...>>
{
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
static_assert(sqlpp::detail::and_t<is_text_t, First, Args...>::value, "at least one non-text argument detected in concat()");
static_assert(sqlpp::detail::all_t<is_text_t, First, Args...>::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
{
@ -70,7 +71,7 @@ namespace sqlpp
};
template<typename Context, typename First, typename... Args>
struct interpreter_t<Context, concat_t<First, Args...>>
struct serializer_t<Context, concat_t<First, Args...>>
{
using T = concat_t<First, Args...>;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -32,7 +32,7 @@
#include <sqlpp11/tvin.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/expression_fwd.h>
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/vendor/wrap_operand.h>
namespace sqlpp
@ -40,35 +40,36 @@ namespace sqlpp
namespace vendor
{
template<typename Lhs, typename Rhs>
struct equal_t: public ::sqlpp::detail::boolean::template operators<equal_t<Lhs, Rhs>>
struct binary_expression_t<Lhs, tag::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<equal_to_t<Lhs, Rhs>>
{
using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
equal_t(Lhs lhs, Rhs rhs):
binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
equal_t(const equal_t&) = default;
equal_t(equal_t&&) = default;
equal_t& operator=(const equal_t&) = default;
equal_t& operator=(equal_t&&) = default;
~equal_t() = default;
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
tvin_wrap_t<Rhs> _rhs;
maybe_tvin_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct interpreter_t<Context, equal_t<Lhs, Rhs>>
struct serializer_t<Context, equal_to_t<Lhs, Rhs>>
{
using T = equal_t<Lhs, Rhs>;
using T = equal_to_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
interpret(t._lhs, context);
serialize(t._lhs, context);
if (t._rhs._is_trivial())
{
context << " IS NULL";
@ -76,7 +77,7 @@ namespace sqlpp
else
{
context << "=";
interpret(t._rhs, context);
serialize(t._rhs, context);
}
context << ")";
return context;
@ -84,35 +85,36 @@ namespace sqlpp
};
template<typename Lhs, typename Rhs>
struct not_equal_t: public ::sqlpp::detail::boolean::template operators<not_equal_t<Lhs, Rhs>>
struct binary_expression_t<Lhs, tag::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<not_equal_to_t<Lhs, Rhs>>
{
using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
not_equal_t(Lhs lhs, Rhs rhs):
binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
not_equal_t(const not_equal_t&) = default;
not_equal_t(not_equal_t&&) = default;
not_equal_t& operator=(const not_equal_t&) = default;
not_equal_t& operator=(not_equal_t&&) = default;
~not_equal_t() = default;
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
tvin_wrap_t<Rhs> _rhs;
maybe_tvin_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct interpreter_t<Context, not_equal_t<Lhs, Rhs>>
struct serializer_t<Context, not_equal_to_t<Lhs, Rhs>>
{
using T = not_equal_t<Lhs, Rhs>;
using T = not_equal_to_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
interpret(t._lhs, context);
serialize(t._lhs, context);
if (t._rhs._is_trivial())
{
context << " IS NOT NULL";
@ -120,54 +122,56 @@ namespace sqlpp
else
{
context << "!=";
interpret(t._rhs, context);
serialize(t._rhs, context);
}
context << ")";
return context;
}
};
template<typename Lhs>
struct logical_not_t: public ::sqlpp::detail::boolean::template operators<logical_not_t<Lhs>>
template<typename Rhs>
struct unary_expression_t<tag::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<logical_not_t<Rhs>>
{
using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs>;
using _parameter_tuple_t = std::tuple<Rhs>;
using _table_set = typename Rhs::_table_set;
logical_not_t(Lhs l):
_lhs(l)
unary_expression_t(Rhs rhs):
_rhs(rhs)
{}
logical_not_t(const logical_not_t&) = default;
logical_not_t(logical_not_t&&) = default;
logical_not_t& operator=(const logical_not_t&) = default;
logical_not_t& operator=(logical_not_t&&) = default;
~logical_not_t() = default;
unary_expression_t(const unary_expression_t&) = default;
unary_expression_t(unary_expression_t&&) = default;
unary_expression_t& operator=(const unary_expression_t&) = default;
unary_expression_t& operator=(unary_expression_t&&) = default;
~unary_expression_t() = default;
Lhs _lhs;
Rhs _rhs;
};
template<typename Context, typename Lhs>
struct interpreter_t<Context, logical_not_t<Lhs>>
template<typename Context, typename Rhs>
struct serializer_t<Context, logical_not_t<Rhs>>
{
using T = logical_not_t<Lhs>;
using T = logical_not_t<Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
context << "NOT ";
interpret(t._lhs, context);
serialize(t._lhs, context);
context << ")";
return context;
}
};
template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t: public O::_value_type::template operators<binary_expression_t<Lhs, O, Rhs>>
struct binary_expression_t: public O::_value_type::template expression_operators<binary_expression_t<Lhs, O, Rhs>>
{
using _lhs_t = Lhs;
using _rhs_t = 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):
_lhs(lhs),
@ -185,26 +189,27 @@ namespace sqlpp
};
template<typename Context, typename Lhs, typename O, typename Rhs>
struct interpreter_t<Context, binary_expression_t<Lhs, O, Rhs>>
struct serializer_t<Context, binary_expression_t<Lhs, O, Rhs>>
{
using T = binary_expression_t<Lhs, O, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
interpret(t._lhs, context);
serialize(t._lhs, context);
context << O::_name;
interpret(t._rhs, context);
serialize(t._rhs, context);
context << ")";
return context;
}
};
template<typename O, typename Rhs>
struct unary_expression_t: public O::_value_type::template 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 _parameter_tuple_t = std::tuple<Rhs>;
using _table_set = typename Rhs::_table_set;
unary_expression_t(Rhs rhs):
_rhs(rhs)
@ -220,7 +225,7 @@ namespace sqlpp
};
template<typename Context, typename O, typename Rhs>
struct interpreter_t<Context, unary_expression_t<O, Rhs>>
struct serializer_t<Context, unary_expression_t<O, Rhs>>
{
using T = unary_expression_t<O, Rhs>;
@ -228,7 +233,7 @@ namespace sqlpp
{
context << "(";
context << O::_name;
interpret(t._rhs, context);
serialize(t._rhs, context);
context << ")";
return context;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -31,18 +31,9 @@ namespace sqlpp
{
namespace vendor
{
template<typename Lhs, typename Rhs>
struct equal_t;
template<typename Lhs, typename Rhs>
struct not_equal_t;
template<typename Lhs>
struct logical_not_t;
namespace tag
{
struct less_than
struct less
{
using _value_type = ::sqlpp::detail::boolean;
static constexpr const char* _name = "<";
@ -54,13 +45,23 @@ namespace sqlpp
static constexpr const char* _name = "<=";
};
struct equal_to
{
using _value_type = ::sqlpp::detail::boolean;
};
struct not_equal_to
{
using _value_type = ::sqlpp::detail::boolean;
};
struct greater_equal
{
using _value_type = ::sqlpp::detail::boolean;
static constexpr const char* _name = ">=";
};
struct greater_than
struct greater
{
using _value_type = ::sqlpp::detail::boolean;
static constexpr const char* _name = ">";
@ -78,6 +79,11 @@ namespace sqlpp
static constexpr const char* _name = " AND ";
};
struct logical_not
{
using _value_type = ::sqlpp::detail::boolean;
};
template<typename ValueType>
struct plus
{
@ -133,13 +139,19 @@ namespace sqlpp
struct unary_expression_t;
template<typename Lhs, typename Rhs>
using less_than_t = binary_expression_t<Lhs, tag::less_than, Rhs>;
using less_than_t = binary_expression_t<Lhs, tag::less, Rhs>;
template<typename Lhs, typename Rhs>
using less_equal_t = binary_expression_t<Lhs, tag::less_equal, Rhs>;
template<typename Lhs, typename Rhs>
using greater_than_t = binary_expression_t<Lhs, tag::greater_than, Rhs>;
using equal_to_t = binary_expression_t<Lhs, tag::equal_to, Rhs>;
template<typename Lhs, typename Rhs>
using not_equal_to_t = binary_expression_t<Lhs, tag::not_equal_to, Rhs>;
template<typename Lhs, typename Rhs>
using greater_than_t = binary_expression_t<Lhs, tag::greater, Rhs>;
template<typename Lhs, typename Rhs>
using greater_equal_t = binary_expression_t<Lhs, tag::greater_equal, Rhs>;
@ -165,6 +177,9 @@ namespace sqlpp
template<typename Lhs, typename Rhs>
using modulus_t = binary_expression_t<Lhs, tag::modulus, Rhs>;
template<typename Rhs>
using logical_not_t = unary_expression_t<tag::logical_not, Rhs>;
template<typename ValueType, typename Rhs>
using unary_plus_t = unary_expression_t<tag::unary_plus<ValueType>, Rhs>;

114
include/sqlpp11/vendor/extra_tables.h vendored Normal file
View File

@ -0,0 +1,114 @@
/*
* 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_EXTRA_TABLES_H
#define SQLPP_EXTRA_TABLES_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/vendor/policy_update.h>
namespace sqlpp
{
namespace vendor
{
// EXTRA_TABLES
template<typename... Tables>
struct extra_tables_t
{
using _is_extra_tables = std::true_type;
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(::sqlpp::detail::all_t<is_table_t, Tables...>::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(const extra_tables_t&) = default;
extra_tables_t(extra_tables_t&&) = default;
extra_tables_t& operator=(const extra_tables_t&) = default;
extra_tables_t& operator=(extra_tables_t&&) = default;
~extra_tables_t() = default;
template<typename Policies>
struct _methods_t
{
};
};
struct no_extra_tables_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
template<typename Policies>
struct _methods_t
{
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_extra_tables_t, T>;
template<typename... Args>
auto extra_tables(Args...)
-> _new_statement_t<extra_tables_t<Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), extra_tables_t<Args...>{} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, extra_tables_t<Database, Tables...>>
{
using T = extra_tables_t<Database, Tables...>;
static Context& _(const T& t, Context& context)
{
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_extra_tables_t>
{
using T = no_extra_tables_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -33,11 +33,12 @@ namespace sqlpp
{
namespace vendor
{
template<typename NameType, typename ValueType>
template<typename NameType, typename ValueType, bool TrivialValueIsNull>
struct field_t
{
using _name_t = NameType;
using _value_type = ValueType;
static constexpr bool _trivial_value_is_null = TrivialValueIsNull;
};
template<typename AliasProvider, typename FieldTuple>
@ -50,11 +51,13 @@ namespace sqlpp
template<typename NamedExpr>
struct make_field_t_impl
{
using type = field_t<typename NamedExpr::_name_t, typename NamedExpr::_value_type::_base_value_type>;
using type = field_t<typename NamedExpr::_name_t,
typename NamedExpr::_value_type::_base_value_type,
trivial_value_is_null_t<NamedExpr>::value>;
};
template<typename AliasProvider, typename... NamedExpr>
struct make_field_t_impl<multi_column_t<AliasProvider, std::tuple<NamedExpr...>>>
struct make_field_t_impl<multi_column_alias_t<AliasProvider, NamedExpr...>>
{
using type = multi_field_t<AliasProvider, std::tuple<typename make_field_t_impl<NamedExpr>::type...>>;
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,63 +27,132 @@
#ifndef SQLPP_FROM_H
#define SQLPP_FROM_H
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/vendor/policy_update.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... TableOrJoin>
// FROM
template<typename Database, typename... Tables>
struct from_t
{
using _is_from = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
// ensure one argument at least
static_assert(_is_dynamic::value or sizeof...(TableOrJoin), "at least one table or join argument required in from()");
// check for duplicate arguments
static_assert(not ::sqlpp::detail::has_duplicates<TableOrJoin...>::value, "at least one duplicate argument detected in from()");
// check for invalid arguments
static_assert(::sqlpp::detail::and_t<is_table_t, TableOrJoin...>::value, "at least one argument is not a table or join in from()");
static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table or join argument required in from()");
// FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in from()");
template<typename Table>
void add(Table table)
static_assert(::sqlpp::detail::all_t<is_table_t, Tables...>::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...>;
from_t(Tables... tables):
_tables(tables...)
{}
from_t(const from_t&) = default;
from_t(from_t&&) = default;
from_t& operator=(const from_t&) = default;
from_t& operator=(from_t&&) = default;
~from_t() = default;
template<typename Policies>
struct _methods_t
{
static_assert(is_table_t<Table>::value, "from arguments require to be tables or joins");
_dynamic_tables.emplace_back(table);
}
template<typename Table>
void add_from(Table table)
{
static_assert(_is_dynamic::value, "add_from must not be called for static from()");
static_assert(is_table_t<Table>::value, "invalid table argument in add_from()");
std::tuple<TableOrJoin...> _tables;
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_table_t<Table>>;
_add_from_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Table>
void _add_from_impl(Table table, const std::true_type&)
{
return static_cast<typename Policies::_statement_t*>(this)->_from._dynamic_tables.emplace_back(table);
}
template<typename Table>
void _add_from_impl(Table table, const std::false_type&);
};
std::tuple<Tables...> _tables;
vendor::interpretable_list_t<Database> _dynamic_tables;
};
template<typename Context, typename Database, typename... TableOrJoin>
struct interpreter_t<Context, from_t<Database, TableOrJoin...>>
struct no_from_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
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_from_t, T>;
template<typename... Args>
auto from(Args... args)
-> _new_statement_t<from_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), from_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_from(Args... args)
-> _new_statement_t<from_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::from_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, from_t<Database, Tables...>>
{
using T = from_t<Database, TableOrJoin...>;
using T = from_t<Database, Tables...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(TableOrJoin) == 0 and t._dynamic_tables.empty())
if (sizeof...(Tables) == 0 and t._dynamic_tables.empty())
return context;
context << " FROM ";
interpret_tuple(t._tables, ',', context);
if (sizeof...(TableOrJoin) and not t._dynamic_tables.empty())
if (sizeof...(Tables) and not t._dynamic_tables.empty())
context << ',';
interpret_list(t._dynamic_tables, ',', context);
return context;
}
};
}
template<typename Context>
struct serializer_t<Context, no_from_t>
{
using T = no_from_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -32,57 +32,136 @@
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... Expr>
// GROUP BY
template<typename Database, typename... Expressions>
struct group_by_t
{
using _is_group_by = std::true_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<Expr...>;
using _parameter_tuple_t = std::tuple<Expressions...>;
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
// ensure one argument at least
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression (e.g. a column) required in group_by()");
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
// check for duplicate expressions
static_assert(not ::sqlpp::detail::has_duplicates<Expr...>::value, "at least one duplicate argument detected in group_by()");
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
// check for invalid expressions
static_assert(::sqlpp::detail::and_t<is_expression_t, Expr...>::value, "at least one argument is not an expression in group_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
template<typename E>
void add(E expr)
static_assert(::sqlpp::detail::all_t<is_expression_t, Expressions...>::value, "at least one argument is not an expression in group_by()");
group_by_t(Expressions... expressions):
_expressions(expressions...)
{}
group_by_t(const group_by_t&) = default;
group_by_t(group_by_t&&) = default;
group_by_t& operator=(const group_by_t&) = default;
group_by_t& operator=(group_by_t&&) = default;
~group_by_t() = default;
template<typename Policies>
struct _methods_t
{
static_assert(is_table_t<E>::value, "from arguments require to be tables or joins");
_dynamic_expressions.emplace_back(expr);
}
template<typename Expression>
void add_group_by_ntc(Expression expression)
{
add_group_by<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_group_by(Expression expression)
{
static_assert(_is_dynamic::value, "add_group_by must not be called for static group_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_group_by()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_group_by()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_expression_t<Expression>>;
_add_group_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
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);
}
template<typename Expression>
void _add_group_by_impl(Expression expression, const std::false_type&);
};
const group_by_t& _group_by() const { return *this; }
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
template<typename Context, typename Database, typename... Expr>
struct interpreter_t<Context, group_by_t<Database, Expr...>>
struct no_group_by_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
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_group_by_t, T>;
template<typename... Args>
auto group_by(Args... args)
-> _new_statement_t<group_by_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), group_by_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_group_by(Args... args)
-> _new_statement_t<group_by_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::group_by_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, group_by_t<Database, Expressions...>>
{
using T = group_by_t<Database, Expr...>;
using T = group_by_t<Database, Expressions...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " GROUP BY ";
interpret_tuple(t._expressions, ',', context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << ',';
interpret_list(t._dynamic_expressions, ',', context);
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_group_by_t>
{
using T = no_group_by_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -31,52 +31,133 @@
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... Expr>
// HAVING
template<typename Database, typename... Expressions>
struct having_t
{
using _is_having = std::true_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<Expr...>;
using _parameter_tuple_t = std::tuple<Expressions...>;
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in having()");
static_assert(::sqlpp::detail::and_t<is_expression_t, Expr...>::value, "at least one argument is not an expression 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, "at least one argument is not an expression in having()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
template<typename E>
void add(E expr)
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
having_t(Expressions... expressions):
_expressions(expressions...)
{}
having_t(const having_t&) = default;
having_t(having_t&&) = default;
having_t& operator=(const having_t&) = default;
having_t& operator=(having_t&&) = default;
~having_t() = default;
template<typename Policies>
struct _methods_t
{
static_assert(is_expression_t<E>::value, "invalid expression argument in add_having()");
_dynamic_expressions.emplace_back(expr);
}
template<typename Expression>
void add_having_ntc(Expression expression)
{
add_having<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_having(Expression expression)
{
static_assert(_is_dynamic::value, "add_having must not be called for static having");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_having()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_having()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_expression_t<Expression>>;
_add_having_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_having_impl(Expression expression, const std::true_type&)
{
return static_cast<typename Policies::_statement_t*>(this)->_having._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_having_impl(Expression expression, const std::false_type&);
};
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
template<typename Context, typename Database, typename... Expr>
struct interpreter_t<Context, having_t<Database, Expr...>>
struct no_having_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
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_having_t, T>;
template<typename... Args>
auto having(Args... args)
-> _new_statement_t<having_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), having_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_having(Args... args)
-> _new_statement_t<having_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::having_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, having_t<Database, Expressions...>>
{
using T = having_t<Database, Expr...>;
using T = having_t<Database, Expressions...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " HAVING ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_having_t>
{
using T = no_having_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -37,7 +37,7 @@ namespace sqlpp
namespace vendor
{
template<bool NotInverted, typename Operand, typename... Args>
struct in_t: public boolean::template operators<in_t<NotInverted, Operand, Args...>>
struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>
{
static constexpr bool _inverted = not NotInverted;
static_assert(sizeof...(Args) > 0, "in() requires at least one argument");
@ -56,6 +56,7 @@ namespace sqlpp
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):
_operand(operand),
@ -73,13 +74,13 @@ namespace sqlpp
};
template<typename Context, bool NotInverted, typename Operand, typename... Args>
struct interpreter_t<Context, vendor::in_t<NotInverted, Operand, Args...>>
struct serializer_t<Context, vendor::in_t<NotInverted, Operand, Args...>>
{
using T = vendor::in_t<NotInverted, Operand, Args...>;
static Context& _(const T& t, Context& context)
{
interpret(t._operand, context);
serialize(t._operand, context);
context << (t._inverted ? " NOT IN(" : " IN(");
interpret_tuple(t._args, ',', context);
context << ')';

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,141 +0,0 @@
/*
* Copyright (c) 2013, 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_INSERT_LIST_H
#define SQLPP_INSERT_LIST_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/simple_column.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
namespace vendor
{
struct insert_default_values_t
{
using _is_insert_list = std::true_type;
using _is_dynamic = std::false_type;
};
template<typename Context>
struct interpreter_t<Context, insert_default_values_t>
{
using T = insert_default_values_t;
static Context& _(const T& t, Context& context)
{
context << " DEFAULT VALUES";
return context;
}
};
template<typename Database, typename... Assignments>
struct insert_list_t
{
using _is_insert_list = std::true_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>
using copy_assignments_t = Target<Assignments...>; // FIXME: Nice idea to copy variadic template arguments?
template<template<typename...> class Target, template<typename> class Wrap>
using copy_wrapped_assignments_t = Target<Wrap<Assignments>...>;
// check for at least one order expression
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one select expression required in set()");
// check for duplicate assignments
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
// check for invalid assignments
static_assert(sqlpp::detail::and_t<is_assignment_t, Assignments...>::value, "at least one argument is not an assignment in set()");
// check for prohibited assignments
static_assert(not sqlpp::detail::or_t<must_not_insert_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()");
insert_list_t(Assignments... assignment):
_assignments(assignment...),
_columns({assignment._lhs}...),
_values(assignment._rhs...)
{}
insert_list_t(const insert_list_t&) = default;
insert_list_t(insert_list_t&&) = default;
insert_list_t& operator=(const insert_list_t&) = default;
insert_list_t& operator=(insert_list_t&&) = default;
~insert_list_t() = default;
template<typename Assignment>
void add(Assignment assignment)
{
static_assert(is_assignment_t<Assignment>::value, "set() arguments require to be assigments");
static_assert(not must_not_insert_t<Assignment>::value, "set() argument must not be used in insert");
_dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
_dynamic_values.emplace_back(assignment._rhs);
}
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
std::tuple<typename Assignments::value_type...> _values;
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_values;
};
template<typename Context, typename Database, typename... Assignments>
struct interpreter_t<Context, insert_list_t<Database, Assignments...>>
{
using T = insert_list_t<Database, Assignments...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Assignments) + t._dynamic_columns.size() == 0)
{
interpret(insert_default_values_t(), context);
}
else
{
context << " (";
interpret_tuple(t._columns, ",", context);
if (sizeof...(Assignments) and not t._dynamic_columns.empty())
context << ',';
interpret_list(t._dynamic_columns, ',', context);
context << ") VALUES(";
interpret_tuple(t._values, ",", context);
if (sizeof...(Assignments) and not t._dynamic_values.empty())
context << ',';
interpret_list(t._dynamic_values, ',', context);
context << ")";
}
return context;
}
};
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -31,7 +31,8 @@
#include <sqlpp11/null.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
@ -43,6 +44,7 @@ namespace sqlpp
struct type_if
{
using type = Type;
using _table_set = typename Type::_table_set;
};
template<typename Type>
@ -50,6 +52,7 @@ namespace sqlpp
{
struct type
{
using _table_set = sqlpp::detail::type_set<>;
};
};
}
@ -99,7 +102,7 @@ namespace sqlpp
};
template<typename Context, typename ValueType>
struct interpreter_t<Context, insert_value_t<ValueType>>
struct serializer_t<Context, insert_value_t<ValueType>>
{
using T = insert_value_t<ValueType>;
@ -110,7 +113,7 @@ namespace sqlpp
else if (t._is_default)
context << "DEFAULT";
else
interpret(t._value, context);
serialize(t._value, context);
return context;
}
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -29,62 +29,242 @@
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/vendor/insert_value.h>
#include <sqlpp11/vendor/assignment.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/insert_value.h>
#include <sqlpp11/vendor/simple_column.h>
namespace sqlpp
{
namespace vendor
{
template<typename... InsertValues>
struct insert_value_list_t
// COLUMN AND VALUE LIST
struct insert_default_values_t
{
using _table_set = ::sqlpp::detail::type_set<>;
using _is_dynamic = std::false_type;
template<typename Policies>
struct _methods_t
{};
};
template<typename Database, typename... Assignments>
struct insert_list_t
{
using _is_insert_value_list = std::true_type;
using _is_insert_list = std::true_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>
using copy_assignments_t = Target<Assignments...>; // FIXME: Nice idea to copy variadic template arguments?
template<template<typename...> class Target, template<typename> class Wrap>
using copy_wrapped_assignments_t = Target<Wrap<Assignments>...>;
static_assert(sizeof...(InsertValues), "at least one insert value required");
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one select expression required in set()");
// check for invalid arguments
static_assert(::sqlpp::detail::and_t<is_insert_value_t, InsertValues...>::value, "at least one argument is not an insert value");
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
using _value_tuple_t = std::tuple<InsertValues...>;
static_assert(sqlpp::detail::all_t<is_assignment_t, Assignments...>::value, "at least one argument is not an assignment in set()");
void add(_value_tuple_t value_tuple)
{
_insert_values.emplace_back(value_tuple);
}
static_assert(not sqlpp::detail::any_t<must_not_insert_t, typename Assignments::_column_t...>::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;
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;
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");
insert_list_t(Assignments... assignment):
_assignments(assignment...),
_columns({assignment._lhs}...),
_values(assignment._rhs...)
{}
insert_list_t(const insert_list_t&) = default;
insert_list_t(insert_list_t&&) = default;
insert_list_t& operator=(const insert_list_t&) = default;
insert_list_t& operator=(insert_list_t&&) = default;
~insert_list_t() = default;
template<typename Policies>
struct _methods_t
{
template<typename Assignment>
void add_set(Assignment assignment)
{
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(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;
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<sqlpp::detail::identity_t,
_is_dynamic,
is_assignment_t<Assignment>,
::sqlpp::detail::not_t<must_not_insert_t, typename Assignment::_column_t>,
::sqlpp::detail::is_subset_of<_value_table_set, typename Policies::_table_set>,
::sqlpp::detail::is_subset_of<_column_table_set, typename Policies::_table_set>>;
_add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Assignment>
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_values.emplace_back(assignment._rhs);
}
template<typename Assignment>
void _add_set_impl(Assignment assignment, const std::false_type&);
};
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
std::tuple<typename Assignments::value_type...> _values;
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_values;
};
template<typename... Columns>
struct column_list_t
{
using _is_column_list = std::true_type;
using _parameter_tuple_t = std::tuple<Columns...>;
static_assert(sizeof...(Columns), "at least one column required in columns()");
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected in columns()");
static_assert(::sqlpp::detail::all_t<is_column_t, Columns...>::value, "at least one argument is not a column in columns()");
static_assert(not ::sqlpp::detail::any_t<must_not_insert_t, Columns...>::value, "at least one column argument has a must_not_insert flag in its definition");
using _value_tuple_t = std::tuple<vendor::insert_value_t<Columns>...>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Columns::_table_set...>::type;
static_assert(_table_set::size::value == 1, "columns from multiple tables in columns()");
column_list_t(Columns... columns):
_columns(simple_column_t<Columns>{columns}...)
{}
column_list_t(const column_list_t&) = default;
column_list_t(column_list_t&&) = default;
column_list_t& operator=(const column_list_t&) = default;
column_list_t& operator=(column_list_t&&) = default;
~column_list_t() = default;
template<typename Policies>
struct _methods_t
{
template<typename... Assignments>
void add_values(Assignments... assignments)
{
static_assert(::sqlpp::detail::all_t<is_assignment_t, Assignments...>::value, "add_values() arguments have to be assignments");
using _arg_value_tuple = std::tuple<vendor::insert_value_t<typename Assignments::_column_t>...>;
using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>;
static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t,
::sqlpp::detail::all_t<is_assignment_t, Assignments...>,
_args_correct>;
_add_values_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename... 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}...);
}
template<typename... Assignments>
void _add_values_impl(const std::false_type&, Assignments... assignments);
};
bool empty() const
{
return _insert_values.empty();
}
std::tuple<simple_column_t<Columns>...> _columns;
std::vector<_value_tuple_t> _insert_values;
};
template<>
struct insert_value_list_t<noop>
{
using _is_insert_value_list = std::true_type;
struct no_insert_value_list_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
using _value_tuple_t = std::tuple<>;
void add(_value_tuple_t value_tuple)
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_insert_value_list_t, T>;
static constexpr bool empty()
{
return true;
}
};
auto default_values()
-> _new_statement_t<insert_default_values_t>
{
return { *static_cast<typename Policies::_statement_t*>(this), insert_default_values_t{} };
}
template<typename Context, typename... InsertValues>
struct interpreter_t<Context, insert_value_list_t<InsertValues...>>
template<typename... Args>
auto columns(Args... args)
-> _new_statement_t<column_list_t<Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), column_list_t<Args...>{args...} };
}
template<typename... Args>
auto set(Args... args)
-> _new_statement_t<insert_list_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), insert_list_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_set(Args... args)
-> _new_statement_t<insert_list_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::insert_list_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context>
struct serializer_t<Context, insert_default_values_t>
{
using T = insert_value_list_t<InsertValues...>;
using T = insert_default_values_t;
static Context& _(const T& t, Context& context)
{
context << " DEFAULT VALUES";
return context;
}
};
template<typename Context, typename... Columns>
struct serializer_t<Context, column_list_t<Columns...>>
{
using T = column_list_t<Columns...>;
static Context& _(const T& t, Context& context)
{
context << " (";
interpret_tuple(t._columns, ",", context);
context << ")";
context << " VALUES ";
bool first = true;
for (const auto& row : t._insert_values)
@ -97,20 +277,51 @@ namespace sqlpp
interpret_tuple(row, ",", context);
context << ')';
}
return context;
}
};
template<typename Context, typename Database, typename... Assignments>
struct serializer_t<Context, insert_list_t<Database, Assignments...>>
{
using T = insert_list_t<Database, Assignments...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Assignments) + t._dynamic_columns.size() == 0)
{
serialize(insert_default_values_t(), context);
}
else
{
context << " (";
interpret_tuple(t._columns, ",", context);
if (sizeof...(Assignments) and not t._dynamic_columns.empty())
context << ',';
interpret_list(t._dynamic_columns, ',', context);
context << ") VALUES(";
interpret_tuple(t._values, ",", context);
if (sizeof...(Assignments) and not t._dynamic_values.empty())
context << ',';
interpret_list(t._dynamic_values, ',', context);
context << ")";
}
return context;
}
};
template<typename Context>
struct interpreter_t<Context, insert_value_list_t<noop>>
struct serializer_t<Context, no_insert_value_list_t>
{
using T = insert_value_list_t<noop>;
using T = no_insert_value_list_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,8 +28,8 @@
#define SQLPP_INTERPRET_TUPLE_H
#include <tuple>
#include <ostream>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/serialize.h>
namespace sqlpp
{
@ -54,7 +54,7 @@ namespace sqlpp
using entry_type = typename std::tuple_element<index, Tuple>::type;
if (requires_braces_t<entry_type>::value)
context << "(";
interpret(entry, context);
serialize(entry, context);
if (requires_braces_t<entry_type>::value)
context << ")";
_impl(t, separator, context, type<index + 1>());

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,8 +28,9 @@
#define SQLPP_INTERPRETABLE_H
#include <memory>
#include <sqlpp11/serializer.h>
#include <sqlpp11/serializer_context.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/interpret.h>
namespace sqlpp
@ -39,7 +40,8 @@ namespace sqlpp
template<typename Db>
struct interpretable_t
{
using _context_t = typename Db::_context_t;
using _serializer_context_t = typename Db::_serializer_context_t;
using _interpreter_context_t = typename Db::_interpreter_context_t;
template<typename T>
interpretable_t(T t):
@ -52,12 +54,21 @@ namespace sqlpp
interpretable_t& operator=(interpretable_t&&) = default;
~interpretable_t() = default;
sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const
{
return _impl->interpret(context);
return _impl->serialize(context);
}
_context_t& interpret(_context_t& context) const
// This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same
template<typename Context>
auto serialize(Context& context) const
-> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value
and not std::is_same<Context, sqlpp::serializer_context_t>::value, Context&>::type
{
return _impl->db_serialize(context);
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
{
return _impl->interpret(context);
}
@ -65,8 +76,9 @@ namespace sqlpp
private:
struct _impl_base
{
virtual sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const = 0;
virtual _context_t& interpret(_context_t& context) const = 0;
virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0;
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
};
template<typename T>
@ -77,15 +89,21 @@ namespace sqlpp
_t(t)
{}
sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const
{
sqlpp::interpret(_t, context);
sqlpp::serialize(_t, context);
return context;
}
_context_t& interpret(_context_t& context) const
_serializer_context_t& db_serialize(_serializer_context_t& context) const
{
sqlpp::interpret(_t, context);
Db::_serialize_interpretable(_t, context);
return context;
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
{
Db::_interpret_interpretable(_t, context);
return context;
}
@ -96,13 +114,13 @@ namespace sqlpp
};
template<typename Context, typename Database>
struct interpreter_t<Context, interpretable_t<Database>>
struct serializer_t<Context, interpretable_t<Database>>
{
using T = interpretable_t<Database>;
static Context& _(const T& t, Context& context)
{
t.interpret(context);
t.serialize(context);
return context;
}
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -60,9 +60,6 @@ namespace sqlpp
template<>
struct interpretable_list_t<void>
{
template<typename T>
void emplace_back(const T&) {}
static constexpr std::size_t size()
{
return 0;
@ -91,7 +88,7 @@ namespace sqlpp
context << separator;
first = false;
}
interpret(entry, context);
serialize(entry, context);
}
return context;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -24,8 +24,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_VENDOR_INTERPRET_H
#define SQLPP_VENDOR_INTERPRET_H
#ifndef SQLPP_VENDOR_INTERPRETER_H
#define SQLPP_VENDOR_INTERPRETER_H
#include <sqlpp11/vendor/wrong.h>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -36,9 +36,10 @@ namespace sqlpp
namespace vendor
{
template<bool NotInverted, typename Operand>
struct is_null_t: public boolean::template operators<is_null_t<NotInverted, Operand>>
struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>
{
static constexpr bool _inverted = not NotInverted;
using _table_set = typename Operand::_table_set;
struct _value_type: public boolean
{
@ -69,13 +70,13 @@ namespace sqlpp
};
template<typename Context, bool NotInverted, typename Operand>
struct interpreter_t<Context, ::sqlpp::vendor::is_null_t<NotInverted, Operand>>
struct serializer_t<Context, ::sqlpp::vendor::is_null_t<NotInverted, Operand>>
{
using T = ::sqlpp::vendor::is_null_t<NotInverted, Operand>;
static Context& _(const T& t, Context& context)
{
interpret(t._operand, context);
serialize(t._operand, context);
context << (t._inverted ? " IS NOT NULL" : " IS NULL");
return context;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -36,11 +36,12 @@ namespace sqlpp
namespace vendor
{
template<typename Operand, typename Pattern>
struct like_t: public boolean::template operators<like_t<Operand, Pattern>>
struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>
{
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");
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
{
@ -73,15 +74,15 @@ namespace sqlpp
};
template<typename Context, typename Operand, typename Pattern>
struct interpreter_t<Context, like_t<Operand, Pattern>>
struct serializer_t<Context, like_t<Operand, Pattern>>
{
using T = like_t<Operand, Pattern>;
static Context& _(const T& t, Context& context)
{
interpret(t._operand, context);
serialize(t._operand, context);
context << " LIKE(";
interpret(t._pattern, context);
serialize(t._pattern, context);
context << ")";
return context;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,63 +27,153 @@
#ifndef SQLPP_LIMIT_H
#define SQLPP_LIMIT_H
#include <ostream>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
namespace vendor
{
// LIMIT
template<typename Limit>
struct limit_t
{
using _is_limit = std::true_type;
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 _limit;
limit_t(Limit value):
_value(value)
{}
limit_t(const limit_t&) = default;
limit_t(limit_t&&) = default;
limit_t& operator=(const limit_t&) = default;
limit_t& operator=(limit_t&&) = default;
~limit_t() = default;
template<typename Policies>
struct _methods_t
{
};
Limit _value;
};
template<typename Database>
struct dynamic_limit_t
{
using _is_limit = std::true_type;
using _is_dynamic = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
dynamic_limit_t():
_value(noop())
{
}
template<typename Limit>
dynamic_limit_t(Limit value):
_initialized(true),
_value(typename wrap_operand<Limit>::type(value))
{
}
dynamic_limit_t(const dynamic_limit_t&) = default;
dynamic_limit_t(dynamic_limit_t&&) = default;
dynamic_limit_t& operator=(const dynamic_limit_t&) = default;
dynamic_limit_t& operator=(dynamic_limit_t&&) = default;
~dynamic_limit_t() = default;
template<typename Policies>
struct _methods_t
{
template<typename Limit>
void set_limit(Limit value)
{
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Limit>::type;
static_cast<typename Policies::_statement_t*>(this)->_limit._value = arg_t{value};
static_cast<typename Policies::_statement_t*>(this)->_limit._initialized = true;
}
};
bool _initialized = false;
interpretable_t<Database> _value;
};
struct no_limit_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
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_limit_t, T>;
template<typename Arg>
auto limit(Arg arg)
-> _new_statement_t<limit_t<typename wrap_operand<Arg>::type>>
{
return { *static_cast<typename Policies::_statement_t*>(this), limit_t<typename wrap_operand<Arg>::type>{{arg}} };
}
auto dynamic_limit()
-> _new_statement_t<dynamic_limit_t<_database_t>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_limit_t<_database_t>{} };
}
};
};
// Interpreters
template<typename Context, typename Database>
struct serializer_t<Context, dynamic_limit_t<Database>>
{
using T = dynamic_limit_t<Database>;
static Context& _(const T& t, Context& context)
{
if (t._initialized)
{
context << " LIMIT ";
serialize(t._value, context);
}
return context;
}
};
template<typename Context, typename Limit>
struct interpreter_t<Context, limit_t<Limit>>
struct serializer_t<Context, limit_t<Limit>>
{
using T = limit_t<Limit>;
static Context& _(const T& t, Context& context)
{
context << " LIMIT ";
interpret(t._limit, context);
serialize(t._value, context);
return context;
}
};
struct dynamic_limit_t
{
using _is_limit = std::true_type;
using _is_dynamic = std::true_type;
void set(std::size_t limit)
{
_limit = limit;
}
std::size_t _limit;
};
template<typename Context>
struct interpreter_t<Context, dynamic_limit_t>
struct serializer_t<Context, no_limit_t>
{
using T = dynamic_limit_t;
using T = no_limit_t;
static Context& _(const T& t, Context& context)
{
if (t._limit > 0)
context << " LIMIT " << t._limit;
return context;
}
};
}
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,7 +28,7 @@
#define SQLPP_NAMED_SERIALIZABLE_H
#include <memory>
#include <sqlpp11/serializer.h>
#include <sqlpp11/serializer_context.h>
#include <sqlpp11/parameter_list.h>
namespace sqlpp
@ -38,7 +38,8 @@ namespace sqlpp
template<typename Db>
struct named_interpretable_t
{
using _context_t = typename Db::_context_t;
using _serializer_context_t = typename Db::_serializer_context_t;
using _interpreter_context_t = typename Db::_interpreter_context_t;
template<typename T>
named_interpretable_t(T t):
@ -51,12 +52,21 @@ namespace sqlpp
named_interpretable_t& operator=(named_interpretable_t&&) = default;
~named_interpretable_t() = default;
sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const
{
return _impl->interpret(context);
return _impl->serialize(context);
}
_context_t& interpret(_context_t& context) const
// This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same
template<typename Context>
auto serialize(Context& context) const
-> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value
and not std::is_same<Context, sqlpp::serializer_context_t>::value, Context&>::type
{
return _impl->db_serialize(context);
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
{
return _impl->interpret(context);
}
@ -69,8 +79,9 @@ namespace sqlpp
private:
struct _impl_base
{
virtual sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const = 0;
virtual _context_t& interpret(_context_t& context) const = 0;
virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0;
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
virtual std::string _get_name() const = 0;
};
@ -82,15 +93,21 @@ namespace sqlpp
_t(t)
{}
sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const
{
sqlpp::interpret(_t, context);
sqlpp::serialize(_t, context);
return context;
}
_context_t& interpret(_context_t& context) const
_serializer_context_t& db_serialize(_serializer_context_t& context) const
{
sqlpp::interpret(_t, context);
Db::_serialize_interpretable(_t, context);
return context;
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
{
Db::_interpret_interpretable(_t, context);
return context;
}
@ -106,13 +123,13 @@ namespace sqlpp
};
template<typename Context, typename Database>
struct interpreter_t<Context, named_interpretable_t<Database>>
struct serializer_t<Context, named_interpretable_t<Database>>
{
using T = named_interpretable_t<Database>;
static Context& _(const T& t, Context& context)
{
t.interpret(context);
t.serialize(context);
return context;
}
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -35,10 +35,11 @@ namespace sqlpp
{
struct noop
{
using is_noop = std::true_type;
};
template<typename Context>
struct interpreter_t<Context, noop>
struct serializer_t<Context, noop>
{
using T = noop;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,59 +28,149 @@
#define SQLPP_OFFSET_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
namespace vendor
{
// OFFSET
template<typename Offset>
struct offset_t
{
using _is_offset = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
Offset _offset;
offset_t(Offset value):
_value(value)
{}
offset_t(const offset_t&) = default;
offset_t(offset_t&&) = default;
offset_t& operator=(const offset_t&) = default;
offset_t& operator=(offset_t&&) = default;
~offset_t() = default;
template<typename Policies>
struct _methods_t
{
};
Offset _value;
};
template<typename Database>
struct dynamic_offset_t
{
using _is_offset = std::true_type;
using _is_dynamic = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
dynamic_offset_t():
_value(noop())
{
}
template<typename Offset>
dynamic_offset_t(Offset value):
_initialized(true),
_value(typename wrap_operand<Offset>::type(value))
{
}
dynamic_offset_t(const dynamic_offset_t&) = default;
dynamic_offset_t(dynamic_offset_t&&) = default;
dynamic_offset_t& operator=(const dynamic_offset_t&) = default;
dynamic_offset_t& operator=(dynamic_offset_t&&) = default;
~dynamic_offset_t() = default;
template<typename Policies>
struct _methods_t
{
template<typename Offset>
void set_offset(Offset value)
{
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Offset>::type;
static_cast<typename Policies::_statement_t*>(this)->_offset._value = arg_t{value};
static_cast<typename Policies::_statement_t*>(this)->_offset._initialized = true;
}
};
bool _initialized = false;
interpretable_t<Database> _value;
};
struct no_offset_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
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_offset_t, T>;
template<typename Arg>
auto offset(Arg arg)
-> _new_statement_t<offset_t<typename wrap_operand<Arg>::type>>
{
return { *static_cast<typename Policies::_statement_t*>(this), offset_t<typename wrap_operand<Arg>::type>{{arg}} };
}
auto dynamic_offset()
-> _new_statement_t<dynamic_offset_t<_database_t>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_offset_t<_database_t>{} };
}
};
};
// Interpreters
template<typename Context, typename Offset>
struct interpreter_t<Context, offset_t<Offset>>
struct serializer_t<Context, offset_t<Offset>>
{
using T = offset_t<Offset>;
static Context& _(const T& t, Context& context)
{
context << " OFFSET ";
interpret(t._offset, context);
serialize(t._value, context);
return context;
}
};
struct dynamic_offset_t
{
using _is_offset = std::true_type;
using _is_dynamic = std::true_type;
void set(std::size_t offset)
template<typename Context, typename Database>
struct serializer_t<Context, dynamic_offset_t<Database>>
{
_offset = offset;
}
std::size_t _offset;
};
template<typename Context>
struct interpreter_t<Context, dynamic_offset_t>
{
using T = dynamic_offset_t;
using T = dynamic_offset_t<Database>;
static Context& _(const T& t, Context& context)
{
if (t._offset > 0)
context << " OFFSET " << t._offset;
if (t._initialized)
{
context << " OFFSET ";
serialize(t._value, context);
}
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_offset_t>
{
using T = no_offset_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,59 +28,138 @@
#define SQLPP_ORDER_BY_H
#include <tuple>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database,typename... Expr>
template<typename Database,typename... Expressions>
struct order_by_t
{
using _is_order_by = std::true_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<Expr...>;
using _parameter_tuple_t = std::tuple<Expressions...>;
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
// check for at least one order expression
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one sort-order expression required in order_by()");
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
// check for duplicate order expressions
static_assert(not ::sqlpp::detail::has_duplicates<Expr...>::value, "at least one duplicate argument detected in order_by()");
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one sort-order expression required in order_by()");
// check for invalid order expressions
static_assert(::sqlpp::detail::and_t<is_sort_order_t, Expr...>::value, "at least one argument is not a sort order expression in order_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
template<typename E>
void add(E expr)
static_assert(::sqlpp::detail::all_t<is_sort_order_t, Expressions...>::value, "at least one argument is not a sort order expression in order_by()");
order_by_t(Expressions... expressions):
_expressions(expressions...)
{}
order_by_t(const order_by_t&) = default;
order_by_t(order_by_t&&) = default;
order_by_t& operator=(const order_by_t&) = default;
order_by_t& operator=(order_by_t&&) = default;
~order_by_t() = default;
template<typename Policies>
struct _methods_t
{
static_assert(is_sort_order_t<E>::value, "order_by arguments require to be sort-order expressions");
_dynamic_expressions.push_back(expr);
}
template<typename Expression>
void add_order_by_ntc(Expression expression)
{
add_order_by<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_order_by(Expression expression)
{
static_assert(_is_dynamic::value, "add_order_by must not be called for static order_by");
static_assert(is_sort_order_t<Expression>::value, "invalid expression argument in add_order_by()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_order_by()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_sort_order_t<Expression>>;
_add_order_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
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);
}
template<typename Expression>
void _add_order_by_impl(Expression expression, const std::false_type&);
};
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
template<typename Context, typename Database, typename... Expr>
struct interpreter_t<Context, order_by_t<Database, Expr...>>
struct no_order_by_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
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_order_by_t, T>;
template<typename... Args>
auto order_by(Args... args)
-> _new_statement_t<order_by_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), order_by_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_order_by(Args... args)
-> _new_statement_t<order_by_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::order_by_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, order_by_t<Database, Expressions...>>
{
using T = order_by_t<Database, Expr...>;
using T = order_by_t<Database, Expressions...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " ORDER BY ";
interpret_tuple(t._expressions, ',', context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << ',';
interpret_list(t._dynamic_expressions, ',', context);
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_order_by_t>
{
using T = no_order_by_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -24,47 +24,36 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_DETAIL_MAKE_FLAG_TUPLE_H
#define SQLPP_DETAIL_MAKE_FLAG_TUPLE_H
#ifndef SQLPP_VENDOR_POLICY_UPDATE_H
#define SQLPP_VENDOR_POLICY_UPDATE_H
#include <sqlpp11/vendor/wrong.h>
namespace sqlpp
{
namespace detail
namespace vendor
{
// accept select flags
template<typename Expr>
auto make_single_flag_tuple(Expr expr) -> typename std::enable_if<is_select_flag_t<Expr>::value, decltype(std::make_tuple(expr))>::type
template<typename Needle, typename Replacement>
struct policy_update_impl
{
return std::make_tuple(expr);
template<typename T>
using _policy_t = typename std::conditional<std::is_same<Needle, T>::value, Replacement, T>::type;
};
// ignore named expressions
template<typename Expr>
auto make_single_flag_tuple(Expr expr) -> typename std::enable_if<is_named_expression_t<Expr>::value, std::tuple<>>::type
template<typename T, typename Needle, typename Replacement>
using policy_update_t = typename policy_update_impl<Needle, Replacement>::template _policy_t<T>;
template<typename Original, typename Needle, typename Replacement>
struct update_policies_impl
{
return {};
using type = typename Original::template _policy_update_t<Needle, Replacement>;
};
// ignore tables
template<typename Tab>
auto make_single_flag_tuple(Tab tab) -> typename std::enable_if<is_table_t<Tab>::value, std::tuple<>>::type
{
return {};
};
// ignore tuples of expressions
template<typename... Expr>
auto make_single_flag_tuple(std::tuple<Expr...> t) -> std::tuple<>
{
return {};
};
template<typename... Expr>
auto make_flag_tuple(Expr... expr) -> decltype(std::tuple_cat(make_single_flag_tuple(expr)...))
{
return std::tuple_cat(make_single_flag_tuple(expr)...);
};
template<typename Original, typename Needle, typename Replacement>
using update_policies_t = typename update_policies_impl<Original, Needle, Replacement>::type;
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -29,7 +29,6 @@
#include <tuple>
#include <sqlpp11/result_row.h>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/table.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/vendor/field.h>
@ -37,7 +36,9 @@
#include <sqlpp11/vendor/select_pseudo_table.h>
#include <sqlpp11/vendor/named_interpretable.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/detail/copy_tuple_args.h>
namespace sqlpp
{
@ -68,7 +69,7 @@ namespace sqlpp
_names_t _dynamic_expression_names;
template<typename Expr>
void push_back(Expr expr)
void emplace_back(Expr expr)
{
_dynamic_expression_names.push_back(Expr::_name_t::_get_name());
_dynamic_columns.emplace_back(expr);
@ -89,9 +90,6 @@ namespace sqlpp
};
_names_t _dynamic_expression_names;
template<typename T>
void push_back(const T&) {}
static constexpr bool empty()
{
return true;
@ -99,7 +97,7 @@ namespace sqlpp
};
template<typename Context, typename Db>
struct interpreter_t<Context, dynamic_select_column_list<Db>>
struct serializer_t<Context, dynamic_select_column_list<Db>>
{
using T = dynamic_select_column_list<Db>;
@ -112,14 +110,14 @@ namespace sqlpp
first = false;
else
context << ',';
interpret(column, context);
serialize(column, context);
}
return context;
}
};
template<typename Context>
struct interpreter_t<Context, dynamic_select_column_list<void>>
struct serializer_t<Context, dynamic_select_column_list<void>>
{
using T = dynamic_select_column_list<void>;
@ -130,69 +128,165 @@ namespace sqlpp
};
template<typename Database, typename T>
// SELECT COLUMNS
template<typename Database, typename... Columns>
struct select_column_list_t
{
static_assert(::sqlpp::vendor::wrong_t<Database, T>::value, "invalid template argument for select_column_list");
};
template<typename Database, typename... NamedExpr>
struct select_column_list_t<Database, std::tuple<NamedExpr...>>
{
using _is_select_column_list = std::true_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<NamedExpr...>;
using _parameter_tuple_t = std::tuple<Columns...>;
using size = std::tuple_size<_parameter_tuple_t>;
// check for duplicate select expressions
static_assert(not ::sqlpp::detail::has_duplicates<NamedExpr...>::value, "at least one duplicate argument detected");
using _table_set = sqlpp::detail::make_joined_set_t<typename Columns::_table_set...>;
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected");
// check for invalid select expressions
template<typename T>
using is_valid_expression_t = std::integral_constant<bool, is_named_expression_t<T>::value or is_multi_column_t<T>::value>;
static_assert(::sqlpp::detail::and_t<is_valid_expression_t, NamedExpr...>::value, "at least one argument is not a named expression");
static_assert(::sqlpp::detail::all_t<is_valid_expression_t, Columns...>::value, "at least one argument is not a named expression");
// check for duplicate select expression names
static_assert(not ::sqlpp::detail::has_duplicates<typename NamedExpr::_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");
// provide type information for sub-selects that are used as expressions
struct _column_type {};
struct _value_type: ::sqlpp::detail::get_first_argument_if_unique<NamedExpr...>::_value_type
struct _value_type: ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_value_type
{
using _is_expression = typename std::conditional<sizeof...(NamedExpr) == 1, std::true_type, std::false_type>::type;
using _is_named_expression = typename std::conditional<sizeof...(NamedExpr) == 1, std::true_type, std::false_type>::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<NamedExpr...>::_name_t;
using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique<Columns...>::_name_t;
template<typename Db>
using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<make_field_t<NamedExpr>...>,
result_row_t<make_field_t<NamedExpr>...>>::type;
dynamic_result_row_t<Db, make_field_t<Columns>...>,
result_row_t<Db, make_field_t<Columns>...>>::type;
using _dynamic_names_t = typename dynamic_select_column_list<Database>::_names_t;
template <typename Select>
using _pseudo_table_t = select_pseudo_table_t<Select, NamedExpr...>;
using _pseudo_table_t = select_pseudo_table_t<Select, Columns...>;
template <typename Db>
using _dynamic_t = select_column_list_t<Db, std::tuple<NamedExpr...>>;
using _dynamic_t = select_column_list_t<Db, std::tuple<Columns...>>;
template<typename Expr>
void add(Expr namedExpr)
select_column_list_t(std::tuple<Columns...> columns):
_columns(columns)
{}
select_column_list_t(Columns... columns):
_columns(columns...)
{}
select_column_list_t(const select_column_list_t&) = default;
select_column_list_t(select_column_list_t&&) = default;
select_column_list_t& operator=(const select_column_list_t&) = default;
select_column_list_t& operator=(select_column_list_t&&) = default;
~select_column_list_t() = default;
static constexpr size_t static_size()
{
return size::value;
}
template<typename Policies>
struct _methods_t
{
static_assert(is_named_expression_t<Expr>::value, "select() arguments require to be named expressions");
static_assert(_is_dynamic::value, "cannot add columns to a non-dynamic column list");
_dynamic_columns.push_back(namedExpr);
}
template<typename NamedExpression>
void add_column_ntc(NamedExpression namedExpression)
{
add_column<NamedExpression, std::false_type>(namedExpression);
}
template<typename NamedExpression, typename TableCheckRequired = std::true_type>
void add_column(NamedExpression namedExpression)
{
static_assert(_is_dynamic::value, "add_column can only be called for dynamic_column");
static_assert(is_named_expression_t<NamedExpression>::value, "invalid named expression argument in add_column()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<NamedExpression>::value, "named expression uses tables unknown to this statement in add_column()");
using column_names = ::sqlpp::detail::make_type_set_t<typename Columns::_name_t...>;
static_assert(not ::sqlpp::detail::is_element_of<typename NamedExpression::_name_t, column_names>::value, "a column of this name is present in the select already");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t,
_is_dynamic,
is_named_expression_t<NamedExpression>
>;
_add_column_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename NamedExpression>
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);
}
template<typename NamedExpression>
void _add_column_impl(NamedExpression namedExpression, const std::false_type&);
};
const select_column_list_t& _column_list() const { return *this; }
_parameter_tuple_t _columns;
dynamic_select_column_list<Database> _dynamic_columns;
};
}
template<typename Context, typename Database, typename Tuple>
struct interpreter_t<Context, select_column_list_t<Database, Tuple>>
namespace detail
{
template<typename Database, typename... Columns>
using make_select_column_list_t =
copy_tuple_args_t<vendor::select_column_list_t, Database,
decltype(std::tuple_cat(as_tuple<Columns>::_(std::declval<Columns>())...))>;
}
namespace vendor
{
struct no_select_column_list_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
template<typename Db>
using _result_row_t = ::sqlpp::result_row_t<Db>;
using _dynamic_names_t = typename dynamic_select_column_list<void>::_names_t;
using _value_type = no_value_t;
struct _name_t {};
template<typename T>
struct _pseudo_table_t
{
static_assert(wrong_t<T>::value, "Cannot use a select as a table when no columns have been selected yet");
};
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_select_column_list_t, T>;
template<typename... Args>
auto columns(Args... args)
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), ::sqlpp::detail::make_select_column_list_t<void, Args...>{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} };
}
template<typename... Args>
auto dynamic_columns(Args... args)
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), ::sqlpp::detail::make_select_column_list_t<_database_t, Args...>{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Columns>
struct serializer_t<Context, select_column_list_t<Database, Columns...>>
{
using T = select_column_list_t<Database, Tuple>;
using T = select_column_list_t<Database, Columns...>;
static Context& _(const T& t, Context& context)
{
@ -202,7 +296,18 @@ namespace sqlpp
interpret_tuple(t._columns, ',', context);
if (T::size::value and not t._dynamic_columns.empty())
context << ',';
interpret(t._dynamic_columns, context);
serialize(t._dynamic_columns, context);
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_select_column_list_t>
{
using T = no_select_column_list_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,58 +27,118 @@
#ifndef SQLPP_VENDOR_SELECT_FLAG_LIST_H
#define SQLPP_VENDOR_SELECT_FLAG_LIST_H
#include <sqlpp11/select_fwd.h>
#include <tuple>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/select_flags.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <tuple>
#include <sqlpp11/vendor/policy_update.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename T>
// SELECT FLAGS
template<typename Database, typename... Flags>
struct select_flag_list_t
{
static_assert(::sqlpp::vendor::wrong_t<T>::value, "invalid argument for select_flag_list");
};
// select_flag_list_t
template<typename Database, typename... Flag>
struct select_flag_list_t<Database, std::tuple<Flag...>>
{
using _is_select_flag_list = std::true_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<Flag...>;
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;
// check for duplicate order expressions
static_assert(not ::sqlpp::detail::has_duplicates<Flag...>::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");
// check for invalid order expressions
static_assert(::sqlpp::detail::and_t<is_select_flag_t, Flag...>::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, "at least one argument is not a select flag in select flag list");
template<typename E>
void add(E expr)
select_flag_list_t(Flags... flags):
_flags(flags...)
{}
select_flag_list_t(const select_flag_list_t&) = default;
select_flag_list_t(select_flag_list_t&&) = default;
select_flag_list_t& operator=(const select_flag_list_t&) = default;
select_flag_list_t& operator=(select_flag_list_t&&) = default;
~select_flag_list_t() = default;
template<typename Policies>
struct _methods_t
{
static_assert(is_select_flag_t<E>::value, "flag arguments require to be select flags");
_dynamic_flags.emplace_back(expr);
}
template<typename Flag>
void add_flag_ntc(Flag flag)
{
add_flag<Flag, std::false_type>(flag);
}
template<typename Flag, typename TableCheckRequired = std::true_type>
void add_flag(Flag flag)
{
static_assert(_is_dynamic::value, "add_flag must not be called for static select flags");
static_assert(is_select_flag_t<Flag>::value, "invalid select flag argument in add_flag()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Flag>::value, "flag uses tables unknown to this statement in add_flag()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_select_flag_t<Flag>>;
_add_flag_impl(flag, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Flag>
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);
}
template<typename Flag>
void _add_flag_impl(Flag flag, const std::false_type&);
};
const select_flag_list_t& _flag_list() const { return *this; }
_parameter_tuple_t _flags;
vendor::interpretable_list_t<Database> _dynamic_flags;
};
template<typename Context, typename Database, typename... Flag>
struct interpreter_t<Context, select_flag_list_t<Database, std::tuple<Flag...>>>
struct no_select_flag_list_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
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_select_flag_list_t, T>;
template<typename... Args>
auto flags(Args... args)
-> _new_statement_t<select_flag_list_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), select_flag_list_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_flags(Args... args)
-> _new_statement_t<select_flag_list_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::select_flag_list_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Flags>
struct serializer_t<Context, select_flag_list_t<Database, Flags...>>
{
using T = select_flag_list_t<Database, std::tuple<Flag...>>;
using T = select_flag_list_t<Database, Flags...>;
static Context& _(const T& t, Context& context)
{
interpret_tuple(t._flags, ' ', context);
if (sizeof...(Flag))
if (sizeof...(Flags))
context << ' ';
interpret_list(t._dynamic_flags, ',', context);
if (not t._dynamic_flags.empty())
@ -86,6 +146,17 @@ namespace sqlpp
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_select_flag_list_t>
{
using T = no_select_flag_list_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -37,7 +37,11 @@ namespace sqlpp
{
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_update = std::true_type;
};
};
template<
@ -68,13 +72,13 @@ namespace sqlpp
namespace vendor
{
template<typename Context, typename Select, typename... NamedExpr>
struct interpreter_t<Context, select_pseudo_table_t<Select, NamedExpr...>>
struct serializer_t<Context, select_pseudo_table_t<Select, NamedExpr...>>
{
using T = select_pseudo_table_t<Select, NamedExpr...>;
static Context& _(const T& t, Context& context)
{
interpret(t._select, context);
serialize(t._select, context);
return context;
}
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -24,34 +24,25 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_SELECT_FWD_H
#define SQLPP_SELECT_FWD_H
#ifndef SQLPP_VENDOR_SERIALIZER_H
#define SQLPP_VENDOR_SERIALIZER_H
#include <type_traits>
#include <sqlpp11/vendor/wrong.h>
namespace sqlpp
{
namespace vendor
{
struct noop;
template<typename Context, typename T, typename Enable = void>
struct serializer_t
{
static void _(const T& t, Context& context)
{
static_assert(wrong_t<Context, T>::value, "missing serializer specialization");
}
};
}
// select flags
struct all_t;
struct distinct_t;
struct straight_join_t;
template<
typename Db,
typename Flags = vendor::noop,
typename ExpressionList = vendor::noop,
typename From = vendor::noop,
typename Where = vendor::noop,
typename GroupBy = vendor::noop,
typename Having = vendor::noop,
typename OrderBy = vendor::noop,
typename Limit = vendor::noop,
typename Offset = vendor::noop
>
struct select_t;
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,7 +27,7 @@
#ifndef SQLPP_SIMPLE_COLUMN_H
#define SQLPP_SIMPLE_COLUMN_H
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/vendor/serializer.h>
namespace sqlpp
{
@ -40,7 +40,7 @@ namespace sqlpp
};
template<typename Context, typename Column>
struct interpreter_t<Context, simple_column_t<Column>>
struct serializer_t<Context, simple_column_t<Column>>
{
using T = simple_column_t<Column>;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -24,53 +24,56 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_COLUMN_LIST_H
#define SQLPP_COLUMN_LIST_H
#ifndef SQLPP_VENDOR_SINGLE_TABLE_H
#define SQLPP_VENDOR_SINGLE_TABLE_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/simple_column.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
namespace vendor
{
template<typename... Columns>
struct column_list_t
// A SINGLE TABLE
template<typename Database, typename Table>
struct single_table_t
{
using _is_column_list = std::true_type;
using _parameter_tuple_t = std::tuple<Columns...>;
using _is_single_table = std::true_type;
// check for at least one order column
static_assert(sizeof...(Columns), "at least one column required in columns()");
static_assert(is_table_t<Table>::value, "argument has to be a table");
// check for duplicate columns
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected in columns()");
single_table_t(Table table):
_table(table)
{}
// check for invalid columns
static_assert(::sqlpp::detail::and_t<is_column_t, Columns...>::value, "at least one argument is not a column in columns()");
single_table_t(const single_table_t&) = default;
single_table_t(single_table_t&&) = default;
single_table_t& operator=(const single_table_t&) = default;
single_table_t& operator=(single_table_t&&) = default;
~single_table_t() = default;
// check for prohibited columns
static_assert(not ::sqlpp::detail::or_t<must_not_insert_t, Columns...>::value, "at least one column argument has a must_not_insert flag in its definition");
std::tuple<simple_column_t<Columns>...> _columns;
using _table_set = typename Table::_table_set;
Table _table;
};
template<typename Context, typename... Columns>
struct interpreter_t<Context, column_list_t<Columns...>>
struct no_single_table_t
{
using _table_set = ::sqlpp::detail::type_set<>;
};
// Interpreters
template<typename Context, typename Database, typename Table>
struct serializer_t<Context, single_table_t<Database, Table>>
{
using T = column_list_t<Columns...>;
using T = single_table_t<Database, Table>;
static Context& _(const T& t, Context& context)
{
context << " (";
interpret_tuple(t._columns, ",", context);
context << ")";
serialize(t._table, context);
return context;
}
};
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -36,6 +36,7 @@ namespace sqlpp
{
namespace vendor
{
// UPDATE ASSIGNMENTS
template<typename Database, typename... Assignments>
struct update_list_t
{
@ -43,32 +44,103 @@ namespace sqlpp
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...>;
// check for at least one order expression
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment expression required in set()");
// check for duplicate assignments
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
// check for invalid assignments
static_assert(::sqlpp::detail::and_t<is_assignment_t, Assignments...>::value, "at least one argument is not an assignment in set()");
static_assert(::sqlpp::detail::all_t<is_assignment_t, Assignments...>::value, "at least one argument is not an assignment in set()");
// check for prohibited assignments
static_assert(not ::sqlpp::detail::or_t<must_not_update_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()");
static_assert(not ::sqlpp::detail::any_t<must_not_update_t, typename Assignments::_column_t...>::value, "at least one assignment is prohibited by its column definition in set()");
template<typename Assignment>
void add(Assignment assignment)
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 _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(::sqlpp::detail::is_subset_of<_value_table_set, _column_table_set>::value, "set() contains values from foreign tables");
update_list_t(Assignments... assignments):
_assignments(assignments...)
{}
update_list_t(const update_list_t&) = default;
update_list_t(update_list_t&&) = default;
update_list_t& operator=(const update_list_t&) = default;
update_list_t& operator=(update_list_t&&) = default;
~update_list_t() = default;
template<typename Policies>
struct _methods_t
{
static_assert(is_assignment_t<Assignment>::value, "set() arguments require to be assigments");
static_assert(not must_not_update_t<typename Assignment::_column_t>::value, "set() argument must not be updated");
_dynamic_assignments.emplace_back(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)
{
static_assert(_is_dynamic::value, "add_set must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add_set()");
static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_column_t>::value, "add_set() argument must not be updated");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "assignment uses tables unknown to this statement in add_set()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t,
_is_dynamic,
is_assignment_t<Assignment>,
sqlpp::detail::not_t<must_not_update_t, typename Assignment::_column_t>>;
_add_set_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Assignment>
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);
}
template<typename Assignment>
void _add_set_impl(Assignment assignment, const std::false_type&);
};
_parameter_tuple_t _assignments;
typename vendor::interpretable_list_t<Database> _dynamic_assignments;
};
struct no_update_list_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
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_update_list_t, T>;
template<typename... Args>
auto set(Args... args)
-> _new_statement_t<update_list_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), update_list_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_set(Args... args)
-> _new_statement_t<update_list_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::update_list_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Assignments>
struct interpreter_t<Context, update_list_t<Database, Assignments...>>
struct serializer_t<Context, update_list_t<Database, Assignments...>>
{
using T = update_list_t<Database, Assignments...>;
@ -82,6 +154,18 @@ namespace sqlpp
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_update_list_t>
{
using T = no_update_list_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Roland Bock
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -31,55 +31,126 @@
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/vendor/policy_update.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... Table>
// USING
template<typename Database, typename... Tables>
struct using_t
{
using _is_using = std::true_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<Table...>;
using _parameter_tuple_t = std::tuple<Tables...>;
static_assert(_is_dynamic::value or sizeof...(Table), "at least one table argument required in using()");
static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()");
// check for duplicate arguments
static_assert(not ::sqlpp::detail::has_duplicates<Table...>::value, "at least one duplicate argument detected in using()");
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in using()");
// check for invalid arguments
static_assert(::sqlpp::detail::and_t<is_table_t, Table...>::value, "at least one argument is not an table in using()");
static_assert(::sqlpp::detail::all_t<is_table_t, Tables...>::value, "at least one argument is not an table in using()");
using _table_set = ::sqlpp::detail::make_joined_set_t<typename Tables::_table_set...>;
template<typename T>
void add(T table)
using_t(Tables... tables):
_tables(tables...)
{}
using_t(const using_t&) = default;
using_t(using_t&&) = default;
using_t& operator=(const using_t&) = default;
using_t& operator=(using_t&&) = default;
~using_t() = default;
template<typename Policies>
struct _methods_t
{
static_assert(is_table_t<T>::value, "using() arguments require to be tables");
_dynamic_tables.emplace_back(table);
}
template<typename Table>
void add_using(Table table)
{
static_assert(_is_dynamic::value, "add_using must not be called for static using()");
static_assert(is_table_t<Table>::value, "invalid table argument in add_using()");
using ok = ::sqlpp::detail::all_t<sqlpp::detail::identity_t, _is_dynamic, is_table_t<Table>>;
_add_using_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Table>
void _add_using_impl(Table table, const std::true_type&)
{
return static_cast<typename Policies::_statement_t*>(this)->_using._dynamic_tables.emplace_back(table);
}
template<typename Table>
void _add_using_impl(Table table, const std::false_type&);
};
_parameter_tuple_t _tables;
vendor::interpretable_list_t<Database> _dynamic_tables;
};
template<typename Context, typename Database, typename... Table>
struct interpreter_t<Context, using_t<Database, Table...>>
struct no_using_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
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_using_t, T>;
template<typename... Args>
auto using_(Args... args)
-> _new_statement_t<using_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), using_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_using(Args... args)
-> _new_statement_t<using_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::using_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, using_t<Database, Tables...>>
{
using T = using_t<Database, Table...>;
using T = using_t<Database, Tables...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Table) == 0 and t._dynamic_tables.empty())
if (sizeof...(Tables) == 0 and t._dynamic_tables.empty())
return context;
context << " USING ";
interpret_tuple(t._tables, ',', context);
if (sizeof...(Table) and not t._dynamic_tables.empty())
if (sizeof...(Tables) and not t._dynamic_tables.empty())
context << ',';
interpret_list(t._dynamic_tables, ',', context);
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_using_t>
{
using T = no_using_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}

Some files were not shown because too many files have changed in this diff Show More