mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Fixed outer-tables for joins, added tests
This commit is contained in:
parent
0a325e4471
commit
aceede57eb
@ -65,6 +65,7 @@ target_compile_features(sqlpp11 INTERFACE
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
add_subdirectory(test_types)
|
||||||
add_subdirectory(test_serializer)
|
add_subdirectory(test_serializer)
|
||||||
add_subdirectory(test_static_asserts)
|
add_subdirectory(test_static_asserts)
|
||||||
add_subdirectory(test_constraints)
|
add_subdirectory(test_constraints)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -111,7 +111,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
"avg() cannot be used on an aggregate function");
|
"avg() cannot be used on an aggregate function");
|
||||||
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
|
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a numeric value expression as argument");
|
||||||
return {t};
|
return {t};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
"avg() cannot be used on an aggregate function");
|
"avg() cannot be used on an aggregate function");
|
||||||
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
|
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a numeric value expression as argument");
|
||||||
return {t};
|
return {t};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,14 +49,14 @@ namespace sqlpp
|
|||||||
struct left_outer_join_t
|
struct left_outer_join_t
|
||||||
{
|
{
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
|
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
||||||
|
|
||||||
static constexpr const char* _name = " LEFT OUTER";
|
static constexpr const char* _name = " LEFT OUTER";
|
||||||
};
|
};
|
||||||
struct right_outer_join_t
|
struct right_outer_join_t
|
||||||
{
|
{
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
|
||||||
|
|
||||||
static constexpr const char* _name = " RIGHT OUTER";
|
static constexpr const char* _name = " RIGHT OUTER";
|
||||||
};
|
};
|
||||||
|
@ -91,6 +91,7 @@ namespace sqlpp
|
|||||||
using _traits = make_traits<no_value_t, tag::is_pre_join>;
|
using _traits = make_traits<no_value_t, tag::is_pre_join>;
|
||||||
using _nodes = detail::type_vector<Lhs, Rhs>;
|
using _nodes = detail::type_vector<Lhs, Rhs>;
|
||||||
using _can_be_null = std::false_type;
|
using _can_be_null = std::false_type;
|
||||||
|
using _provided_outer_tables = typename JoinType::template _provided_outer_tables<Lhs, Rhs>;
|
||||||
|
|
||||||
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
|
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
|
||||||
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
|
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
|
||||||
@ -185,7 +186,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
template <typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
auto outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
auto outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
|
||||||
pre_join_t<right_outer_join_t, Lhs, Rhs>,
|
pre_join_t<outer_join_t, Lhs, Rhs>,
|
||||||
bad_statement>::type
|
bad_statement>::type
|
||||||
{
|
{
|
||||||
check_pre_join_t<Lhs, Rhs>::_();
|
check_pre_join_t<Lhs, Rhs>::_();
|
||||||
|
@ -48,6 +48,14 @@ int From(int, char* [])
|
|||||||
compare(__LINE__, from(foo.cross_join(bar)), " FROM tab_foo CROSS JOIN tab_bar");
|
compare(__LINE__, from(foo.cross_join(bar)), " FROM tab_foo CROSS JOIN tab_bar");
|
||||||
compare(__LINE__, from(foo.join(bar).on(foo.omega > bar.alpha)),
|
compare(__LINE__, from(foo.join(bar).on(foo.omega > bar.alpha)),
|
||||||
" FROM tab_foo INNER JOIN tab_bar ON (tab_foo.omega>tab_bar.alpha)");
|
" FROM tab_foo INNER JOIN tab_bar ON (tab_foo.omega>tab_bar.alpha)");
|
||||||
|
compare(__LINE__, from(foo.inner_join(bar).on(foo.omega > bar.alpha)),
|
||||||
|
" FROM tab_foo INNER JOIN tab_bar ON (tab_foo.omega>tab_bar.alpha)");
|
||||||
|
compare(__LINE__, from(foo.outer_join(bar).on(foo.omega > bar.alpha)),
|
||||||
|
" FROM tab_foo OUTER JOIN tab_bar ON (tab_foo.omega>tab_bar.alpha)");
|
||||||
|
compare(__LINE__, from(foo.left_outer_join(bar).on(foo.omega > bar.alpha)),
|
||||||
|
" FROM tab_foo LEFT OUTER JOIN tab_bar ON (tab_foo.omega>tab_bar.alpha)");
|
||||||
|
compare(__LINE__, from(foo.right_outer_join(bar).on(foo.omega > bar.alpha)),
|
||||||
|
" FROM tab_foo RIGHT OUTER JOIN tab_bar ON (tab_foo.omega>tab_bar.alpha)");
|
||||||
compare(__LINE__, from(aFoo.join(bFoo).on(aFoo.omega > bFoo.omega)),
|
compare(__LINE__, from(aFoo.join(bFoo).on(aFoo.omega > bFoo.omega)),
|
||||||
" FROM tab_foo AS a INNER JOIN tab_foo AS b ON (a.omega>b.omega)");
|
" FROM tab_foo AS a INNER JOIN tab_foo AS b ON (a.omega>b.omega)");
|
||||||
compare(
|
compare(
|
||||||
@ -62,11 +70,31 @@ int From(int, char* [])
|
|||||||
dfa.from.add(dynamic_cross_join(bar));
|
dfa.from.add(dynamic_cross_join(bar));
|
||||||
compare(__LINE__, dfa, " FROM tab_foo CROSS JOIN tab_bar");
|
compare(__LINE__, dfa, " FROM tab_foo CROSS JOIN tab_bar");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
auto dfa = df;
|
||||||
|
dfa.from.add(dynamic_join(bar).on(bar.alpha > foo.omega));
|
||||||
|
compare(__LINE__, dfa, " FROM tab_foo INNER JOIN tab_bar ON (tab_bar.alpha>tab_foo.omega)");
|
||||||
|
}
|
||||||
{
|
{
|
||||||
auto dfa = df;
|
auto dfa = df;
|
||||||
dfa.from.add(dynamic_inner_join(bar).on(bar.alpha > foo.omega));
|
dfa.from.add(dynamic_inner_join(bar).on(bar.alpha > foo.omega));
|
||||||
compare(__LINE__, dfa, " FROM tab_foo INNER JOIN tab_bar ON (tab_bar.alpha>tab_foo.omega)");
|
compare(__LINE__, dfa, " FROM tab_foo INNER JOIN tab_bar ON (tab_bar.alpha>tab_foo.omega)");
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
auto dfa = df;
|
||||||
|
dfa.from.add(dynamic_outer_join(bar).on(bar.alpha > foo.omega));
|
||||||
|
compare(__LINE__, dfa, " FROM tab_foo OUTER JOIN tab_bar ON (tab_bar.alpha>tab_foo.omega)");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto dfa = df;
|
||||||
|
dfa.from.add(dynamic_left_outer_join(bar).on(bar.alpha > foo.omega));
|
||||||
|
compare(__LINE__, dfa, " FROM tab_foo LEFT OUTER JOIN tab_bar ON (tab_bar.alpha>tab_foo.omega)");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto dfa = df;
|
||||||
|
dfa.from.add(dynamic_right_outer_join(bar).on(bar.alpha > foo.omega));
|
||||||
|
compare(__LINE__, dfa, " FROM tab_foo RIGHT OUTER JOIN tab_bar ON (tab_bar.alpha>tab_foo.omega)");
|
||||||
|
}
|
||||||
{
|
{
|
||||||
auto dfa = df;
|
auto dfa = df;
|
||||||
dfa.from.add(dynamic_inner_join(bar).on(bar.alpha > foo.omega));
|
dfa.from.add(dynamic_inner_join(bar).on(bar.alpha > foo.omega));
|
||||||
|
32
test_types/CMakeLists.txt
Normal file
32
test_types/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright (c) 2016-2016, 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.
|
||||||
|
|
||||||
|
function(test_compile name)
|
||||||
|
set(target sqlpp11_${name})
|
||||||
|
add_executable(${target} ${name}.cpp)
|
||||||
|
target_link_libraries(${target} PRIVATE sqlpp11 sqlpp11_testing)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
test_compile(result_row)
|
||||||
|
|
50
test_types/compare.h
Normal file
50
test_types/compare.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2015, 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_TEST_SERIALIZER_H
|
||||||
|
#define SQLPP_TEST_SERIALIZER_H
|
||||||
|
|
||||||
|
#include "MockDb.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <typename Expression>
|
||||||
|
void compare(int lineNo, const Expression& expr, const std::string& expected)
|
||||||
|
{
|
||||||
|
MockDb::_serializer_context_t printer = {};
|
||||||
|
|
||||||
|
const auto result = serialize(expr, printer).str();
|
||||||
|
|
||||||
|
if (result != expected)
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << " " << lineNo << '\n' << "Expected: -->|" << expected << "|<--\n"
|
||||||
|
<< "Received: -->|" << result << "|<--\n";
|
||||||
|
throw std::runtime_error("unexpected serialization result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
212
test_types/result_row.cpp
Normal file
212
test_types/result_row.cpp
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2016, 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 "MockDb.h"
|
||||||
|
#include "Sample.h"
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr auto bar = test::TabBar{};
|
||||||
|
constexpr auto foo = test::TabFoo{};
|
||||||
|
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(bar.alpha)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(foo.omega)>::value, "");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(foo.delta)>::value, "");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(bar.gamma)>::value, "");
|
||||||
|
const auto seven = sqlpp::value(7).as(sqlpp::alias::s);
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(seven)>::value, "");
|
||||||
|
|
||||||
|
auto db = MockDb{};
|
||||||
|
|
||||||
|
void single_table()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// result fields are as nullable as the expressions they represent
|
||||||
|
const auto& x = db(select(bar.alpha, bar.gamma, seven).from(bar).unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void join()
|
||||||
|
{
|
||||||
|
// Join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of (inner) join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of (inner) join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of (inner) join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of (inner) join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.inner_join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of inner join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of inner join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.inner_join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of inner join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of inner join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left outer join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.left_outer_join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of left outer join cannot be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of left outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.left_outer_join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of left outer join cannot be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of left outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right outer join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.right_outer_join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of right outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value,
|
||||||
|
"right side of right outer join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.right_outer_join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of right outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value,
|
||||||
|
"right side of right outer join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outer join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.outer_join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of outer join can be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.outer_join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of outer join can be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cross join
|
||||||
|
{
|
||||||
|
const auto& x =
|
||||||
|
db(select(bar.alpha, foo.delta, bar.gamma, seven).from(foo.cross_join(bar)).unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of cross join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of cross join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x =
|
||||||
|
db(select(bar.alpha, foo.delta, bar.gamma, seven).from(bar.cross_join(foo)).unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of cross join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of cross join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void aggregates()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// aggregates of nullable values
|
||||||
|
const auto a = bar.alpha;
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(bar.alpha)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(a)>::value, "");
|
||||||
|
const auto& x = db(select(count(a), avg(a), max(a), min(a), sum(a)).from(bar).unconditionally()).front();
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.count)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.avg)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.sum)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.max)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.min)>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// aggregates of nullable values
|
||||||
|
const auto o = foo.omega;
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(foo.omega)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(o)>::value, "");
|
||||||
|
const auto& x = db(select(count(o), avg(o), max(o), min(o), sum(o)).from(foo).unconditionally()).front();
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.count)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.avg)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.sum)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.max)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.min)>::value, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char* [])
|
||||||
|
{
|
||||||
|
single_table();
|
||||||
|
join();
|
||||||
|
aggregates();
|
||||||
|
}
|
@ -29,7 +29,7 @@ namespace test
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
|
using _traits = sqlpp::make_traits<sqlpp::varchar>;
|
||||||
};
|
};
|
||||||
struct Epsilon
|
struct Epsilon
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user