0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-15 20:31:16 +08:00

We now have unique name representations per name

Before this, there could be multiple classes representing multiple id
columns. Now there is one class representing ALL the name "id". Very
important for analyzing potential name clashes.
This commit is contained in:
rbock 2014-11-30 19:40:34 +01:00
parent d34c22ca5a
commit 74cafe35dd
46 changed files with 425 additions and 133 deletions

View File

@ -3,6 +3,7 @@
#include <sqlpp11/table.h>
#include <sqlpp11/column_types.h>
#include <sqlpp11/char_sequence.h>
namespace test
{
@ -10,9 +11,10 @@ namespace test
{
struct Id
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "id"; }
static constexpr const char _literal[] = "id";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -25,9 +27,10 @@ namespace test
};
struct Name
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "name"; }
static constexpr const char _literal[] = "name";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -40,9 +43,10 @@ namespace test
};
struct Feature
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "feature"; }
static constexpr const char _literal[] = "feature";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -60,9 +64,10 @@ namespace test
TabPerson_::Name,
TabPerson_::Feature>
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "tab_person"; }
static constexpr const char _literal[] = "tab_person";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -76,9 +81,10 @@ namespace test
{
struct Id
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "id"; }
static constexpr const char _literal[] = "id";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -91,9 +97,10 @@ namespace test
};
struct Name
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "name"; }
static constexpr const char _literal[] = "name";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -106,9 +113,10 @@ namespace test
};
struct Fatal
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "fatal"; }
static constexpr const char _literal[] = "fatal";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -126,9 +134,10 @@ namespace test
TabFeature_::Name,
TabFeature_::Fatal>
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "tab_feature"; }
static constexpr const char _literal[] = "tab_feature";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -41,7 +41,7 @@ namespace sqlpp
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");
using _name_t = typename AliasProvider::_name_t;
using _alias_t = typename AliasProvider::_alias_t;
Expression _expression;
};
@ -57,7 +57,7 @@ namespace sqlpp
context << '(';
serialize(t._expression, context);
context << ") AS ";
context << T::_name_t::_get_name();
context << name_of<T>::char_ptr();
return context;
}
};

View File

