mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Merge branch 'feature/with_cte' into develop
This commit is contained in:
commit
80bc0fcf5e
53
.clang-format
Normal file
53
.clang-format
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -2
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
AlignEscapedNewlinesLeft: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: true
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
BreakBeforeBinaryOperators: false
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BinPackParameters: false
|
||||||
|
ColumnLimit: 160
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
IndentFunctionDeclarationAfterType: false
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
NamespaceIndentation: All
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: false
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerAlignment: Left
|
||||||
|
SpacesBeforeTrailingComments: 2
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
Standard: Cpp11
|
||||||
|
IndentWidth: 2
|
||||||
|
TabWidth: 2
|
||||||
|
UseTab: Never
|
||||||
|
BreakBeforeBraces: Allman
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
DisableFormat: false
|
@ -36,6 +36,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
|||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
||||||
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}")
|
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}")
|
||||||
endif ()
|
endif ()
|
||||||
|
set(CMAKE_CXX_FLAGS "-Wconversion -Wpedantic ${CMAKE_CXX_FLAGS}")
|
||||||
|
|
||||||
set(include_dir "${PROJECT_SOURCE_DIR}/include")
|
set(include_dir "${PROJECT_SOURCE_DIR}/include")
|
||||||
file(GLOB_RECURSE sqlpp_headers "${include_dir}/*.h")
|
file(GLOB_RECURSE sqlpp_headers "${include_dir}/*.h")
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
static constexpr bool some_condition = true;
|
static constexpr bool some_condition = true;
|
||||||
static constexpr bool some_other_condition = false;
|
static constexpr bool some_other_condition = false;
|
||||||
|
|
||||||
SQLPP_ALIAS_PROVIDER(cheesecake);
|
SQLPP_ALIAS_PROVIDER(cheesecake)
|
||||||
|
|
||||||
MockDb db;
|
MockDb db;
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ int main()
|
|||||||
.from(p.join(x).on(p.feature == x.cheesecake))
|
.from(p.join(x).on(p.feature == x.cheesecake))
|
||||||
.where(true)))
|
.where(true)))
|
||||||
{
|
{
|
||||||
int id = row.id;
|
int64_t id = row.id;
|
||||||
std::string name = row.name;
|
std::string name = row.name;
|
||||||
std::string x_name = row.x.name;
|
std::string x_name = row.x.name;
|
||||||
int cheesecake = row.x.cheesecake;
|
int cheesecake = row.x.cheesecake;
|
||||||
|
@ -62,35 +62,35 @@ namespace sqlpp
|
|||||||
static constexpr bool value = true;
|
static constexpr bool value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace alias
|
inline namespace alias
|
||||||
{
|
{
|
||||||
SQLPP_ALIAS_PROVIDER(a);
|
SQLPP_ALIAS_PROVIDER(a)
|
||||||
SQLPP_ALIAS_PROVIDER(b);
|
SQLPP_ALIAS_PROVIDER(b)
|
||||||
SQLPP_ALIAS_PROVIDER(c);
|
SQLPP_ALIAS_PROVIDER(c)
|
||||||
SQLPP_ALIAS_PROVIDER(d);
|
SQLPP_ALIAS_PROVIDER(d)
|
||||||
SQLPP_ALIAS_PROVIDER(e);
|
SQLPP_ALIAS_PROVIDER(e)
|
||||||
SQLPP_ALIAS_PROVIDER(f);
|
SQLPP_ALIAS_PROVIDER(f)
|
||||||
SQLPP_ALIAS_PROVIDER(g);
|
SQLPP_ALIAS_PROVIDER(g)
|
||||||
SQLPP_ALIAS_PROVIDER(h);
|
SQLPP_ALIAS_PROVIDER(h)
|
||||||
SQLPP_ALIAS_PROVIDER(i);
|
SQLPP_ALIAS_PROVIDER(i)
|
||||||
SQLPP_ALIAS_PROVIDER(j);
|
SQLPP_ALIAS_PROVIDER(j)
|
||||||
SQLPP_ALIAS_PROVIDER(k);
|
SQLPP_ALIAS_PROVIDER(k)
|
||||||
SQLPP_ALIAS_PROVIDER(l);
|
SQLPP_ALIAS_PROVIDER(l)
|
||||||
SQLPP_ALIAS_PROVIDER(m);
|
SQLPP_ALIAS_PROVIDER(m)
|
||||||
SQLPP_ALIAS_PROVIDER(n);
|
SQLPP_ALIAS_PROVIDER(n)
|
||||||
SQLPP_ALIAS_PROVIDER(o);
|
SQLPP_ALIAS_PROVIDER(o)
|
||||||
SQLPP_ALIAS_PROVIDER(p);
|
SQLPP_ALIAS_PROVIDER(p)
|
||||||
SQLPP_ALIAS_PROVIDER(q);
|
SQLPP_ALIAS_PROVIDER(q)
|
||||||
SQLPP_ALIAS_PROVIDER(s);
|
SQLPP_ALIAS_PROVIDER(s)
|
||||||
SQLPP_ALIAS_PROVIDER(t);
|
SQLPP_ALIAS_PROVIDER(t)
|
||||||
SQLPP_ALIAS_PROVIDER(u);
|
SQLPP_ALIAS_PROVIDER(u)
|
||||||
SQLPP_ALIAS_PROVIDER(v);
|
SQLPP_ALIAS_PROVIDER(v)
|
||||||
SQLPP_ALIAS_PROVIDER(w);
|
SQLPP_ALIAS_PROVIDER(w)
|
||||||
SQLPP_ALIAS_PROVIDER(x);
|
SQLPP_ALIAS_PROVIDER(x)
|
||||||
SQLPP_ALIAS_PROVIDER(y);
|
SQLPP_ALIAS_PROVIDER(y)
|
||||||
SQLPP_ALIAS_PROVIDER(z);
|
SQLPP_ALIAS_PROVIDER(z)
|
||||||
SQLPP_ALIAS_PROVIDER(left);
|
SQLPP_ALIAS_PROVIDER(left)
|
||||||
SQLPP_ALIAS_PROVIDER(right);
|
SQLPP_ALIAS_PROVIDER(right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,11 +54,13 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct _recursive_traits
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
using _parameters = std::tuple<>;
|
using _required_ctes = detail::type_set<>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
|
using _required_tables = detail::type_set<Table>;
|
||||||
using _provided_tables = detail::type_set<>;
|
using _provided_tables = detail::type_set<>;
|
||||||
using _provided_outer_tables = detail::type_set<>;
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
using _required_tables = detail::type_set<Table>;
|
|
||||||
using _extra_tables = detail::type_set<>;
|
using _extra_tables = detail::type_set<>;
|
||||||
|
using _parameters = std::tuple<>;
|
||||||
using _tags = typename std::conditional<column_spec_can_be_null_t<ColumnSpec>::value,
|
using _tags = typename std::conditional<column_spec_can_be_null_t<ColumnSpec>::value,
|
||||||
detail::type_set<tag::can_be_null>,
|
detail::type_set<tag::can_be_null>,
|
||||||
detail::type_set<>>::type;
|
detail::type_set<>>::type;
|
||||||
|
@ -41,6 +41,8 @@ namespace sqlpp
|
|||||||
using _traits = make_traits<integral, tag::is_expression, tag::is_selectable>;
|
using _traits = make_traits<integral, tag::is_expression, tag::is_selectable>;
|
||||||
struct _recursive_traits
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
|
using _required_ctes = required_ctes_of<Expr>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
using _required_tables = required_tables_of<Expr>;
|
using _required_tables = required_tables_of<Expr>;
|
||||||
using _provided_tables = provided_tables_of<Expr>;
|
using _provided_tables = provided_tables_of<Expr>;
|
||||||
using _provided_outer_tables = provided_outer_tables_of<Expr>;
|
using _provided_outer_tables = provided_outer_tables_of<Expr>;
|
||||||
|
286
include/sqlpp11/cte.h
Normal file
286
include/sqlpp11/cte.h
Normal file
@ -0,0 +1,286 @@
|
|||||||
|
/*
|
||||||
|
* 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_CTE_H
|
||||||
|
#define SQLPP_CTE_H
|
||||||
|
|
||||||
|
#include <sqlpp11/table_ref.h>
|
||||||
|
#include <sqlpp11/select_flags.h>
|
||||||
|
#include <sqlpp11/result_row.h>
|
||||||
|
#include <sqlpp11/statement_fwd.h>
|
||||||
|
#include <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/parameter_list.h>
|
||||||
|
#include <sqlpp11/expression.h>
|
||||||
|
#include <sqlpp11/interpret_tuple.h>
|
||||||
|
#include <sqlpp11/interpretable_list.h>
|
||||||
|
#include <sqlpp11/logic.h>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
template<typename Flag, typename Lhs, typename Rhs>
|
||||||
|
struct cte_union_t
|
||||||
|
{
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Lhs>, required_ctes_of<Rhs>>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
|
using _required_tables = detail::type_set<>;
|
||||||
|
using _provided_tables = detail::type_set<>;
|
||||||
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
using _parameters = detail::make_parameter_tuple_t<parameters_of<Lhs>, parameters_of<Rhs>>;
|
||||||
|
using _tags = detail::type_set<>;
|
||||||
|
};
|
||||||
|
|
||||||
|
cte_union_t(Lhs lhs, Rhs rhs):
|
||||||
|
_lhs(lhs),
|
||||||
|
_rhs(rhs)
|
||||||
|
{}
|
||||||
|
|
||||||
|
cte_union_t(const cte_union_t&) = default;
|
||||||
|
cte_union_t(cte_union_t&&) = default;
|
||||||
|
cte_union_t& operator=(const cte_union_t&) = default;
|
||||||
|
cte_union_t& operator=(cte_union_t&&) = default;
|
||||||
|
~cte_union_t() = default;
|
||||||
|
|
||||||
|
Lhs _lhs;
|
||||||
|
Rhs _rhs;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Interpreters
|
||||||
|
template<typename Context, typename Flag, typename Lhs, typename Rhs>
|
||||||
|
struct serializer_t<Context, cte_union_t<Flag, Lhs, Rhs>>
|
||||||
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
|
||||||
|
using T = cte_union_t<Flag, Lhs, Rhs>;
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
context << '(';
|
||||||
|
serialize(t._lhs, context);
|
||||||
|
context << ") UNION ";
|
||||||
|
serialize(Flag{}, context);
|
||||||
|
context << " (";
|
||||||
|
serialize(t._rhs, context);
|
||||||
|
context << ')';
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
|
struct cte_t;
|
||||||
|
|
||||||
|
template<typename AliasProvider>
|
||||||
|
struct cte_ref_t;
|
||||||
|
|
||||||
|
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
|
auto from_table(cte_t<AliasProvider, Statement, FieldSpecs...> t) -> cte_ref_t<AliasProvider>
|
||||||
|
{
|
||||||
|
return cte_ref_t<AliasProvider>{};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
|
struct from_table_impl<cte_t<AliasProvider, Statement, FieldSpecs...>>
|
||||||
|
{
|
||||||
|
using type = cte_ref_t<AliasProvider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename FieldSpec>
|
||||||
|
struct cte_column_spec_t
|
||||||
|
{
|
||||||
|
using _alias_t = typename FieldSpec::_alias_t;
|
||||||
|
|
||||||
|
using _traits = make_traits<value_type_of<FieldSpec>,
|
||||||
|
tag::must_not_insert,
|
||||||
|
tag::must_not_update,
|
||||||
|
tag_if<tag::can_be_null, column_spec_can_be_null_t<FieldSpec>::value>
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename AliasProvider, typename Statement, typename ResultRow>
|
||||||
|
struct make_cte_impl
|
||||||
|
{
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
|
struct make_cte_impl<AliasProvider, Statement, result_row_t<void, FieldSpecs...>>
|
||||||
|
{
|
||||||
|
using type = cte_t<AliasProvider, Statement, FieldSpecs...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename AliasProvider, typename Statement>
|
||||||
|
using make_cte_t = typename make_cte_impl<AliasProvider, Statement, get_result_row_t<Statement>>::type;
|
||||||
|
|
||||||
|
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
|
struct cte_t: public member_t<cte_column_spec_t<FieldSpecs>, column_t<AliasProvider, cte_column_spec_t<FieldSpecs>>>...
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_cte, tag::is_table>; // FIXME: is table? really?
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Statement>, detail::type_set<AliasProvider>>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
|
using _required_tables = detail::type_set<>;
|
||||||
|
using _provided_tables = detail::type_set<>;
|
||||||
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
using _parameters = parameters_of<Statement>;
|
||||||
|
using _tags = detail::type_set<>;
|
||||||
|
};
|
||||||
|
using _alias_t = typename AliasProvider::_alias_t;
|
||||||
|
constexpr static bool _is_recursive = detail::is_element_of<AliasProvider, required_ctes_of<Statement>>::value;
|
||||||
|
|
||||||
|
using _column_tuple_t = std::tuple<column_t<AliasProvider, cte_column_spec_t<FieldSpecs>>...>;
|
||||||
|
|
||||||
|
template<typename... T>
|
||||||
|
using _check = logic::all_t<is_statement_t<T>::value...>;
|
||||||
|
|
||||||
|
using _result_row_t = result_row_t<void, FieldSpecs...>;
|
||||||
|
|
||||||
|
template<typename Rhs>
|
||||||
|
auto union_distinct(Rhs rhs) const
|
||||||
|
-> typename std::conditional<_check<Rhs>::value, cte_t<AliasProvider, cte_union_t<distinct_t, Statement, Rhs>, FieldSpecs...>, bad_statement>::type
|
||||||
|
{
|
||||||
|
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
||||||
|
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
||||||
|
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
||||||
|
|
||||||
|
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
|
||||||
|
|
||||||
|
return _union_impl<void, distinct_t>(_check<Rhs>{}, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Rhs>
|
||||||
|
auto union_all(Rhs rhs) const
|
||||||
|
-> typename std::conditional<_check<Rhs>::value, cte_t<AliasProvider, cte_union_t<all_t, Statement, Rhs>, FieldSpecs...>, bad_statement>::type
|
||||||
|
{
|
||||||
|
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
||||||
|
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
||||||
|
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
||||||
|
|
||||||
|
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
|
||||||
|
|
||||||
|
return _union_impl<all_t>(_check<Rhs>{}, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename Flag, typename Rhs>
|
||||||
|
auto _union_impl(const std::false_type&, Rhs rhs) const
|
||||||
|
-> bad_statement;
|
||||||
|
|
||||||
|
template<typename Flag, typename Rhs>
|
||||||
|
auto _union_impl(const std::true_type&, Rhs rhs) const
|
||||||
|
-> cte_t<AliasProvider, cte_union_t<Flag, Statement, Rhs>, FieldSpecs...>
|
||||||
|
{
|
||||||
|
return cte_union_t<Flag, Statement, Rhs>{_statement, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
cte_t(Statement statement): _statement(statement){}
|
||||||
|
cte_t(const cte_t&) = default;
|
||||||
|
cte_t(cte_t&&) = default;
|
||||||
|
cte_t& operator=(const cte_t&) = default;
|
||||||
|
cte_t& operator=(cte_t&&) = default;
|
||||||
|
~cte_t() = default;
|
||||||
|
|
||||||
|
Statement _statement;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Context, typename AliasProvider, typename Statement, typename... ColumnSpecs>
|
||||||
|
struct serializer_t<Context, cte_t<AliasProvider, Statement, ColumnSpecs...>>
|
||||||
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, Statement>;
|
||||||
|
using T = cte_t<AliasProvider, Statement, ColumnSpecs...>;
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
context << name_of<T>::char_ptr() << " AS (";
|
||||||
|
serialize(t._statement, context);
|
||||||
|
context << ")";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// The cte_t is displayed as AliasProviderName except within the with:
|
||||||
|
// - the with needs the
|
||||||
|
// AliasProviderName AS (ColumnNames) (select/union)
|
||||||
|
// The result row of the select should not have dynamic parts
|
||||||
|
template<typename AliasProvider>
|
||||||
|
struct cte_ref_t
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_cte, tag::is_table>; // FIXME: is table? really?
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _required_ctes = detail::make_type_set_t<AliasProvider>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
|
using _required_tables = detail::type_set<>;
|
||||||
|
using _provided_tables = detail::type_set<AliasProvider>;
|
||||||
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
using _parameters = std::tuple<>;
|
||||||
|
using _tags = detail::type_set<>;
|
||||||
|
};
|
||||||
|
|
||||||
|
using _alias_t = typename AliasProvider::_alias_t;
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
auto as(Statement statement)
|
||||||
|
-> make_cte_t<AliasProvider, Statement>
|
||||||
|
{
|
||||||
|
static_assert(required_tables_of<Statement>::size::value == 0, "common table expression must not use unknown tables");
|
||||||
|
static_assert(not detail::is_element_of<AliasProvider, required_ctes_of<Statement>>::value, "common table expression must not self-reference in the first part, use union_all/union_distinct for recursion");
|
||||||
|
static_assert(is_static_result_row_t<get_result_row_t<Statement>>::value, "ctes must not have dynamically added columns");
|
||||||
|
|
||||||
|
return { statement };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Context, typename AliasProvider>
|
||||||
|
struct serializer_t<Context, cte_ref_t<AliasProvider>>
|
||||||
|
{
|
||||||
|
using _serialize_check = consistent_t;
|
||||||
|
using T = cte_ref_t<AliasProvider>;
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
context << name_of<T>::char_ptr();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename AliasProvider>
|
||||||
|
auto cte(const AliasProvider&)
|
||||||
|
-> cte_ref_t<AliasProvider>
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -37,20 +37,20 @@ namespace sqlpp
|
|||||||
typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::true_type&)
|
typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::true_type&)
|
||||||
{
|
{
|
||||||
return term;
|
return term;
|
||||||
};
|
}
|
||||||
|
|
||||||
template<typename Target, typename Statement, typename Term>
|
template<typename Target, typename Statement, typename Term>
|
||||||
typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::false_type&)
|
typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::false_type&)
|
||||||
{
|
{
|
||||||
return Target::_get_member(statement)._data;
|
return Target::_get_member(statement)._data;
|
||||||
};
|
}
|
||||||
|
|
||||||
// Returns a statement's term either by picking the term from the statement or using the new term
|
// Returns a statement's term either by picking the term from the statement or using the new term
|
||||||
template<typename Target, typename Statement, typename Term>
|
template<typename Target, typename Statement, typename Term>
|
||||||
typename Target::_data_t pick_arg(Statement statement, Term term)
|
typename Target::_data_t pick_arg(Statement statement, Term term)
|
||||||
{
|
{
|
||||||
return pick_arg_impl<Target>(statement, term, std::is_same<typename Target::_data_t, Term>());
|
return pick_arg_impl<Target>(statement, term, std::is_same<typename Target::_data_t, Term>());
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,11 +54,13 @@ namespace sqlpp
|
|||||||
using _traits = make_traits<no_value_t, tag::is_extra_tables>;
|
using _traits = make_traits<no_value_t, tag::is_extra_tables>;
|
||||||
struct _recursive_traits
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
using _parameters = std::tuple<>;
|
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Tables>...>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
using _required_tables = detail::type_set<>;
|
using _required_tables = detail::type_set<>;
|
||||||
using _provided_outer_tables = detail::type_set<>;
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
using _provided_tables = detail::type_set<>;
|
using _provided_tables = detail::type_set<>;
|
||||||
using _extra_tables = detail::type_set<Tables...>;
|
using _extra_tables = detail::type_set<Tables...>;
|
||||||
|
using _parameters = std::tuple<>;
|
||||||
using _tags = detail::type_set<>;
|
using _tags = detail::type_set<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#ifndef SQLPP_FROM_H
|
#ifndef SQLPP_FROM_H
|
||||||
#define SQLPP_FROM_H
|
#define SQLPP_FROM_H
|
||||||
|
|
||||||
|
#include <sqlpp11/table_ref.h>
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/no_data.h>
|
#include <sqlpp11/no_data.h>
|
||||||
#include <sqlpp11/interpretable_list.h>
|
#include <sqlpp11/interpretable_list.h>
|
||||||
@ -90,7 +91,7 @@ namespace sqlpp
|
|||||||
template<typename Table>
|
template<typename Table>
|
||||||
void _add_impl(Table table, const std::true_type&)
|
void _add_impl(Table table, const std::true_type&)
|
||||||
{
|
{
|
||||||
return _data._dynamic_tables.emplace_back(table);
|
return _data._dynamic_tables.emplace_back(from_table(table));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Table>
|
template<typename Table>
|
||||||
@ -164,7 +165,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
template<typename... Tables>
|
template<typename... Tables>
|
||||||
auto from(Tables... tables) const
|
auto from(Tables... tables) const
|
||||||
-> _new_statement_t<_check<Tables...>, from_t<void, Tables...>>
|
-> _new_statement_t<_check<Tables...>, from_t<void, from_table_t<Tables>...>>
|
||||||
{
|
{
|
||||||
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
|
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
|
||||||
static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
|
static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
|
||||||
@ -173,7 +174,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
template<typename... Tables>
|
template<typename... Tables>
|
||||||
auto dynamic_from(Tables... tables) const
|
auto dynamic_from(Tables... tables) const
|
||||||
-> _new_statement_t<_check<Tables...>, from_t<_database_t, Tables...>>
|
-> _new_statement_t<_check<Tables...>, from_t<_database_t, from_table_t<Tables>...>>
|
||||||
{
|
{
|
||||||
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
|
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
|
||||||
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
|
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
|
||||||
@ -187,7 +188,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
template<typename Database, typename... Tables>
|
template<typename Database, typename... Tables>
|
||||||
auto _from_impl(const std::true_type&, Tables... tables) const
|
auto _from_impl(const std::true_type&, Tables... tables) const
|
||||||
-> _new_statement_t<std::true_type, from_t<Database, Tables...>>
|
-> _new_statement_t<std::true_type, from_t<Database, from_table_t<Tables>...>>
|
||||||
{
|
{
|
||||||
static_assert(required_tables_of<from_t<Database, Tables...>>::size::value == 0, "at least one table depends on another table in from()");
|
static_assert(required_tables_of<from_t<Database, Tables...>>::size::value == 0, "at least one table depends on another table in from()");
|
||||||
|
|
||||||
@ -197,7 +198,7 @@ namespace sqlpp
|
|||||||
static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()");
|
static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()");
|
||||||
static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()");
|
static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()");
|
||||||
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), from_data_t<Database, Tables...>{tables...} };
|
return { static_cast<const derived_statement_t<Policies>&>(*this), from_data_t<Database, from_table_t<Tables>...>{from_table(tables)...} };
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -211,7 +211,7 @@ namespace sqlpp
|
|||||||
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
|
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
|
||||||
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), group_by_data_t<Database, Expressions...>{expressions...} };
|
return { static_cast<const derived_statement_t<Policies>&>(*this), group_by_data_t<Database, Expressions...>{expressions...} };
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ namespace sqlpp
|
|||||||
static void _()
|
static void _()
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "insert values required, e.g. set(...) or default_values()");
|
static_assert(wrong_t<T>::value, "insert values required, e.g. set(...) or default_values()");
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// NO INSERT COLUMNS/VALUES YET
|
// NO INSERT COLUMNS/VALUES YET
|
||||||
|
@ -54,7 +54,9 @@ namespace sqlpp
|
|||||||
// See also: "http://stackoverflow.com/questions/6245735/pretty-print-stdtuple/6245777#6245777"
|
// See also: "http://stackoverflow.com/questions/6245735/pretty-print-stdtuple/6245777#6245777"
|
||||||
// Beware of gcc-bug: "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253", otherwise an empty swallow struct could be used
|
// Beware of gcc-bug: "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253", otherwise an empty swallow struct could be used
|
||||||
using swallow = int[];
|
using swallow = int[];
|
||||||
(void) swallow{(interpret_tuple_element(std::get<Is>(t), separator, context, useBraces, Is), 0)...};
|
(void) swallow{
|
||||||
|
0, //workaround against -Wpedantic GCC warning "zero-size array 'int [0]'"
|
||||||
|
(interpret_tuple_element(std::get<Is>(t), separator, context, useBraces, Is), 0)...};
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,8 @@ namespace sqlpp
|
|||||||
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
|
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
|
||||||
struct _recursive_traits
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
|
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Lhs>, required_ctes_of<Rhs>>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
using _required_tables = detail::make_joined_set_t<required_tables_of<Lhs>, required_tables_of<Rhs>>;
|
using _required_tables = detail::make_joined_set_t<required_tables_of<Lhs>, required_tables_of<Rhs>>;
|
||||||
using _provided_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
using _provided_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
||||||
using _provided_outer_tables = typename JoinType::template _provided_outer_tables<Lhs, Rhs>;
|
using _provided_outer_tables = typename JoinType::template _provided_outer_tables<Lhs, Rhs>;
|
||||||
|
@ -211,7 +211,7 @@ namespace sqlpp
|
|||||||
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
|
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
|
||||||
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), order_by_data_t<Database, Expressions...>{expressions...} };
|
return { static_cast<const derived_statement_t<Policies>&>(*this), order_by_data_t<Database, Expressions...>{expressions...} };
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,11 +40,13 @@ namespace sqlpp
|
|||||||
using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>;
|
using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>;
|
||||||
struct _recursive_traits
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
using _parameters = std::tuple<parameter_t>;
|
using _required_ctes = detail::type_set<>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
|
using _required_tables = detail::type_set<>;
|
||||||
using _provided_tables = detail::type_set<>;
|
using _provided_tables = detail::type_set<>;
|
||||||
using _provided_outer_tables = detail::type_set<>;
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
using _required_tables = detail::type_set<>;
|
|
||||||
using _extra_tables = detail::type_set<>;
|
using _extra_tables = detail::type_set<>;
|
||||||
|
using _parameters = std::tuple<parameter_t>;
|
||||||
using _tags = detail::type_set<tag::can_be_null>;
|
using _tags = detail::type_set<tag::can_be_null>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,11 +83,13 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct _recursive_traits
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
using _parameters = std::tuple<>;
|
using _required_ctes = detail::type_set<>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
|
using _required_tables = detail::type_set<>;
|
||||||
using _provided_tables = detail::type_set<>;
|
using _provided_tables = detail::type_set<>;
|
||||||
using _provided_outer_tables = detail::type_set<>;
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
using _required_tables = detail::type_set<>;
|
|
||||||
using _extra_tables = detail::type_set<>;
|
using _extra_tables = detail::type_set<>;
|
||||||
|
using _parameters = std::tuple<>;
|
||||||
using _tags = typename std::conditional<column_spec_can_be_null_t<_field_spec_t>::value,
|
using _tags = typename std::conditional<column_spec_can_be_null_t<_field_spec_t>::value,
|
||||||
detail::type_set<tag::can_be_null>,
|
detail::type_set<tag::can_be_null>,
|
||||||
detail::type_set<>>::type;
|
detail::type_set<>>::type;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#define SQLPP_RESULT_ROW_H
|
#define SQLPP_RESULT_ROW_H
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <sqlpp11/result_row_fwd.h>
|
||||||
#include <sqlpp11/field_spec.h>
|
#include <sqlpp11/field_spec.h>
|
||||||
#include <sqlpp11/text.h>
|
#include <sqlpp11/text.h>
|
||||||
#include <sqlpp11/detail/field_index_sequence.h>
|
#include <sqlpp11/detail/field_index_sequence.h>
|
||||||
@ -265,6 +266,21 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_static_result_row_impl
|
||||||
|
{
|
||||||
|
using type = std::false_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Db, typename... FieldSpecs>
|
||||||
|
struct is_static_result_row_impl<result_row_t<Db, FieldSpecs...>>
|
||||||
|
{
|
||||||
|
using type = std::true_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using is_static_result_row_t = typename is_static_result_row_impl<T>::type;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
39
include/sqlpp11/result_row_fwd.h
Normal file
39
include/sqlpp11/result_row_fwd.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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_RESULT_ROW_FWD_H
|
||||||
|
#define SQLPP_RESULT_ROW_FWD_H
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
template<typename Db, typename... FieldSpecs>
|
||||||
|
struct result_row_t;
|
||||||
|
|
||||||
|
template<typename Db, typename... FieldSpecs>
|
||||||
|
struct dynamic_result_row_t;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include <sqlpp11/noop.h>
|
#include <sqlpp11/noop.h>
|
||||||
#include <sqlpp11/connection.h>
|
#include <sqlpp11/connection.h>
|
||||||
|
#include <sqlpp11/with.h>
|
||||||
#include <sqlpp11/select_flag_list.h>
|
#include <sqlpp11/select_flag_list.h>
|
||||||
#include <sqlpp11/select_column_list.h>
|
#include <sqlpp11/select_column_list.h>
|
||||||
#include <sqlpp11/from.h>
|
#include <sqlpp11/from.h>
|
||||||
@ -69,6 +70,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
template<typename Database>
|
template<typename Database>
|
||||||
using blank_select_t = statement_t<Database,
|
using blank_select_t = statement_t<Database,
|
||||||
|
no_with_t,
|
||||||
select_t,
|
select_t,
|
||||||
no_select_flag_list_t,
|
no_select_flag_list_t,
|
||||||
no_select_column_list_t,
|
no_select_column_list_t,
|
||||||
|
@ -286,6 +286,7 @@ namespace sqlpp
|
|||||||
template<typename AliasProvider>
|
template<typename AliasProvider>
|
||||||
_alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const
|
_alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const
|
||||||
{
|
{
|
||||||
|
consistency_check_t<_statement_t>::_();
|
||||||
static_assert(_statement_t::_can_be_used_as_table(), "statement cannot be used as table, e.g. due to missing tables");
|
static_assert(_statement_t::_can_be_used_as_table(), "statement cannot be used as table, e.g. due to missing tables");
|
||||||
static_assert(logic::none_t<is_multi_column_t<Columns>::value...>::value, "cannot use multi-columns in sub selects");
|
static_assert(logic::none_t<is_multi_column_t<Columns>::value...>::value, "cannot use multi-columns in sub selects");
|
||||||
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
|
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
|
||||||
@ -340,7 +341,7 @@ namespace sqlpp
|
|||||||
auto tuple_merge(Columns... columns) -> decltype(std::tuple_cat(as_tuple<Columns>::_(columns)...))
|
auto tuple_merge(Columns... columns) -> decltype(std::tuple_cat(as_tuple<Columns>::_(columns)...))
|
||||||
{
|
{
|
||||||
return std::tuple_cat(as_tuple<Columns>::_(columns)...);
|
return std::tuple_cat(as_tuple<Columns>::_(columns)...);
|
||||||
};
|
}
|
||||||
|
|
||||||
template<typename Database, typename... Columns>
|
template<typename Database, typename... Columns>
|
||||||
using make_select_column_list_t =
|
using make_select_column_list_t =
|
||||||
|
@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
|
// FIXME: We might use field specs here (same as with cte)
|
||||||
|
//
|
||||||
// provide type information for sub-selects that are used as named expressions or tables
|
// provide type information for sub-selects that are used as named expressions or tables
|
||||||
template<typename Select, typename NamedExpr>
|
template<typename Select, typename NamedExpr>
|
||||||
struct select_column_spec_t
|
struct select_column_spec_t
|
||||||
|
@ -44,6 +44,17 @@ namespace sqlpp
|
|||||||
template<typename Db, typename... Policies>
|
template<typename Db, typename... Policies>
|
||||||
struct statement_t;
|
struct statement_t;
|
||||||
|
|
||||||
|
struct assert_no_unknown_ctes_t
|
||||||
|
{
|
||||||
|
using type = std::false_type;
|
||||||
|
|
||||||
|
template<typename T = void>
|
||||||
|
static void _()
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<T>::value, "one clause requires common table expressions which are otherwise not known in the statement");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct assert_no_unknown_tables_t
|
struct assert_no_unknown_tables_t
|
||||||
{
|
{
|
||||||
using type = std::false_type;
|
using type = std::false_type;
|
||||||
@ -84,6 +95,8 @@ namespace sqlpp
|
|||||||
template<typename Needle, typename Replacement>
|
template<typename Needle, typename Replacement>
|
||||||
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
|
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
|
||||||
|
|
||||||
|
using _all_required_ctes = detail::make_joined_set_t<required_ctes_of<Policies>...>;
|
||||||
|
using _all_provided_ctes = detail::make_joined_set_t<provided_ctes_of<Policies>...>;
|
||||||
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
||||||
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
||||||
using _all_provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Policies>...>;
|
using _all_provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Policies>...>;
|
||||||
@ -94,12 +107,21 @@ namespace sqlpp
|
|||||||
template<typename Expression>
|
template<typename Expression>
|
||||||
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
|
||||||
|
|
||||||
|
template<template<typename> class Predicate>
|
||||||
|
using any_t = logic::any_t<Predicate<Policies>::value...>;
|
||||||
|
|
||||||
// The tables not covered by the from.
|
// The tables not covered by the from.
|
||||||
using _required_tables = detail::make_difference_set_t<
|
using _required_tables = detail::make_difference_set_t<
|
||||||
_all_required_tables,
|
_all_required_tables,
|
||||||
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
|
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
// The common table expressions not covered by the with.
|
||||||
|
using _required_ctes = detail::make_difference_set_t<
|
||||||
|
_all_required_ctes,
|
||||||
|
_all_provided_ctes
|
||||||
|
>;
|
||||||
|
|
||||||
using _result_type_provider = detail::get_last_if<is_return_value_t, noop, Policies...>;
|
using _result_type_provider = detail::get_last_if<is_return_value_t, noop, Policies...>;
|
||||||
|
|
||||||
struct _result_methods_t: public _result_type_provider::template _result_methods_t<_statement_t>
|
struct _result_methods_t: public _result_type_provider::template _result_methods_t<_statement_t>
|
||||||
@ -108,10 +130,12 @@ namespace sqlpp
|
|||||||
|
|
||||||
// A select can be used as a pseudo table if
|
// A select can be used as a pseudo table if
|
||||||
// - at least one column is selected
|
// - at least one column is selected
|
||||||
// - the select is complete (leaks no tables)
|
// - the select is complete (leaks no table requirements)
|
||||||
static constexpr bool _can_be_used_as_table()
|
static constexpr bool _can_be_used_as_table()
|
||||||
{
|
{
|
||||||
return is_select_column_list_t<_result_type_provider>::value and _required_tables::size::value == 0
|
return has_result_row_t<_statement_t>::value
|
||||||
|
and _required_tables::size::value == 0
|
||||||
|
and _all_provided_ctes::size::value == 0 // a sub-select must not contain a WITH
|
||||||
? true
|
? true
|
||||||
: false;
|
: false;
|
||||||
}
|
}
|
||||||
@ -133,6 +157,8 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct _recursive_traits
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
|
using _required_ctes = statement_policies_t::_required_ctes;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
using _required_tables = statement_policies_t::_required_tables;
|
using _required_tables = statement_policies_t::_required_tables;
|
||||||
using _provided_tables = detail::type_set<>;
|
using _provided_tables = detail::type_set<>;
|
||||||
using _provided_outer_tables = detail::type_set<>;
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
@ -143,6 +169,8 @@ namespace sqlpp
|
|||||||
detail::type_set<>>::type;
|
detail::type_set<>>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using _cte_check = typename std::conditional<_required_ctes::size::value == 0,
|
||||||
|
consistent_t, assert_no_unknown_ctes_t>::type;
|
||||||
using _table_check = typename std::conditional<_required_tables::size::value == 0,
|
using _table_check = typename std::conditional<_required_tables::size::value == 0,
|
||||||
consistent_t, assert_no_unknown_tables_t>::type;
|
consistent_t, assert_no_unknown_tables_t>::type;
|
||||||
using _parameter_check = typename std::conditional<std::tuple_size<typename _recursive_traits::_parameters>::value == 0,
|
using _parameter_check = typename std::conditional<std::tuple_size<typename _recursive_traits::_parameters>::value == 0,
|
||||||
@ -158,13 +186,15 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
using _policies_t = typename detail::statement_policies_t<Db, Policies...>;
|
using _policies_t = typename detail::statement_policies_t<Db, Policies...>;
|
||||||
|
|
||||||
using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
||||||
typename _policies_t::_parameter_check,
|
|
||||||
typename Policies::template _base_t<_policies_t>::_consistency_check...,
|
typename Policies::template _base_t<_policies_t>::_consistency_check...,
|
||||||
typename _policies_t::_table_check>;
|
typename _policies_t::_table_check>;
|
||||||
using _prepare_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
using _prepare_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
||||||
typename Policies::template _base_t<_policies_t>::_consistency_check...,
|
typename _policies_t::_cte_check,
|
||||||
typename _policies_t::_table_check>;
|
_consistency_check>;
|
||||||
|
using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
||||||
|
typename _policies_t::_parameter_check,
|
||||||
|
_prepare_check>;
|
||||||
|
|
||||||
using _result_type_provider = typename _policies_t::_result_type_provider;
|
using _result_type_provider = typename _policies_t::_result_type_provider;
|
||||||
template<typename Composite>
|
template<typename Composite>
|
||||||
|
@ -48,11 +48,13 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct _recursive_traits
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
using _parameters = std::tuple<>;
|
using _required_ctes = detail::type_set<>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
using _required_tables = detail::type_set<>;
|
using _required_tables = detail::type_set<>;
|
||||||
using _provided_tables = detail::type_set<Table>;
|
using _provided_tables = detail::type_set<Table>;
|
||||||
using _provided_outer_tables = detail::type_set<>;
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
using _extra_tables = detail::type_set<>;
|
using _extra_tables = detail::type_set<>;
|
||||||
|
using _parameters = std::tuple<>;
|
||||||
using _tags = detail::type_set<>;
|
using _tags = detail::type_set<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,11 +44,13 @@ namespace sqlpp
|
|||||||
|
|
||||||
struct _recursive_traits
|
struct _recursive_traits
|
||||||
{
|
{
|
||||||
using _parameters = std::tuple<>;
|
using _required_ctes = required_ctes_of<Table>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
using _required_tables = detail::type_set<>;
|
using _required_tables = detail::type_set<>;
|
||||||
using _provided_tables = detail::type_set<AliasProvider>;
|
using _provided_tables = detail::type_set<AliasProvider>;
|
||||||
using _provided_outer_tables = detail::type_set<>;
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
using _extra_tables = detail::type_set<>;
|
using _extra_tables = detail::type_set<>;
|
||||||
|
using _parameters = std::tuple<>;
|
||||||
using _tags = detail::type_set<>;
|
using _tags = detail::type_set<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
55
include/sqlpp11/table_ref.h
Normal file
55
include/sqlpp11/table_ref.h
Normal 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_TABLE_REF_H
|
||||||
|
#define SQLPP_TABLE_REF_H
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
auto from_table(T t) -> T
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct from_table_impl
|
||||||
|
{
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
template<typename T>
|
||||||
|
using from_table_t = typename from_table_impl<T>::type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
auto table_ref(T t) -> T
|
||||||
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -90,7 +90,7 @@ namespace sqlpp
|
|||||||
transaction_t<Db> start_transaction(Db& db, bool report_unfinished_transaction = report_auto_rollback)
|
transaction_t<Db> start_transaction(Db& db, bool report_unfinished_transaction = report_auto_rollback)
|
||||||
{
|
{
|
||||||
return { db, report_unfinished_transaction };
|
return { db, report_unfinished_transaction };
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,7 +39,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct can_be_null{};
|
struct can_be_null{};
|
||||||
struct contains_aggregate_function{};
|
struct contains_aggregate_function{};
|
||||||
};
|
}
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@ -74,7 +74,7 @@ namespace sqlpp
|
|||||||
namespace tag
|
namespace tag
|
||||||
{
|
{
|
||||||
struct is_expression{};
|
struct is_expression{};
|
||||||
};
|
}
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename T, typename Enable = void>
|
template<typename T, typename Enable = void>
|
||||||
@ -92,7 +92,7 @@ namespace sqlpp
|
|||||||
namespace tag\
|
namespace tag\
|
||||||
{\
|
{\
|
||||||
struct name{};\
|
struct name{};\
|
||||||
};\
|
}\
|
||||||
namespace detail\
|
namespace detail\
|
||||||
{\
|
{\
|
||||||
template<typename T, typename Enable = void>\
|
template<typename T, typename Enable = void>\
|
||||||
@ -103,68 +103,71 @@ namespace sqlpp
|
|||||||
template<typename T>\
|
template<typename T>\
|
||||||
using name##_t = typename detail::name##_impl<T>::type;
|
using name##_t = typename detail::name##_impl<T>::type;
|
||||||
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_value_type);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_value_type)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_sql_null);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_sql_null)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_boolean);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_boolean)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_integral);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_integral)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_floating_point);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_floating_point)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using is_numeric_t = logic::any_t<
|
using is_numeric_t = logic::any_t<
|
||||||
detail::is_element_of<tag::is_integral, typename T::_traits::_tags>::value,
|
detail::is_element_of<tag::is_integral, typename T::_traits::_tags>::value,
|
||||||
detail::is_element_of<tag::is_floating_point, typename T::_traits::_tags>::value>;
|
detail::is_element_of<tag::is_floating_point, typename T::_traits::_tags>::value>;
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_text);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_selectable);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_alias);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_result_field);
|
|
||||||
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(must_not_insert);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_text)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(must_not_update);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(require_insert);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_selectable)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(trivial_value_is_null);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(null_is_trivial_value);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_alias)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_result_field)
|
||||||
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_statement);
|
SQLPP_VALUE_TRAIT_GENERATOR(must_not_insert)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_prepared_statement);
|
SQLPP_VALUE_TRAIT_GENERATOR(must_not_update)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_noop);
|
SQLPP_VALUE_TRAIT_GENERATOR(require_insert)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_missing);
|
SQLPP_VALUE_TRAIT_GENERATOR(trivial_value_is_null)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value);
|
SQLPP_VALUE_TRAIT_GENERATOR(null_is_trivial_value)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_table);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_join);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_pseudo_table);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_column);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_select);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag_list);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_select_column_list);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_from);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_single_table);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_into);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_extra_tables);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_on);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_where);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_group_by);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_having);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_order_by);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_limit);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_offset);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_union);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_using_);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_column_list);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_column);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_value_list);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_assignment);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_update_list);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_insert_list);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_insert_value);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_insert_value_list);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_sort_order);
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_parameter);
|
|
||||||
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(requires_braces);
|
SQLPP_VALUE_TRAIT_GENERATOR(is_statement)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_prepared_statement)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_union)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_with)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_cte)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_noop)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_missing)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_table)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_join)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_pseudo_table)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_column)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_select)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag_list)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_select_column_list)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_from)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_single_table)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_into)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_extra_tables)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_on)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_where)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_group_by)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_having)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_order_by)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_limit)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_offset)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_using_)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_column_list)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_column)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_value_list)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_assignment)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_update_list)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_insert_list)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_insert_value)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_insert_value_list)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_sort_order)
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(is_parameter)
|
||||||
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(enforce_null_result_treatment);
|
SQLPP_VALUE_TRAIT_GENERATOR(requires_braces)
|
||||||
|
|
||||||
|
SQLPP_VALUE_TRAIT_GENERATOR(enforce_null_result_treatment)
|
||||||
|
|
||||||
template<typename Tag, bool Condition>
|
template<typename Tag, bool Condition>
|
||||||
using tag_if = typename std::conditional<Condition, Tag, void>::type;
|
using tag_if = typename std::conditional<Condition, Tag, void>::type;
|
||||||
@ -183,6 +186,12 @@ namespace sqlpp
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
using cpp_value_type_of = typename value_type_of<T>::_cpp_value_type;
|
using cpp_value_type_of = typename value_type_of<T>::_cpp_value_type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using required_ctes_of = typename T::_recursive_traits::_required_ctes;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using provided_ctes_of = typename T::_recursive_traits::_provided_ctes;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using required_tables_of = typename T::_recursive_traits::_required_tables;
|
using required_tables_of = typename T::_recursive_traits::_required_tables;
|
||||||
|
|
||||||
@ -217,6 +226,8 @@ namespace sqlpp
|
|||||||
template<typename... Arguments>
|
template<typename... Arguments>
|
||||||
struct make_recursive_traits
|
struct make_recursive_traits
|
||||||
{
|
{
|
||||||
|
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Arguments>...>;
|
||||||
|
using _provided_ctes = detail::make_joined_set_t<provided_ctes_of<Arguments>...>;
|
||||||
using _required_tables = detail::make_joined_set_t<required_tables_of<Arguments>...>;
|
using _required_tables = detail::make_joined_set_t<required_tables_of<Arguments>...>;
|
||||||
using _provided_tables = detail::make_joined_set_t<provided_tables_of<Arguments>...>;
|
using _provided_tables = detail::make_joined_set_t<provided_tables_of<Arguments>...>;
|
||||||
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Arguments>...>;
|
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Arguments>...>;
|
||||||
@ -228,6 +239,8 @@ namespace sqlpp
|
|||||||
template<typename... Tags>
|
template<typename... Tags>
|
||||||
struct recursive_tags
|
struct recursive_tags
|
||||||
{
|
{
|
||||||
|
using _required_ctes = detail::type_set<>;
|
||||||
|
using _provided_ctes = detail::type_set<>;
|
||||||
using _required_tables = detail::type_set<>;
|
using _required_tables = detail::type_set<>;
|
||||||
using _provided_tables = detail::type_set<>;
|
using _provided_tables = detail::type_set<>;
|
||||||
using _provided_outer_tables = detail::type_set<>;
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
@ -269,7 +282,7 @@ namespace sqlpp
|
|||||||
static void _()
|
static void _()
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "connection cannot run something that is neither statement nor prepared statement");
|
static_assert(wrong_t<T>::value, "connection cannot run something that is neither statement nor prepared statement");
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct assert_prepare_statement_t
|
struct assert_prepare_statement_t
|
||||||
@ -280,9 +293,24 @@ namespace sqlpp
|
|||||||
static void _()
|
static void _()
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "connection cannot prepare something that is not a statement");
|
static_assert(wrong_t<T>::value, "connection cannot prepare something that is not a statement");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T, typename Enable = void>
|
||||||
|
struct consistency_check
|
||||||
|
{
|
||||||
|
using type = assert_run_statement_or_prepared_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct consistency_check<T, typename std::enable_if<is_statement_t<T>::value or is_prepared_statement_t<T>::value>::type>
|
||||||
|
{
|
||||||
|
using type = typename T::_consistency_check;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using consistency_check_t = typename consistency_check<T>::type;
|
||||||
|
|
||||||
template<typename T, typename Enable = void>
|
template<typename T, typename Enable = void>
|
||||||
struct run_check
|
struct run_check
|
||||||
{
|
{
|
||||||
@ -329,6 +357,57 @@ namespace sqlpp
|
|||||||
template<typename Context, typename T>
|
template<typename Context, typename T>
|
||||||
using serialize_check_t = typename serialize_check<Context, T>::type;
|
using serialize_check_t = typename serialize_check<Context, T>::type;
|
||||||
|
|
||||||
|
template<typename Statement, typename Enable = void>
|
||||||
|
struct has_result_row_impl
|
||||||
|
{
|
||||||
|
using type = std::false_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
struct has_result_row_impl<Statement,
|
||||||
|
typename std::enable_if<
|
||||||
|
not wrong_t<typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>>::value,
|
||||||
|
void>::type>
|
||||||
|
{
|
||||||
|
using type = std::true_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
using has_result_row_t = typename has_result_row_impl<Statement>::type;
|
||||||
|
|
||||||
|
template<typename Statement, typename Enable = void>
|
||||||
|
struct get_result_row_impl
|
||||||
|
{
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
struct get_result_row_impl<Statement,
|
||||||
|
typename std::enable_if<
|
||||||
|
not wrong_t<typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>>::value,
|
||||||
|
void>::type>
|
||||||
|
{
|
||||||
|
using type = typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
using get_result_row_t = typename get_result_row_impl<Statement>::type;
|
||||||
|
|
||||||
|
template<typename Statement, template<typename> class Predicate, typename Enable=void>
|
||||||
|
struct has_policy_impl
|
||||||
|
{
|
||||||
|
using type = std::false_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement, template<typename> class Predicate>
|
||||||
|
struct has_policy_impl<Statement, Predicate, typename std::enable_if<is_statement_t<Statement>::value>::type>
|
||||||
|
{
|
||||||
|
using type = std::true_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Statement, template<typename> class Predicate>
|
||||||
|
using has_policy_t = typename has_policy_impl<Statement, Predicate>::type;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,53 +27,19 @@
|
|||||||
#ifndef SQLPP_UNION_H
|
#ifndef SQLPP_UNION_H
|
||||||
#define SQLPP_UNION_H
|
#define SQLPP_UNION_H
|
||||||
|
|
||||||
|
#include <sqlpp11/union_data.h>
|
||||||
|
#include <sqlpp11/select_flags.h>
|
||||||
#include <sqlpp11/statement_fwd.h>
|
#include <sqlpp11/statement_fwd.h>
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/parameter_list.h>
|
#include <sqlpp11/parameter_list.h>
|
||||||
#include <sqlpp11/expression.h>
|
#include <sqlpp11/expression.h>
|
||||||
#include <sqlpp11/interpret_tuple.h>
|
#include <sqlpp11/interpret_tuple.h>
|
||||||
#include <sqlpp11/interpretable_list.h>
|
#include <sqlpp11/interpretable_list.h>
|
||||||
|
#include <sqlpp11/result_row.h>
|
||||||
#include <sqlpp11/logic.h>
|
#include <sqlpp11/logic.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Statement, typename Enable = void>
|
|
||||||
struct has_result_row_impl
|
|
||||||
{
|
|
||||||
using type = std::false_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Statement>
|
|
||||||
struct has_result_row_impl<Statement,
|
|
||||||
typename std::enable_if<
|
|
||||||
not wrong_t<typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>>::value,
|
|
||||||
void>::type>
|
|
||||||
{
|
|
||||||
using type = std::true_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Statement>
|
|
||||||
using has_result_row_t = typename has_result_row_impl<Statement>::type;
|
|
||||||
|
|
||||||
template<typename Statement, typename Enable = void>
|
|
||||||
struct get_result_row_impl
|
|
||||||
{
|
|
||||||
using type = void;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Statement>
|
|
||||||
struct get_result_row_impl<Statement,
|
|
||||||
typename std::enable_if<
|
|
||||||
not wrong_t<typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>>::value,
|
|
||||||
void>::type>
|
|
||||||
{
|
|
||||||
using type = typename Statement::template _result_methods_t<Statement>::template _result_row_t<void>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Statement>
|
|
||||||
using get_result_row_t = typename get_result_row_impl<Statement>::type;
|
|
||||||
|
|
||||||
|
|
||||||
struct no_union_t;
|
struct no_union_t;
|
||||||
|
|
||||||
using blank_union_t = statement_t<void,
|
using blank_union_t = statement_t<void,
|
||||||
@ -83,7 +49,7 @@ namespace sqlpp
|
|||||||
template<bool, typename Union>
|
template<bool, typename Union>
|
||||||
struct union_statement_impl
|
struct union_statement_impl
|
||||||
{
|
{
|
||||||
using type = statement_t<void, Union>;
|
using type = statement_t<void, Union, no_union_t>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Union>
|
template<typename Union>
|
||||||
@ -95,31 +61,11 @@ namespace sqlpp
|
|||||||
template<bool Check, typename Union>
|
template<bool Check, typename Union>
|
||||||
using union_statement_t = typename union_statement_impl<Check, Union>::type;
|
using union_statement_t = typename union_statement_impl<Check, Union>::type;
|
||||||
|
|
||||||
|
|
||||||
// UNION DATA
|
|
||||||
template<typename Database, typename Flag, typename Lhs, typename Rhs>
|
|
||||||
struct union_data_t
|
|
||||||
{
|
|
||||||
union_data_t(Lhs lhs, Rhs rhs):
|
|
||||||
_lhs(lhs),
|
|
||||||
_rhs(rhs)
|
|
||||||
{}
|
|
||||||
|
|
||||||
union_data_t(const union_data_t&) = default;
|
|
||||||
union_data_t(union_data_t&&) = default;
|
|
||||||
union_data_t& operator=(const union_data_t&) = default;
|
|
||||||
union_data_t& operator=(union_data_t&&) = default;
|
|
||||||
~union_data_t() = default;
|
|
||||||
|
|
||||||
Lhs _lhs;
|
|
||||||
Rhs _rhs;
|
|
||||||
};
|
|
||||||
|
|
||||||
// UNION(EXPR)
|
// UNION(EXPR)
|
||||||
template<typename Database, typename Flag, typename Lhs, typename Rhs>
|
template<typename Database, typename Flag, typename Lhs, typename Rhs>
|
||||||
struct union_t
|
struct union_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_union, tag::is_select_column_list, tag::is_return_value>;
|
using _traits = make_traits<no_value_t, tag::is_union, tag::is_return_value>;
|
||||||
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
|
||||||
|
|
||||||
using _alias_t = struct{};
|
using _alias_t = struct{};
|
||||||
@ -145,9 +91,9 @@ namespace sqlpp
|
|||||||
_impl_t<Policies>& operator()() { return union_; }
|
_impl_t<Policies>& operator()() { return union_; }
|
||||||
const _impl_t<Policies>& operator()() const { return union_; }
|
const _impl_t<Policies>& operator()() const { return union_; }
|
||||||
|
|
||||||
using _selected_columns_t = decltype(union_._data._lhs.selected_columns);
|
using _selected_columns_t = typename std::decay<decltype(union_._data._lhs.get_selected_columns())>::type;
|
||||||
_selected_columns_t& get_selected_columns() { return union_._data._lhs.selected_columns;}
|
_selected_columns_t& get_selected_columns() { return union_._data._lhs.get_selected_columns(); }
|
||||||
const _selected_columns_t& get_selected_columns() const { return union_._data._lhs.selected_columns; }
|
const _selected_columns_t& get_selected_columns() const { return union_._data._lhs.get_selected_columns(); }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.union_)
|
static auto _get_member(T t) -> decltype(t.union_)
|
||||||
@ -155,7 +101,9 @@ namespace sqlpp
|
|||||||
return t.union_;
|
return t.union_;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
||||||
|
typename Lhs::_consistency_check,
|
||||||
|
typename Rhs::_consistency_check>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Statement>
|
template<typename Statement>
|
||||||
@ -197,7 +145,7 @@ namespace sqlpp
|
|||||||
using _database_t = typename Policies::_database_t;
|
using _database_t = typename Policies::_database_t;
|
||||||
|
|
||||||
template<typename... T>
|
template<typename... T>
|
||||||
using _check = logic::all_t<is_statement_t<T>::value...>; // FIXME and consistent/runnable
|
using _check = logic::all_t<is_statement_t<T>::value...>;
|
||||||
|
|
||||||
template<typename Check, typename T>
|
template<typename Check, typename T>
|
||||||
using _new_statement_t = union_statement_t<Check::value, T>;
|
using _new_statement_t = union_statement_t<Check::value, T>;
|
||||||
@ -209,9 +157,13 @@ namespace sqlpp
|
|||||||
-> _new_statement_t<_check<Rhs>, union_t<void, distinct_t, derived_statement_t<Policies>, Rhs>>
|
-> _new_statement_t<_check<Rhs>, union_t<void, distinct_t, derived_statement_t<Policies>, Rhs>>
|
||||||
{
|
{
|
||||||
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
||||||
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
||||||
static_assert(has_result_row_t<derived_statement_t<Policies>>::value, "left hand side argument of a union has to be a (complete) select statement");
|
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a complete select statement");
|
||||||
static_assert(std::is_same<get_result_row_t<derived_statement_t<Policies>>, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
|
static_assert(has_result_row_t<derived_statement_t<Policies>>::value, "left hand side argument of a union has to be a complete select statement or union");
|
||||||
|
|
||||||
|
using _result_row_t = get_result_row_t<Rhs>;
|
||||||
|
static_assert(std::is_same<get_result_row_t<derived_statement_t<Policies>>, _result_row_t>::value, "both arguments in a union have to have the same result columns (type and name)");
|
||||||
|
static_assert(is_static_result_row_t<_result_row_t>::value, "unions must not have dynamically added columns");
|
||||||
|
|
||||||
return _union_impl<void, distinct_t>(_check<derived_statement_t<Policies>, Rhs>{}, rhs);
|
return _union_impl<void, distinct_t>(_check<derived_statement_t<Policies>, Rhs>{}, rhs);
|
||||||
}
|
}
|
||||||
@ -221,10 +173,13 @@ namespace sqlpp
|
|||||||
-> _new_statement_t<_check<Rhs>, union_t<void, all_t, derived_statement_t<Policies>, Rhs>>
|
-> _new_statement_t<_check<Rhs>, union_t<void, all_t, derived_statement_t<Policies>, Rhs>>
|
||||||
{
|
{
|
||||||
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
||||||
|
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
||||||
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
||||||
static_assert(has_result_row_t<derived_statement_t<Policies>>::value, "left hand side argument of a union has to be a (complete) select statement");
|
static_assert(has_result_row_t<derived_statement_t<Policies>>::value, "left hand side argument of a union has to be a (complete) select statement");
|
||||||
static_assert(std::is_same<get_result_row_t<derived_statement_t<Policies>>, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
|
|
||||||
|
|
||||||
|
using _result_row_t = get_result_row_t<Rhs>;
|
||||||
|
static_assert(std::is_same<get_result_row_t<derived_statement_t<Policies>>, _result_row_t>::value, "both arguments in a union have to have the same result columns (type and name)");
|
||||||
|
static_assert(is_static_result_row_t<_result_row_t>::value, "unions must not have dynamically added columns");
|
||||||
|
|
||||||
return _union_impl<void, all_t>(_check<derived_statement_t<Policies>, Rhs>{}, rhs);
|
return _union_impl<void, all_t>(_check<derived_statement_t<Policies>, Rhs>{}, rhs);
|
||||||
}
|
}
|
||||||
@ -245,26 +200,6 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Interpreters
|
|
||||||
template<typename Context, typename Database, typename Flag, typename Lhs, typename Rhs>
|
|
||||||
struct serializer_t<Context, union_data_t<Database, Flag, Lhs, Rhs>>
|
|
||||||
{
|
|
||||||
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
|
|
||||||
using T = union_data_t<Database, Flag, Lhs, Rhs>;
|
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
context << '(';
|
|
||||||
serialize(t._lhs, context);
|
|
||||||
context << ") UNION ";
|
|
||||||
serialize(Flag{}, context);
|
|
||||||
context << " (";
|
|
||||||
serialize(t._rhs, context);
|
|
||||||
context << ')';
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
74
include/sqlpp11/union_data.h
Normal file
74
include/sqlpp11/union_data.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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_UNION_DATA_H
|
||||||
|
#define SQLPP_UNION_DATA_H
|
||||||
|
|
||||||
|
#include <sqlpp11/serializer.h>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
template<typename Database, typename Flag, typename Lhs, typename Rhs>
|
||||||
|
struct union_data_t
|
||||||
|
{
|
||||||
|
union_data_t(Lhs lhs, Rhs rhs):
|
||||||
|
_lhs(lhs),
|
||||||
|
_rhs(rhs)
|
||||||
|
{}
|
||||||
|
|
||||||
|
union_data_t(const union_data_t&) = default;
|
||||||
|
union_data_t(union_data_t&&) = default;
|
||||||
|
union_data_t& operator=(const union_data_t&) = default;
|
||||||
|
union_data_t& operator=(union_data_t&&) = default;
|
||||||
|
~union_data_t() = default;
|
||||||
|
|
||||||
|
Lhs _lhs;
|
||||||
|
Rhs _rhs;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Interpreters
|
||||||
|
template<typename Context, typename Database, typename Flag, typename Lhs, typename Rhs>
|
||||||
|
struct serializer_t<Context, union_data_t<Database, Flag, Lhs, Rhs>>
|
||||||
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
|
||||||
|
using T = union_data_t<Database, Flag, Lhs, Rhs>;
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
context << '(';
|
||||||
|
serialize(t._lhs, context);
|
||||||
|
context << ") UNION ";
|
||||||
|
serialize(Flag{}, context);
|
||||||
|
context << " (";
|
||||||
|
serialize(t._rhs, context);
|
||||||
|
context << ')';
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -147,7 +147,7 @@ namespace sqlpp
|
|||||||
static void _()
|
static void _()
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "update assignments required, i.e. set(...)");
|
static_assert(wrong_t<T>::value, "update assignments required, i.e. set(...)");
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct no_update_list_t
|
struct no_update_list_t
|
||||||
|
@ -192,7 +192,7 @@ namespace sqlpp
|
|||||||
static_assert(not detail::has_duplicates<Args...>::value, "at least one duplicate argument detected in using()");
|
static_assert(not detail::has_duplicates<Args...>::value, "at least one duplicate argument detected in using()");
|
||||||
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), using_data_t<Database, Args...>{args...} };
|
return { static_cast<const derived_statement_t<Policies>&>(*this), using_data_t<Database, Args...>{args...} };
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ namespace sqlpp
|
|||||||
static void _()
|
static void _()
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "where expression required, e.g. where(true)");
|
static_assert(wrong_t<T>::value, "where expression required, e.g. where(true)");
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// NO WHERE YET
|
// NO WHERE YET
|
||||||
|
196
include/sqlpp11/with.h
Normal file
196
include/sqlpp11/with.h
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* 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_WITH_H
|
||||||
|
#define SQLPP_WITH_H
|
||||||
|
|
||||||
|
#include <sqlpp11/assignment.h>
|
||||||
|
#include <sqlpp11/column_fwd.h>
|
||||||
|
#include <sqlpp11/statement_fwd.h>
|
||||||
|
#include <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/no_data.h>
|
||||||
|
#include <sqlpp11/policy_update.h>
|
||||||
|
#include <sqlpp11/parameter_list.h>
|
||||||
|
#include <sqlpp11/expression.h>
|
||||||
|
#include <sqlpp11/interpret_tuple.h>
|
||||||
|
#include <sqlpp11/interpretable_list.h>
|
||||||
|
#include <sqlpp11/logic.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <sqlpp11/cte.h>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
template<typename Database, typename... Expressions>
|
||||||
|
struct with_data_t
|
||||||
|
{
|
||||||
|
using _is_recursive = logic::any_t<Expressions::_is_recursive...>;
|
||||||
|
|
||||||
|
with_data_t(Expressions... expressions):
|
||||||
|
_expressions(expressions...)
|
||||||
|
{}
|
||||||
|
|
||||||
|
with_data_t(const with_data_t&) = default;
|
||||||
|
with_data_t(with_data_t&&) = default;
|
||||||
|
with_data_t& operator=(const with_data_t&) = default;
|
||||||
|
with_data_t& operator=(with_data_t&&) = default;
|
||||||
|
~with_data_t() = default;
|
||||||
|
|
||||||
|
std::tuple<Expressions...> _expressions;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Database, typename... Expressions>
|
||||||
|
struct with_t
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_with>;
|
||||||
|
struct _recursive_traits
|
||||||
|
{
|
||||||
|
using _required_ctes = detail::type_set<>;
|
||||||
|
using _provided_ctes = detail::make_joined_set_t<required_ctes_of<Expressions>...>; // with provides common table expressions
|
||||||
|
using _required_tables = detail::type_set<>;
|
||||||
|
using _provided_tables = detail::type_set<>;
|
||||||
|
using _provided_outer_tables = detail::type_set<>;
|
||||||
|
using _extra_tables = detail::type_set<>;
|
||||||
|
using _parameters = detail::make_parameter_tuple_t<parameters_of<Expressions>...>;
|
||||||
|
using _tags = detail::type_set<>;
|
||||||
|
};
|
||||||
|
|
||||||
|
using _is_dynamic = is_database<Database>;
|
||||||
|
|
||||||
|
// Data
|
||||||
|
using _data_t = with_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
|
// Member implementation with data and methods
|
||||||
|
template <typename Policies>
|
||||||
|
struct _impl_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
_data_t _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Base template to be inherited by the statement
|
||||||
|
template<typename Policies>
|
||||||
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = with_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
|
_impl_t<Policies> with;
|
||||||
|
_impl_t<Policies>& operator()() { return with; }
|
||||||
|
const _impl_t<Policies>& operator()() const { return with; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static auto _get_member(T t) -> decltype(t.with)
|
||||||
|
{
|
||||||
|
return t.with;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Need real checks here
|
||||||
|
using _consistency_check = consistent_t;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct no_with_t
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_with>;
|
||||||
|
using _recursive_traits = make_recursive_traits<>;
|
||||||
|
|
||||||
|
// Data
|
||||||
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
|
// Member implementation with data and methods
|
||||||
|
template<typename Policies>
|
||||||
|
struct _impl_t
|
||||||
|
{
|
||||||
|
_data_t _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Base template to be inherited by the statement
|
||||||
|
template<typename Policies>
|
||||||
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
|
_impl_t<Policies> no_with;
|
||||||
|
_impl_t<Policies>& operator()() { return no_with; }
|
||||||
|
const _impl_t<Policies>& operator()() const { return no_with; }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static auto _get_member(T t) -> decltype(t.no_with)
|
||||||
|
{
|
||||||
|
return t.no_with;
|
||||||
|
}
|
||||||
|
|
||||||
|
using _consistency_check = consistent_t;
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Database, typename... Expressions>
|
||||||
|
struct blank_with_t
|
||||||
|
{
|
||||||
|
with_data_t<Database, Expressions...> _data;
|
||||||
|
|
||||||
|
template<typename Statement>
|
||||||
|
auto operator()(Statement statement)
|
||||||
|
-> new_statement_t<true, typename Statement::_policies_t, no_with_t, with_t<Database, Expressions...>>
|
||||||
|
{
|
||||||
|
// FIXME need checks here
|
||||||
|
// check that no cte refers to any of the ctes to the right
|
||||||
|
return { statement, _data };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Interpreters
|
||||||
|
template<typename Context, typename Database, typename... Expressions>
|
||||||
|
struct serializer_t<Context, with_data_t<Database, Expressions...>>
|
||||||
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
||||||
|
using T = with_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
// FIXME: If there is a recursive CTE, add a "RECURSIVE" here
|
||||||
|
context << " WITH ";
|
||||||
|
if (T::_is_recursive::value)
|
||||||
|
context << "RECURSIVE ";
|
||||||
|
interpret_tuple(t._expressions, ',', context);
|
||||||
|
context << ' ';
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Expressions>
|
||||||
|
auto with(Expressions... cte)
|
||||||
|
-> blank_with_t<void, Expressions...>
|
||||||
|
{
|
||||||
|
static_assert(logic::all_t<is_cte_t<Expressions>::value...>::value, "at least one expression in with is not a common table expression");
|
||||||
|
static_assert(logic::none_t<is_alias_t<Expressions>::value...>::value, "at least one expression in with is an incomplete common table expression");
|
||||||
|
return { {cte...} };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -19,6 +19,7 @@ endmacro ()
|
|||||||
#build_and_run(Minimalistic)
|
#build_and_run(Minimalistic)
|
||||||
#build_and_run(ResultTest)
|
#build_and_run(ResultTest)
|
||||||
build_and_run(UnionTest)
|
build_and_run(UnionTest)
|
||||||
|
build_and_run(WithTest)
|
||||||
|
|
||||||
# if you want to use the generator, you can do something like this:
|
# if you want to use the generator, you can do something like this:
|
||||||
#find_package(PythonInterp REQUIRED)
|
#find_package(PythonInterp REQUIRED)
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
MockDb db = {};
|
MockDb db = {};
|
||||||
SQLPP_ALIAS_PROVIDER(kaesekuchen);
|
SQLPP_ALIAS_PROVIDER(kaesekuchen)
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
@ -103,7 +103,7 @@ struct MockDbT: public sqlpp::connection
|
|||||||
void next(ResultRow& result_row)
|
void next(ResultRow& result_row)
|
||||||
{
|
{
|
||||||
result_row._invalidate();
|
result_row._invalidate();
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Directly executed statements start here
|
// Directly executed statements start here
|
||||||
|
@ -38,10 +38,10 @@ MockDb::_serializer_context_t printer;
|
|||||||
|
|
||||||
namespace alias
|
namespace alias
|
||||||
{
|
{
|
||||||
SQLPP_ALIAS_PROVIDER(a);
|
SQLPP_ALIAS_PROVIDER(a)
|
||||||
SQLPP_ALIAS_PROVIDER(b);
|
SQLPP_ALIAS_PROVIDER(b)
|
||||||
SQLPP_ALIAS_PROVIDER(left);
|
SQLPP_ALIAS_PROVIDER(left)
|
||||||
SQLPP_ALIAS_PROVIDER(right);
|
SQLPP_ALIAS_PROVIDER(right)
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
|
@ -37,12 +37,17 @@ int main()
|
|||||||
test::TabBar t;
|
test::TabBar t;
|
||||||
test::TabFoo f;
|
test::TabFoo f;
|
||||||
|
|
||||||
db(select(t.alpha).from(t).union_distinct(select(f.epsilon.as(t.alpha)).from(f)));
|
db(select(t.alpha).from(t).where(true)
|
||||||
db(select(t.alpha).from(t).union_all(select(f.epsilon.as(t.alpha)).from(f)));
|
.union_distinct(select(f.epsilon.as(t.alpha)).from(f).where(true)));
|
||||||
|
db(select(t.alpha).from(t).where(true)
|
||||||
|
.union_all(select(f.epsilon.as(t.alpha)).from(f).where(true)));
|
||||||
|
|
||||||
auto u = select(t.alpha).from(t).union_all(select(f.epsilon.as(t.alpha)).from(f)).as(sqlpp::alias::u);
|
auto u = select(t.alpha).from(t).where(true).union_all(select(f.epsilon.as(t.alpha)).from(f).where(true)).as(sqlpp::alias::u);
|
||||||
|
|
||||||
db(select(all_of(u)).from(u).union_all(select(t.delta.as(t.alpha)).from(t)));
|
db(select(all_of(u)).from(u).where(true).union_all(select(t.delta.as(t.alpha)).from(t).where(true)));
|
||||||
|
db(select(u.alpha).from(u).where(true).union_all(select(t.delta.as(t.alpha)).from(t).where(true)));
|
||||||
|
|
||||||
|
db(select(t.alpha).from(t).where(true).union_all(select(t.alpha).from(t).where(true)).union_all(select(t.alpha).from(t).where(true)));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
52
tests/WithTest.cpp
Normal file
52
tests/WithTest.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Sample.h"
|
||||||
|
#include "MockDb.h"
|
||||||
|
#include <sqlpp11/select.h>
|
||||||
|
#include <sqlpp11/alias_provider.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
MockDb db;
|
||||||
|
MockDb::_serializer_context_t printer;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
const auto t = test::TabBar{};
|
||||||
|
|
||||||
|
auto x = cte(sqlpp::x).as(select(all_of(t)).from(t));
|
||||||
|
|
||||||
|
db(with(x)(select(x.alpha).from(x).where(true)));
|
||||||
|
|
||||||
|
auto y0 = cte(sqlpp::y).as(select(all_of(t)).from(t));
|
||||||
|
auto y = y0.union_all(select(all_of(y0)).from(y0).where(false));
|
||||||
|
|
||||||
|
std::cout << serialize(y, printer).str() << std::endl; printer.reset();
|
||||||
|
std::cout << serialize(from_table(y), printer).str() << std::endl;
|
||||||
|
|
||||||
|
db(with(y)(select(y.alpha).from(y).where(true)));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user