@ -28,13 +28,15 @@
#define SQLPP_ALIAS_PROVIDER_H
#include <type_traits>
#include <sqlpp11/char_sequence.h>
#define SQLPP_ALIAS_PROVIDER(name) \
struct name##_t\
{\
struct _name_t\
struct _alias_t\
{\
static constexpr const char* _get_name() { return #name; }\
static constexpr const char _literal[] = #name;\
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;\
template<typename T>\
struct _member_t\
{\
@ -55,7 +57,7 @@ namespace sqlpp
};
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>
struct is_alias_provider_t<T, typename std::enable_if<std::is_class<typename T::_alias_t::template _member_t<int>>::value, void>::type>
{
static constexpr bool value = true;
};

View File

@ -28,6 +28,7 @@
#define SQLPP_ANY_H
#include <sqlpp11/boolean.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
@ -38,9 +39,10 @@ namespace sqlpp
using _traits = make_traits<value_type_of<Select>, tag::is_multi_expression>;
using _recursive_traits = make_recursive_traits<Select>;
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "ANY"; }
static constexpr const char _literal[] = "any_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -28,6 +28,7 @@
#define SQLPP_AVG_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp
{
@ -42,9 +43,10 @@ namespace sqlpp
static_assert(is_noop<Flag>::value or std::is_same<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");
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "AVG"; }
static constexpr const char _literal[] = "avg_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -106,12 +106,12 @@ namespace sqlpp
return { *static_cast<const Expr*>(this), rhs{t} };
}
is_null_t<true, Expr> is_null() const
is_null_t<Expr> is_null() const
{
return { *static_cast<const Expr*>(this) };
}
is_null_t<false, Expr> is_not_null() const
is_not_null_t<Expr> is_not_null() const
{
return { *static_cast<const Expr*>(this) };
}
@ -128,14 +128,14 @@ namespace sqlpp
// Hint: use value_list wrapper for containers...
template<typename... T>
in_t<true, Expr, wrap_operand_t<T>...> in(T... t) const
in_t<Expr, wrap_operand_t<T>...> in(T... t) const
{
static_assert(logic::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Expr*>(this), wrap_operand_t<T>{t}... };
}
template<typename... T>
in_t<false, Expr, wrap_operand_t<T>...> not_in(T... t) const
not_in_t<Expr, wrap_operand_t<T>...> not_in(T... t) const
{
static_assert(logic::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Expr*>(this), wrap_operand_t<T>{t}... };

View File

@ -0,0 +1,56 @@
/*
* 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_CHAR_SEQUENCE_H
#define SQLPP_CHAR_SEQUENCE_H
#include <sqlpp11/detail/index_sequence.h>
namespace sqlpp
{
template<char... Cs> struct char_sequence
{
static const char* char_ptr()
{
static char s[] = {Cs...};
return s;
};
};
template<std::size_t N, const char (&s) [N], typename T>
struct make_char_sequence_impl;
template<std::size_t N, const char (&s) [N], size_t... i>
struct make_char_sequence_impl<N, s, sqlpp::detail::index_sequence<i...>>
{
using type = char_sequence<s[i]...>;
};
template<std::size_t N, const char (&Input) [N]>
using make_char_sequence = typename make_char_sequence_impl<sizeof(Input), Input, sqlpp::detail::make_index_sequence<sizeof(Input)>>::type;
}
#endif

View File

@ -66,7 +66,7 @@ namespace sqlpp
using _spec_t = ColumnSpec;
using _table = Table;
using _name_t = typename _spec_t::_name_t;
using _alias_t = typename _spec_t::_alias_t;
template<typename T>
using _is_valid_operand = is_valid_operand<value_type_of<ColumnSpec>, T>;
@ -78,11 +78,6 @@ namespace sqlpp
column_t& operator=(column_t&&) = default;
~column_t() = default;
static constexpr const char* _get_name()
{
return _name_t::_get_name();
}
template<typename alias_provider>
expression_alias_t<column_t, alias_provider> as(const alias_provider&) const
{
@ -120,7 +115,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << T::_table::_name_t::_get_name() << '.' << T::_name_t::_get_name();
context << name_of<typename T::_table>::char_ptr() << '.' << name_of<T>::char_ptr();
return context;
}
};

View File

@ -28,6 +28,7 @@
#define SQLPP_CONCAT_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/logic.h>
@ -45,9 +46,10 @@ namespace sqlpp
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
static_assert(logic::all_t<is_text_t<First>::value, is_text_t<Args>::value...>::value, "at least one non-text argument detected in concat()");
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "CONCAT"; }
static constexpr const char _literal[] = "concat_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -27,6 +27,7 @@
#ifndef SQLPP_COUNT_H
#define SQLPP_COUNT_H
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/select_flags.h>
#include <sqlpp11/integral.h>
@ -52,9 +53,10 @@ namespace sqlpp
static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "count() used with flag other than 'distinct'");
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "COUNT"; }
static constexpr const char _literal[] = "count_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -40,7 +40,7 @@ namespace sqlpp
static_assert(is_database<Db>::value, "Db parameter of eval has to be a database connection");
static_assert(is_expression_t<Expr>::value, "Expression parameter of eval has to be an sqlpp expression or a string");
static_assert(required_tables_of<Expr>::size::value == 0, "Expression cannot be used in eval because it requires tables");
using _name_type = alias::a_t::_name_t;
using _name_type = alias::a_t::_alias_t;
using _value_type = value_type_of<Expr>;
using _field_spec = field_spec_t<_name_type, _value_type, true, false>;
using type = result_field_t<_value_type, Db, _field_spec>;

View File

@ -27,6 +27,7 @@
#ifndef SQLPP_EXISTS_H
#define SQLPP_EXISTS_H
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/boolean.h>
namespace sqlpp
@ -41,9 +42,10 @@ namespace sqlpp
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "EXISTS"; }
static constexpr const char _literal[] = "exists_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -40,7 +40,7 @@ namespace sqlpp
>;
using _recursive_traits = make_recursive_traits<>;
using _name_t = NameType;
using _alias_t = NameType;
};
template<typename AliasProvider, typename FieldSpecTuple>
@ -56,7 +56,7 @@ namespace sqlpp
static constexpr bool _can_be_null = can_be_null_t<NamedExpr>::value;
static constexpr bool _depends_on_outer_table = detail::make_intersect_set_t<required_tables_of<NamedExpr>, typename Select::_used_outer_tables>::size::value > 0;
using type = field_spec_t<typename NamedExpr::_name_t,
using type = field_spec_t<typename NamedExpr::_alias_t,
value_type_of<NamedExpr>,
logic::any_t<_can_be_null, _depends_on_outer_table>::value,
null_is_trivial_value_t<NamedExpr>::value>;

View File

@ -77,7 +77,7 @@ namespace sqlpp
static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
using _known_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table
using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
static_assert(not detail::is_element_of<typename Table::_name_t, _known_table_names>::value, "Must not use the same table name twice in from()");
static_assert(not detail::is_element_of<typename Table::_alias_t, _known_table_names>::value, "Must not use the same table name twice in from()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Table>;
_serialize_check::_();

View File

@ -31,7 +31,9 @@
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/column_types.h>
#include <sqlpp11/in.h>
#include <sqlpp11/not_in.h>
#include <sqlpp11/is_null.h>
#include <sqlpp11/is_not_null.h>
#include <sqlpp11/value_type.h>
#include <sqlpp11/exists.h>
#include <sqlpp11/any.h>
@ -129,7 +131,7 @@ namespace sqlpp
template<typename T>
constexpr const char* get_sql_name(const T&)
{
return T::_name_t::_get_name();
return name_of<T>::char_ptr();
}

View File

@ -28,26 +28,27 @@
#define SQLPP_IN_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/boolean.h>
#include <sqlpp11/in_fwd.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
template<bool NotInverted, typename Operand, typename... Args>
template<typename Operand, typename... Args>
struct in_t:
public expression_operators<in_t<NotInverted, Operand, Args...>, boolean>,
public alias_operators<in_t<NotInverted, Operand, Args...>>
public expression_operators<in_t<Operand, Args...>, boolean>,
public alias_operators<in_t<Operand, Args...>>
{
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand, Args...>;
static constexpr bool _inverted = not NotInverted;
static_assert(sizeof...(Args) > 0, "in() requires at least one argument");
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; }
static constexpr const char _literal[] = "in_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -70,16 +71,16 @@ namespace sqlpp
std::tuple<Args...> _args;
};
template<typename Context, bool NotInverted, typename Operand, typename... Args>
struct serializer_t<Context, in_t<NotInverted, Operand, Args...>>
template<typename Context, typename Operand, typename... Args>
struct serializer_t<Context, in_t<Operand, Args...>>
{
using _serialize_check = serialize_check_of<Context, Args...>;
using T = in_t<NotInverted, Operand, Args...>;
using T = in_t<Operand, Args...>;
static Context& _(const T& t, Context& context)
{
serialize(t._operand, context);
context << (t._inverted ? " NOT IN(" : " IN(");
context << " IN(";
if (sizeof...(Args) == 1)
serialize(std::get<0>(t._args), context); // FIXME: this is a bit of a hack until there is a better overall strategy for using braces
// see https://github.com/rbock/sqlpp11/issues/18

View File

@ -29,8 +29,10 @@
namespace sqlpp
{
template<bool NotInverted, typename Operand, typename... Args>
template<typename Operand, typename... Args>
struct in_t;
template<typename Operand, typename... Args>
struct not_in_t;
}

View File

@ -44,7 +44,7 @@ namespace sqlpp
struct insert_t: public statement_name_t<insert_name_t>
{
using _traits = make_traits<no_value_t, tag::is_return_value>;
struct _name_t {};
struct _alias_t {};
template<typename Statement>
struct _result_methods_t

View File

@ -63,7 +63,7 @@ namespace sqlpp
using _data_t = into_data_t<Database, Table>;
struct _name_t {};
struct _alias_t {};
// Member implementation with data and methods
template <typename Policies>

View File

@ -0,0 +1,85 @@
/*
* 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_IS_NOT_NULL_H
#define SQLPP_IS_NOT_NULL_H
#include <sqlpp11/boolean.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
template<typename Operand>
struct is_not_null_t:
public expression_operators<is_not_null_t<Operand>, boolean>,
public alias_operators<is_not_null_t<Operand>>
{
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand>;
struct _alias_t
{
static constexpr const char _literal[] = "is_not_null_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
T is_not_null;
};
};
is_not_null_t(Operand operand):
_operand(operand)
{}
is_not_null_t(const is_not_null_t&) = default;
is_not_null_t(is_not_null_t&&) = default;
is_not_null_t& operator=(const is_not_null_t&) = default;
is_not_null_t& operator=(is_not_null_t&&) = default;
~is_not_null_t() = default;
Operand _operand;
};
template<typename Context, typename Operand>
struct serializer_t<Context, is_not_null_t<Operand>>
{
using _serialize_check = serialize_check_of<Context, Operand>;
using T = is_not_null_t<Operand>;
static Context& _(const T& t, Context& context)
{
serialize(t._operand, context);
context << " IS NOT NULL";
return context;
}
};
}
#endif

View File

@ -29,27 +29,27 @@
#include <sqlpp11/boolean.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
template<bool NotInverted, typename Operand>
template<typename Operand>
struct is_null_t:
public expression_operators<is_null_t<NotInverted, Operand>, boolean>,
public alias_operators<is_null_t<NotInverted, Operand>>
public expression_operators<is_null_t<Operand>, boolean>,
public alias_operators<is_null_t<Operand>>
{
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand>;
static constexpr bool _inverted = not NotInverted;
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return _inverted ? "IS NOT NULL" : "IS NULL"; }
static constexpr const char _literal[] = "is_nnull_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
T in;
T is_null;
};
};
@ -66,16 +66,16 @@ namespace sqlpp
Operand _operand;
};
template<typename Context, bool NotInverted, typename Operand>
struct serializer_t<Context, is_null_t<NotInverted, Operand>>
template<typename Context, typename Operand>
struct serializer_t<Context, is_null_t<Operand>>
{
using _serialize_check = serialize_check_of<Context, Operand>;
using T = is_null_t<NotInverted, Operand>;
using T = is_null_t<Operand>;
static Context& _(const T& t, Context& context)
{
serialize(t._operand, context);
context << (t._inverted ? " IS NOT NULL" : " IS NULL");
context << " IS NULL";
return context;
}
};

View File

@ -29,8 +29,10 @@
namespace sqlpp
{
template<bool NotInverted, typename Operand>
template<typename Operand>
struct is_null_t;
template<typename Operand>
struct is_not_null_t;
}
#endif

View File

@ -29,6 +29,7 @@
#include <sqlpp11/boolean.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
@ -41,9 +42,10 @@ namespace sqlpp
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand, Pattern>;
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "LIKE"; }
static constexpr const char _literal[] = "like_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -28,6 +28,7 @@
#define SQLPP_MAX_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp
{
@ -39,9 +40,10 @@ namespace sqlpp
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr, aggregate_function>;
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "MAX"; }
static constexpr const char _literal[] = "max_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -28,6 +28,7 @@
#define SQLPP_MIN_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp
{
@ -39,9 +40,10 @@ namespace sqlpp
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr, aggregate_function>;
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "MIN"; }
static constexpr const char _literal[] = "min_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -77,7 +77,7 @@ namespace sqlpp
static_assert(logic::all_t<is_selectable_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
using _name_t = typename AliasProvider::_name_t;
using _alias_t = typename AliasProvider::_alias_t;
multi_column_alias_t(multi_column_t<void, Columns...> multi_column):
_columns(multi_column._columns)

View File

@ -30,6 +30,7 @@
#include <memory>
#include <sqlpp11/serializer_context.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp
{
@ -111,7 +112,7 @@ namespace sqlpp
std::string _get_name() const
{
return T::_name_t::_get_name();
return name_of<T>::char_ptr();
}
T _t;

View File

@ -39,7 +39,7 @@ namespace sqlpp
using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>;
struct _name_t {};
struct _alias_t {};
template<typename Statement>
struct _result_methods_t

96
include/sqlpp11/not_in.h Normal file
View File

@ -0,0 +1,96 @@
/*
* 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_NOT_IN_H
#define SQLPP_NOT_IN_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/boolean.h>
#include <sqlpp11/in_fwd.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
template<typename Operand, typename... Args>
struct not_in_t:
public expression_operators<not_in_t<Operand, Args...>, boolean>,
public alias_operators<not_in_t<Operand, Args...>>
{
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand, Args...>;
static_assert(sizeof...(Args) > 0, "not_in() requires at least one argument");
struct _alias_t
{
static constexpr const char _literal[] = "not_in_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
T not_in;
};
};
not_in_t(Operand operand, Args... args):
_operand(operand),
_args(args...)
{}
not_in_t(const not_in_t&) = default;
not_in_t(not_in_t&&) = default;
not_in_t& operator=(const not_in_t&) = default;
not_in_t& operator=(not_in_t&&) = default;
~not_in_t() = default;
Operand _operand;
std::tuple<Args...> _args;
};
template<typename Context, typename Operand, typename... Args>
struct serializer_t<Context, not_in_t<Operand, Args...>>
{
using _serialize_check = serialize_check_of<Context, Args...>;
using T = not_in_t<Operand, Args...>;
static Context& _(const T& t, Context& context)
{
serialize(t._operand, context);
context << " NOT IN(";
if (sizeof...(Args) == 1)
serialize(std::get<0>(t._args), context); // FIXME: this is a bit of a hack until there is a better overall strategy for using braces
// see https://github.com/rbock/sqlpp11/issues/18
else
interpret_tuple(t._args, ',', context);
context << ')';
return context;
}
};
}
#endif

View File

@ -44,7 +44,7 @@ namespace sqlpp
struct remove_t: public statement_name_t<remove_name_t>
{
using _traits = make_traits<no_value_t, tag::is_return_value>;
struct _name_t {};
struct _alias_t {};
template<typename Statement>
struct _result_methods_t

View File

@ -186,7 +186,7 @@ namespace sqlpp
using _traits = make_traits<text, tag::is_noop, tag::can_be_null, tag::null_is_trivial_value>;
using _recursive_traits = make_recursive_traits<>;
struct _name_t {};
struct _alias_t {};
};
using _field_type = result_field_t<text, Db, _field_spec_t>;

View File

@ -48,14 +48,14 @@ namespace sqlpp
struct select_traits
{
using _traits = make_traits<no_value_t, tag::is_select_column_list, tag::is_return_value>;
struct _name_t {};
struct _alias_t {};
};
template<typename Column>
struct select_traits<Column>
{
using _traits = make_traits<value_type_of<Column>, tag::is_select_column_list, tag::is_return_value, tag::is_expression, tag::is_selectable>;
using _name_t = typename Column::_name_t;
using _alias_t = typename Column::_alias_t;
};
}
@ -69,7 +69,7 @@ namespace sqlpp
template<typename Expr>
void emplace_back(Expr expr)
{
_dynamic_expression_names.push_back(Expr::_name_t::_get_name());
_dynamic_expression_names.push_back(name_of<Expr>::char_ptr());
_dynamic_columns.emplace_back(expr);
}
@ -166,7 +166,7 @@ namespace sqlpp
using _traits = typename detail::select_traits<Columns...>::_traits;
using _recursive_traits = make_recursive_traits<Columns...>;
using _name_t = typename detail::select_traits<Columns...>::_name_t;
using _alias_t = typename detail::select_traits<Columns...>::_alias_t;
using _is_dynamic = is_database<Database>;
@ -191,8 +191,8 @@ namespace sqlpp
static_assert(_is_dynamic::value, "selected_columns::add() can only be called for dynamic_column");
static_assert(is_selectable_t<NamedExpression>::value, "invalid named expression argument in selected_columns::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<NamedExpression>::value, "named expression uses tables unknown to this statement in selected_columns::add()");
using column_names = detail::make_type_set_t<typename Columns::_name_t...>;
static_assert(not detail::is_element_of<typename NamedExpression::_name_t, column_names>::value, "a column of this name is present in the select already");
using column_names = detail::make_type_set_t<typename Columns::_alias_t...>;
static_assert(not detail::is_element_of<typename NamedExpression::_alias_t, column_names>::value, "a column of this name is present in the select already");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, NamedExpression>;
_serialize_check::_();
@ -351,7 +351,7 @@ namespace sqlpp
using _traits = make_traits<no_value_t, tag::is_noop, tag::is_missing>;
using _recursive_traits = make_recursive_traits<>;
struct _name_t {};
struct _alias_t {};
// Data
using _data_t = no_data_t;
@ -431,7 +431,7 @@ namespace sqlpp
-> _new_statement_t<_check<Args...>, select_column_list_t<Database, Args...>>
{
static_assert(not detail::has_duplicates<Args...>::value, "at least one duplicate argument detected");
static_assert(not detail::has_duplicates<typename Args::_name_t...>::value, "at least one duplicate name detected");
static_assert(not detail::has_duplicates<typename Args::_alias_t...>::value, "at least one duplicate name detected");
return { static_cast<const derived_statement_t<Policies>&>(*this), typename select_column_list_t<Database, Args...>::_data_t{args} };
}

View File

@ -35,7 +35,7 @@ namespace sqlpp
template<typename Select, typename NamedExpr>
struct select_column_spec_t
{
using _name_t = typename NamedExpr::_name_t;
using _alias_t = typename NamedExpr::_alias_t;
static constexpr bool _can_be_null = can_be_null_t<NamedExpr>::value;
static constexpr bool _depends_on_outer_table = detail::make_intersect_set_t<required_tables_of<NamedExpr>, typename Select::_used_outer_tables>::size::value > 0;

View File

@ -35,7 +35,8 @@ namespace sqlpp
template<typename Column>
struct simple_column_t
{
Column _column;
using _column_t = Column;
_column_t _column;
using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>;
@ -49,7 +50,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << t._column._get_name();
context << name_of<typename T::_column_t>::char_ptr();
return context;
}
};

View File

@ -65,7 +65,7 @@ namespace sqlpp
using _data_t = single_table_data_t<Database, Table>;
struct _name_t {};
struct _alias_t {};
// Member implementation with data and methods
template <typename Policies>

View File

@ -29,6 +29,7 @@
#include <sqlpp11/boolean.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp
{
@ -38,9 +39,10 @@ namespace sqlpp
using _traits = make_traits<value_type_of<Select>, tag::is_multi_expression>;
using _recursive_traits = make_recursive_traits<Select>;
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "SOME"; }
static constexpr const char _literal[] = "some_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -180,7 +180,7 @@ namespace sqlpp
using _recursive_traits = typename _policies_t::_recursive_traits;
using _used_outer_tables = typename _policies_t::_all_provided_outer_tables;
using _name_t = typename _result_type_provider::_name_t;
using _alias_t = typename _result_type_provider::_alias_t;
// Constructors
statement_t()

View File

@ -28,6 +28,7 @@
#define SQLPP_SUM_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp
{
@ -42,9 +43,10 @@ namespace sqlpp
static_assert(is_noop<Flag>::value or std::is_same<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");
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "SUM"; }
static constexpr const char _literal[] = "sum_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -113,7 +113,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << T::_name_t::_get_name();
context << name_of<T>::char_ptr();
return context;
}
};

View File

@ -54,7 +54,7 @@ namespace sqlpp
static_assert(required_tables_of<Table>::size::value == 0, "table aliases must not depend on external tables");
using _name_t = typename AliasProvider::_name_t;
using _alias_t = typename AliasProvider::_alias_t;
using _column_tuple_t = std::tuple<column_t<AliasProvider, ColumnSpec>...>;
table_alias_t(Table table):
@ -74,7 +74,7 @@ namespace sqlpp
{
context << "(";
serialize(t._table, context);
context << ") AS " << T::_name_t::_get_name();
context << ") AS " << name_of<T>::char_ptr();
return context;
}
};

View File

@ -201,7 +201,10 @@ namespace sqlpp
using recursive_tags_of = typename T::_recursive_traits::_tags;
template<typename T>
using name_of = typename T::_name_t;
using alias_of = typename T::_alias_t;
template<typename T>
using name_of = typename T::_alias_t::_name_t;
template<typename ValueType, typename... Tags>
struct make_traits
@ -239,7 +242,7 @@ namespace sqlpp
};
template<typename NameProvider, typename Member>
using member_t = typename NameProvider::_name_t::template _member_t<Member>;
using member_t = typename NameProvider::_alias_t::template _member_t<Member>;
template<typename Policies>
using derived_statement_t = typename Policies::_statement_t;

View File

@ -44,7 +44,7 @@ namespace sqlpp
struct update_t: public statement_name_t<update_name_t>
{
using _traits = make_traits<no_value_t, tag::is_return_value>;
struct _name_t {};
struct _alias_t {};
template<typename Statement>
struct _result_methods_t

View File

@ -35,8 +35,10 @@ namespace sqlpp
{
struct unusable_pseudo_column_t
{
struct _name_t
struct _alias_t
{
static constexpr const char _literal[] = "pseudo_column";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -53,7 +55,11 @@ namespace sqlpp
using _provided_outer_tables = detail::type_set<verbatim_table_t>;
};
struct _name_t {};
struct _alias_t
{
static constexpr const char _literal[] = "verbatim_table"; // FIXME need to use alias for verbatim table
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
};
verbatim_table_t(std::string representation):
_representation(representation)

View File

@ -118,6 +118,7 @@ print('#define '+get_include_guard_name(namespace, pathToHeader), file=header)
print('', file=header)
print('#include <' + INCLUDE + '/table.h>', file=header)
print('#include <' + INCLUDE + '/column_types.h>', file=header)
print('#include <' + INCLUDE + '/char_sequence.h>', file=header)
print('', file=header)
print('namespace ' + namespace, file=header)
print('{', file=header)
@ -143,9 +144,10 @@ for tableCreation in tableCreations:
columnCanBeNull = not column.notNull
print(' struct ' + columnClass, file=header)
print(' {', file=header)
print(' struct _name_t', file=header)
print(' struct _alias_t', file=header)
print(' {', file=header)
print(' static constexpr const char* _get_name() { return "' + sqlColumnName + '"; }', file=header)
print(' static constexpr const char _literal[] = "' + sqlColumnName + '";', file=header)
print(' using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;', file=header)
print(' template<typename T>', file=header)
print(' struct _member_t', file=header)
print(' {', file=header)
@ -154,7 +156,6 @@ for tableCreation in tableCreations:
print(' const T& operator()() const { return ' + columnMember + '; }', file=header)
print(' };', file=header)
print(' };', file=header)
#print(sqlColumnType)
traitslist = [NAMESPACE + '::' + types[sqlColumnType]];
requireInsert = True
if column.hasAutoValue:
@ -175,9 +176,10 @@ for tableCreation in tableCreations:
print(' struct ' + tableClass + ': ' + NAMESPACE + '::table_t<' + tableTemplateParameters + '>', file=header)
print(' {', file=header)
print(' struct _name_t', file=header)
print(' struct _alias_t', file=header)
print(' {', file=header)
print(' static constexpr const char* _get_name() { return "' + sqlTableName + '"; }', file=header)
print(' static constexpr const char _literal[] = "' + sqlTableName + '";', file=header)
print(' using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;', file=header)
print(' template<typename T>', file=header)
print(' struct _member_t', file=header)
print(' {', file=header)

View File

@ -3,6 +3,7 @@
#include <sqlpp11/table.h>
#include <sqlpp11/column_types.h>
#include <sqlpp11/char_sequence.h>
namespace test
{
@ -10,9 +11,10 @@ namespace test
{
struct Delta
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "delta"; }
static constexpr const char _literal[] = "delta";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -25,9 +27,10 @@ namespace test
};
struct Epsilon
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "epsilon"; }
static constexpr const char _literal[] = "epsilon";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -40,9 +43,10 @@ namespace test
};
struct Omega
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "omega"; }
static constexpr const char _literal[] = "omega";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -60,9 +64,10 @@ namespace test
TabFoo_::Epsilon,
TabFoo_::Omega>
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "tab_foo"; }
static constexpr const char _literal[] = "tab_foo";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -76,9 +81,10 @@ namespace test
{
struct Alpha
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "alpha"; }
static constexpr const char _literal[] = "alpha";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -91,9 +97,10 @@ namespace test
};
struct Beta
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "beta"; }
static constexpr const char _literal[] = "beta";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -106,9 +113,10 @@ namespace test
};
struct Gamma
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "gamma"; }
static constexpr const char _literal[] = "gamma";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -121,9 +129,10 @@ namespace test
};
struct Delta
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "delta"; }
static constexpr const char _literal[] = "delta";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
@ -142,9 +151,10 @@ namespace test
TabBar_::Gamma,
TabBar_::Delta>
{
struct _name_t
struct _alias_t
{
static constexpr const char* _get_name() { return "tab_bar"; }
static constexpr const char _literal[] = "tab_bar";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{

View File

@ -41,7 +41,6 @@ int main()
test::TabFoo f;
test::TabBar t;
select(t.alpha).flags(sqlpp::all).from(t);
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
{
int64_t a = row.alpha;