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

Merge branch 'release/0.36'

This commit is contained in:
rbock 2016-04-17 16:05:10 +02:00
commit 8bd12f02a4
92 changed files with 3435 additions and 1382 deletions

View File

@ -23,6 +23,9 @@ install:
- CMAKE_VERSION_MM=3.2
- CMAKE_VERSION_FULL=$CMAKE_VERSION_MM.2
- git clone https://github.com/HowardHinnant/date
- cd date
- git checkout tags/v1.0.0
- cd ..
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
&& sudo add-apt-repository -y ppa:apokluda/boost1.53

View File

@ -1,4 +1,4 @@
# Copyright (c) 2013-2015, Roland Bock
# Copyright (c) 2013-2016, Roland Bock
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -32,12 +32,19 @@ add_library(sqlpp11 INTERFACE)
set(DATE_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../date" CACHE FILEPATH "Path to Howard Hinnant's date library")
if(NOT EXISTS ${DATE_INCLUDE_DIR}/date.h)
message(SEND_ERROR "Can't find date.h in ${DATE_INCLUDE_DIR}")
message(SEND_ERROR "Can't find file date.h and cannot compile date_test/date_test.cpp")
message("Can't find date.h in ${DATE_INCLUDE_DIR} ")
message("Please either")
message(" - git clone https://github.com/howardhinnant/date ${DATE_INCLUDE_DIR}")
message(" - download and unzip a current version from https://github.com/howardhinnant/date to ${DATE_INCLUDE_DIR}")
message(" - set DATE_INCLUDE_DIR to point to the dir containing date.h from the date library")
message("")
endif()
target_include_directories(sqlpp11 INTERFACE
$<BUILD_INTERFACE:${DATE_INCLUDE_DIR}>
$<BUILD_INTERFACE:${sqlpp11_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
if (NOT MSVC)
@ -64,10 +71,51 @@ target_compile_features(sqlpp11 INTERFACE
)
endif ()
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/sqlpp11"
DESTINATION include
)
install(TARGETS sqlpp11
EXPORT Sqlpp11Targets
)
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/cmake/Sqlpp11ConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
export(EXPORT Sqlpp11Targets
FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/Sqlpp11Targets.cmake"
)
configure_file(cmake/Sqlpp11Config.cmake
"${CMAKE_CURRENT_BINARY_DIR}/cmake/Sqlpp11Config.cmake"
COPYONLY
)
set(ConfigPackageLocation lib/cmake/Sqlpp11)
install(EXPORT Sqlpp11Targets
FILE
Sqlpp11Targets.cmake
DESTINATION
${ConfigPackageLocation}
)
install(
FILES
cmake/Sqlpp11Config.cmake
"${CMAKE_CURRENT_BINARY_DIR}/cmake/Sqlpp11ConfigVersion.cmake"
DESTINATION
${ConfigPackageLocation}
)
add_subdirectory(tests)
add_subdirectory(test_types)
add_subdirectory(test_serializer)
add_subdirectory(test_static_asserts)
add_subdirectory(test_constraints)
add_subdirectory(examples)
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/sqlpp11" DESTINATION include)

View File

@ -1,31 +1,22 @@
sqlpp11
=======
A type safe embedded domain specific language for SQL queries and results in C++
Documentation is found in the [wiki](https://github.com/rbock/sqlpp11/wiki)
Breaking changes in 0.36:
-------------------------
See [Changes](ChangeLog.md)
Status:
-------
Branch / Compiler | clang-3.4, gcc-4.9, Xcode-7 | MSVC 2015 | Test Coverage
------------------| -------------------------------|-------------|---------------
master | [![Build Status](https://travis-ci.org/rbock/sqlpp11.svg?branch=master)](https://travis-ci.org/rbock/sqlpp11?branch=master) | [![Build status](https://ci.appveyor.com/api/projects/status/eid7mwqgavo0h61h/branch/master?svg=true)](https://ci.appveyor.com/project/rbock/sqlpp11/branch/master) | [![Coverage Status](https://coveralls.io/repos/rbock/sqlpp11/badge.svg?branch=master)](https://coveralls.io/r/rbock/sqlpp11?branch=master)
develop | [![Build Status](https://travis-ci.org/rbock/sqlpp11.svg?branch=develop)](https://travis-ci.org/rbock/sqlpp11?branch=develop) | [![Build status](https://ci.appveyor.com/api/projects/status/eid7mwqgavo0h61h/branch/develop?svg=true)](https://ci.appveyor.com/project/rbock/sqlpp11/branch/develop) | [![Coverage Status](https://coveralls.io/repos/rbock/sqlpp11/badge.svg?branch=develop)](https://coveralls.io/r/rbock/sqlpp11?branch=develop)
A type safe embedded domain specific language for SQL queries and results in C++
Documentation is found in the wiki, https://github.com/rbock/sqlpp11/wiki
Past talks about sqlpp11 and some coding concepts used within the library:
* [CppCast:](http://cppcast.com)
* 2015-05-07: http://cppcast.com/2015/05/roland-bock/
* [CppCon:](http://cppcon.org)
* 2015-09-24: [Pruning Error Messages From Your C++ Template Code](https://www.youtube.com/watch?v=2ISqFW9fRws), with examples from sqlpp11
* 2014-09-11: [sqlpp11, An SQL Library Worthy Of Modern C++](https://www.youtube.com/watch?v=cJPAjhBm-HQ)
* [Meeting C++:](http://meetingcpp.com)
* 2014-12-05: [sqlpp11, An EDSL For Type-Safe SQL In C++11](https://www.youtube.com/watch?v=9Hjfg9IfzhU)
* [MUC++:](http://www.meetup.com/MUCplusplus/)
* 2014-02-27: [Selected C++11 Template Toffees From sqlpp11, Part1](https://www.youtube.com/watch?v=hXnGFYNbmXg), [Part2](https://www.youtube.com/watch?v=WPCV6dvxZ_U), [Part 3](https://www.youtube.com/watch?v=eB7hd_KjTig), [Part 4](https://www.youtube.com/watch?v=NBfqzcN0_EQ)
You can contact me
* by posting issues at https://github.com/rbock/sqlpp11/issues
* or via email at rbock at eudoxos dot de
Motivation:
-----------
SQL and C++ are both strongly typed languages. Still, most C/C++ interfaces to SQL are based on constructing queries as strings and on interpreting arrays or maps of strings as results.
@ -46,6 +37,8 @@ The library supports both static and dynamic queries. The former offers greater
sqlpp11 is vendor-neutral. Specific traits of databases (e.g. unsupported or non-standard features) are handled by connector libraries. Connector libraries can inform the developer of missing features at compile time. They also interpret expressions specifically where needed. For example, the connector could use the operator|| or the concat method for string concatenation without the developer being required to change the statement.
The library is already used in production but it is certainly not complete yet. Feature requests, bug reports, contributions to code or documentation are most welcome.
Examples:
---------
For the examples, lets assume you have a table class representing something like
@ -102,9 +95,23 @@ db(update(foo).set(foo.hasFun = not foo.hasFun).where(foo.name != "nobody"));
db(remove_from(foo).where(not foo.hasFun));
```
Your help is needed:
--------------------
The library is already used in production but it is certainly not complete yet. Feature requests, bug reports, contributions to code or documentation are most welcome.
Additional information available:
---------------------------------
Past talks about sqlpp11 and some coding concepts used within the library:
* [CppCast:](http://cppcast.com)
* 2015-05-07: http://cppcast.com/2015/05/roland-bock/
* [CppCon:](http://cppcon.org)
* 2015-09-24: [Pruning Error Messages From Your C++ Template Code](https://www.youtube.com/watch?v=2ISqFW9fRws), with examples from sqlpp11
* 2014-09-11: [sqlpp11, An SQL Library Worthy Of Modern C++](https://www.youtube.com/watch?v=cJPAjhBm-HQ)
* [Meeting C++:](http://meetingcpp.com)
* 2014-12-05: [sqlpp11, An EDSL For Type-Safe SQL In C++11](https://www.youtube.com/watch?v=9Hjfg9IfzhU)
* [MUC++:](http://www.meetup.com/MUCplusplus/)
* 2014-02-27: [Selected C++11 Template Toffees From sqlpp11, Part1](https://www.youtube.com/watch?v=hXnGFYNbmXg), [Part2](https://www.youtube.com/watch?v=WPCV6dvxZ_U), [Part 3](https://www.youtube.com/watch?v=eB7hd_KjTig), [Part 4](https://www.youtube.com/watch?v=NBfqzcN0_EQ)
You can contact me
* by posting issues at https://github.com/rbock/sqlpp11/issues
* or via email at rbock at eudoxos dot de
Requirements:
@ -159,3 +166,4 @@ Include generated header (MyTable.h), that's all
License:
-------------
sqlpp11 is distributed under the [BSD 2-Clause License](https://github.com/rbock/sqlpp11/blob/master/LICENSE).

26
cmake/Sqlpp11Config.cmake Normal file
View File

@ -0,0 +1,26 @@
# Copyright (c) 2016, Christian David
# 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("${CMAKE_CURRENT_LIST_DIR}/Sqlpp11Targets.cmake")

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* 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,
"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};
}
@ -120,7 +120,7 @@ namespace sqlpp
{
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
"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};
}
}

View File

@ -31,6 +31,8 @@ namespace sqlpp
{
struct bad_statement
{
static constexpr bool value = false;
template <typename... T>
bad_statement(T&&...)
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,7 +28,7 @@
#define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H
#include <sqlpp11/value_type_fwd.h>
#include <sqlpp11/bad_statement.h>
#include <sqlpp11/bad_expression.h>
#include <sqlpp11/portable_static_assert.h>
#include <sqlpp11/consistent.h>
#include <sqlpp11/alias.h>
@ -41,206 +41,171 @@
namespace sqlpp
{
SQLPP_PORTABLE_STATIC_ASSERT(assert_valid_rhs_comparison_operand_t, "invalid rhs operand in comparison");
SQLPP_PORTABLE_STATIC_ASSERT(assert_comparison_rhs_is_expression_t, "rhs operand in comparison is not an expression");
SQLPP_PORTABLE_STATIC_ASSERT(assert_comparison_rhs_is_valid_operand_t, "invalid rhs operand in comparison");
SQLPP_PORTABLE_STATIC_ASSERT(assert_comparison_lhs_rhs_differ_t, "identical lhs and rhs operands in comparison");
template <typename LhsValueType, typename RhsType>
using check_rhs_comparison_operand_t =
static_check_t<(is_expression_t<sqlpp::wrap_operand_t<RhsType>>::value // expressions are OK
or
is_multi_expression_t<sqlpp::wrap_operand_t<RhsType>>::value) // multi-expressions like ANY are
// OK for comparisons, too
and
LhsValueType::template _is_valid_operand<
sqlpp::wrap_operand_t<RhsType>>::value, // the correct value type is required, of course
assert_valid_rhs_comparison_operand_t>;
template <typename LhsType, typename RhsType>
using check_comparison_impl = static_combined_check_t<
static_check_t<logic::any_t<is_expression_t<RhsType>::value, is_multi_expression_t<RhsType>::value>::value,
assert_comparison_rhs_is_expression_t>,
static_check_t<value_type_of<LhsType>::template _is_valid_operand<RhsType>::value,
assert_comparison_rhs_is_valid_operand_t>,
static_check_t<not std::is_same<LhsType, RhsType>::value, assert_comparison_lhs_rhs_differ_t>>;
SQLPP_PORTABLE_STATIC_ASSERT(assert_valid_in_arguments_t, "at least one operand of in() is not valid");
template <typename LhsType, typename RhsType>
using check_comparison_t = check_comparison_impl<LhsType, wrap_operand_t<RhsType>>;
template <typename LhsValueType, typename... InTypes>
using check_rhs_in_arguments_t =
static_check_t<logic::all_t<check_rhs_comparison_operand_t<LhsValueType, InTypes>::value...>::value,
assert_valid_in_arguments_t>;
template <typename LhsType, typename... RhsType>
using check_in_impl = static_combined_check_t<
static_check_t<logic::all_t<is_expression_t<RhsType>::value...>::value, assert_comparison_rhs_is_expression_t>,
static_check_t<logic::all_t<value_type_of<LhsType>::template _is_valid_operand<RhsType>::value...>::value,
assert_comparison_rhs_is_valid_operand_t>,
static_check_t<logic::none_t<std::is_same<LhsType, RhsType>::value...>::value,
assert_comparison_lhs_rhs_differ_t>>;
namespace detail
{
template <bool Enable, template <typename Lhs> class Expr, typename Lhs>
struct new_unary_expression_impl
{
using type = bad_statement;
};
template <template <typename Lhs> class Expr, typename Lhs>
struct new_unary_expression_impl<true, Expr, Lhs>
{
using type = Expr<Lhs>;
};
}
template <typename Check, template <typename Lhs> class Expr, typename Lhs>
using new_unary_expression_t = typename detail::new_unary_expression_impl<Check::value, Expr, Lhs>::type;
template <typename LhsType, typename... RhsType>
using check_in_t = check_in_impl<LhsType, typename wrap_operand<RhsType>::type...>;
namespace detail
{
template <bool Enable, template <typename Lhs, typename Rhs> class Expr, typename Lhs, typename Rhs>
struct new_binary_expression_impl
struct comparison_expression_impl
{
using type = bad_statement;
using type = bad_expression<boolean>;
};
template <template <typename Lhs, typename Rhs> class Expr, typename Lhs, typename Rhs>
struct new_binary_expression_impl<true, Expr, Lhs, Rhs>
struct comparison_expression_impl<true, Expr, Lhs, Rhs>
{
using type = Expr<Lhs, Rhs>;
using type = Expr<wrap_operand_t<Lhs>, wrap_operand_t<Rhs>>;
};
}
template <typename Check, template <typename Lhs, typename Rhs> class Expr, typename Lhs, typename Rhs>
using new_binary_expression_t = typename detail::new_binary_expression_impl<Check::value, Expr, Lhs, Rhs>::type;
template <template <typename Lhs, typename Rhs> class Expr, typename Lhs, typename Rhs>
using comparison_expression_t =
typename detail::comparison_expression_impl<check_comparison_t<Lhs, Rhs>::value, Expr, Lhs, Rhs>::type;
namespace detail
{
template <bool Enable, template <typename Lhs, typename... Rhs> class Expr, typename Lhs, typename... Rhs>
struct new_nary_expression_impl
struct in_expression_impl
{
using type = bad_statement;
using type = bad_expression<boolean>;
};
template <template <typename Lhs, typename... Rhs> class Expr, typename Lhs, typename... Rhs>
struct new_nary_expression_impl<true, Expr, Lhs, Rhs...>
struct in_expression_impl<true, Expr, Lhs, Rhs...>
{
using type = Expr<Lhs, Rhs...>;
};
}
template <typename Check, template <typename Lhs, typename... Rhs> class Expr, typename Lhs, typename... Rhs>
using new_nary_expression_t = typename detail::new_nary_expression_impl<Check::value, Expr, Lhs, Rhs...>::type;
using in_expression_t = typename detail::in_expression_impl<Check::value, Expr, Lhs, Rhs...>::type;
// basic operators
template <typename Expr, typename ValueType>
template <typename Expr>
struct basic_expression_operators
{
template <template <typename Lhs, typename Rhs> class NewExpr, typename T>
using _new_binary_expression_t =
new_binary_expression_t<check_rhs_comparison_operand_t<ValueType, wrap_operand_t<T>>,
NewExpr,
Expr,
wrap_operand_t<T>>;
struct _new_binary_expression
{
using type = comparison_expression_t<NewExpr, Expr, T>;
};
template <template <typename Lhs, typename Rhs> class NewExpr, typename T>
using _new_binary_expression_t = typename _new_binary_expression<NewExpr, T>::type;
// workaround for msvs bug
// template <template <typename Lhs, typename... Rhs> class NewExpr, typename... T>
// using _new_nary_expression_t =
// new_nary_expression_t<logic::all_t<check_rhs_comparison_operand_t<ValueType,
// wrap_operand_t<T>>::value...>,
// NewExpr,
// Expr,
// wrap_operand_t<T>...>;
template <template <typename Lhs, typename... Rhs> class NewExpr, typename... T>
struct _new_nary_expression
{
using type =
new_nary_expression_t<logic::all_t<check_rhs_comparison_operand_t<ValueType, wrap_operand_t<T>>::value...>,
NewExpr,
Expr,
wrap_operand_t<T>...>;
using _check = check_in_t<Expr, T...>;
using type = in_expression_t<_check, NewExpr, Expr, wrap_operand_t<T>...>;
};
template <typename T>
_new_binary_expression_t<equal_to_t, T> operator==(T t) const
auto operator==(T t) const -> _new_binary_expression_t<equal_to_t, T>
{
using rhs = wrap_operand_t<T>;
check_rhs_comparison_operand_t<ValueType, rhs>::_();
return {*static_cast<const Expr*>(this), {rhs{t}}};
}
template <typename T>
_new_binary_expression_t<not_equal_to_t, T> operator!=(T t) const
{
using rhs = wrap_operand_t<T>;
check_rhs_comparison_operand_t<ValueType, rhs>::_();
return {*static_cast<const Expr*>(this), {rhs{t}}};
}
template <typename T>
_new_binary_expression_t<less_than_t, T> operator<(T t) const
{
using rhs = wrap_operand_t<T>;
check_rhs_comparison_operand_t<ValueType, rhs>::_();
check_comparison_t<Expr, rhs>::_();
return {*static_cast<const Expr*>(this), rhs{t}};
}
template <typename T>
_new_binary_expression_t<less_equal_t, T> operator<=(T t) const
auto operator!=(T t) const -> _new_binary_expression_t<not_equal_to_t, T>
{
using rhs = wrap_operand_t<T>;
check_rhs_comparison_operand_t<ValueType, rhs>::_();
check_comparison_t<Expr, rhs>::_();
return {*static_cast<const Expr*>(this), rhs{t}};
}
template <typename T>
_new_binary_expression_t<greater_than_t, T> operator>(T t) const
auto operator<(T t) const -> _new_binary_expression_t<less_than_t, T>
{
using rhs = wrap_operand_t<T>;
check_rhs_comparison_operand_t<ValueType, rhs>::_();
check_comparison_t<Expr, rhs>::_();
return {*static_cast<const Expr*>(this), rhs{t}};
}
template <typename T>
_new_binary_expression_t<greater_equal_t, T> operator>=(T t) const
auto operator<=(T t) const -> _new_binary_expression_t<less_equal_t, T>
{
using rhs = wrap_operand_t<T>;
check_rhs_comparison_operand_t<ValueType, rhs>::_();
check_comparison_t<Expr, rhs>::_();
return {*static_cast<const Expr*>(this), rhs{t}};
}
is_null_t<Expr> is_null() const
template <typename T>
auto operator>(T t) const -> _new_binary_expression_t<greater_than_t, T>
{
using rhs = wrap_operand_t<T>;
check_comparison_t<Expr, rhs>::_();
return {*static_cast<const Expr*>(this), rhs{t}};
}
template <typename T>
auto operator>=(T t) const -> _new_binary_expression_t<greater_equal_t, T>
{
using rhs = wrap_operand_t<T>;
check_comparison_t<Expr, rhs>::_();
return {*static_cast<const Expr*>(this), rhs{t}};
}
auto is_null() const -> is_null_t<Expr>
{
return {*static_cast<const Expr*>(this)};
}
is_not_null_t<Expr> is_not_null() const
auto is_not_null() const -> is_not_null_t<Expr>
{
return {*static_cast<const Expr*>(this)};
}
sort_order_t<Expr, sort_type::asc> asc() const
auto asc() const -> sort_order_t<Expr, sort_type::asc>
{
return {*static_cast<const Expr*>(this)};
}
sort_order_t<Expr, sort_type::desc> desc() const
auto desc() const -> sort_order_t<Expr, sort_type::desc>
{
return {*static_cast<const Expr*>(this)};
}
// Hint: use value_list wrapper for containers...
// workaround for msvs bug
// template <typename... T>
// _new_nary_expression_t<in_t, T...> in(T... t) const
// {
// check_rhs_in_arguments_t<ValueType, wrap_operand_t<T>...>::_();
// return {*static_cast<const Expr*>(this), wrap_operand_t<T>{t}...};
// }
template <typename... T>
typename _new_nary_expression<in_t, T...>::type in(T... t) const
auto in(T... t) const -> typename _new_nary_expression<in_t, T...>::type
{
check_rhs_in_arguments_t<ValueType, wrap_operand_t<T>...>::_();
check_in_t<Expr, wrap_operand_t<T>...>::_();
return {*static_cast<const Expr*>(this), typename wrap_operand<T>::type{t}...};
}
// workaround for msvs bug
// template <typename... T>
// _new_nary_expression_t<not_in_t, T...> not_in(T... t) const
// {
// check_rhs_in_arguments_t<ValueType, wrap_operand_t<T>...>::_();
// return {*static_cast<const Expr*>(this), wrap_operand_t<T>{t}...};
// }
template <typename... T>
typename _new_nary_expression<not_in_t, T...>::type not_in(T... t) const
auto not_in(T... t) const -> typename _new_nary_expression<not_in_t, T...>::type
{
check_rhs_in_arguments_t<ValueType, wrap_operand_t<T>...>::_();
check_in_t<Expr, wrap_operand_t<T>...>::_();
return {*static_cast<const Expr*>(this), typename wrap_operand<T>::type{t}...};
}

View File

@ -27,7 +27,7 @@
#ifndef SQLPP_CHRONO_H
#define SQLPP_CHRONO_H
#include <chrono>
#include <date.h>
namespace sqlpp
{
@ -37,6 +37,13 @@ namespace sqlpp
using day_point = std::chrono::time_point<std::chrono::system_clock, days>;
using microsecond_point = std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds>;
#if _MSC_FULL_VER >= 190023918
// MSVC Update 2 provides floor, ceil, round, abs in chrono (which is C++17 only...)
using ::std::chrono::floor;
#else
using ::date::floor;
#endif
}
}

View File

@ -35,26 +35,26 @@
namespace sqlpp
{
template <typename Expression>
struct expression_operators<Expression, boolean> : public basic_expression_operators<Expression, boolean>
struct expression_operators<Expression, boolean> : public basic_expression_operators<Expression>
{
};
template <typename L, typename R>
struct return_type_and<L, R, binary_operand_check_t<L, is_boolean_t, R, is_boolean_t>>
struct return_type_and<L, R, unwrapped_binary_operand_check_t<L, is_boolean_t, R, is_boolean_t>>
{
using check = consistent_t;
using type = logical_and_t<wrap_operand_t<L>, wrap_operand_t<R>>;
};
template <typename L, typename R>
struct return_type_or<L, R, binary_operand_check_t<L, is_boolean_t, R, is_boolean_t>>
struct return_type_or<L, R, unwrapped_binary_operand_check_t<L, is_boolean_t, R, is_boolean_t>>
{
using check = consistent_t;
using type = logical_or_t<wrap_operand_t<L>, wrap_operand_t<R>>;
};
template <typename T, typename Defer>
struct return_type_not<T, Defer, unary_operand_check_t<T, is_boolean_t>>
struct return_type_not<T, Defer, unwrapped_unary_operand_check_t<T, is_boolean_t>>
{
using check = consistent_t;
using type = logical_not_t<wrap_operand_t<T>>;

View File

@ -35,7 +35,7 @@
namespace sqlpp
{
template <typename Expression>
struct expression_operators<Expression, day_point> : public basic_expression_operators<Expression, day_point>
struct expression_operators<Expression, day_point> : public basic_expression_operators<Expression>
{
};
}

View File

@ -61,7 +61,7 @@ namespace sqlpp
bool _is_trivial() const
{
return _t == _value_t{};
return std::chrono::operator==(_t, _value_t{});
}
_value_t _t;

View File

@ -37,7 +37,7 @@
namespace sqlpp
{
template <typename Expr>
struct expression_operators<Expr, floating_point> : public basic_expression_operators<Expr, floating_point>
struct expression_operators<Expr, floating_point> : public basic_expression_operators<Expr>
{
};

View File

@ -27,7 +27,6 @@
#ifndef SQLPP_FLOATING_POINT_RESULT_FIELD_H
#define SQLPP_FLOATING_POINT_RESULT_FIELD_H
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/exception.h>
#include <sqlpp11/result_field.h>
#include <sqlpp11/result_field_base.h>

View File

@ -38,7 +38,7 @@
namespace sqlpp
{
template <typename Expression>
struct expression_operators<Expression, integral> : public basic_expression_operators<Expression, integral>
struct expression_operators<Expression, integral> : public basic_expression_operators<Expression>
{
};

View File

@ -34,7 +34,7 @@
namespace sqlpp
{
template <typename Expression>
struct expression_operators<Expression, no_value_t> : public basic_expression_operators<Expression, no_value_t>
struct expression_operators<Expression, no_value_t> : public basic_expression_operators<Expression>
{
};
}

View File

@ -57,7 +57,7 @@ namespace sqlpp
};
template <typename Expression>
struct expression_operators<Expression, text> : public basic_expression_operators<Expression, text>
struct expression_operators<Expression, text> : public basic_expression_operators<Expression>
{
template <typename T>
using _is_valid_operand = is_valid_operand<text, T>;

View File

@ -36,7 +36,7 @@ namespace sqlpp
{
// time_point expression operators
template <typename Expression>
struct expression_operators<Expression, time_point> : public basic_expression_operators<Expression, time_point>
struct expression_operators<Expression, time_point> : public basic_expression_operators<Expression>
{
};
}

View File

@ -27,7 +27,6 @@
#ifndef SQLPP_TIME_POINT_OPERAND_H
#define SQLPP_TIME_POINT_OPERAND_H
#include <date.h>
#include <sqlpp11/chrono.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/alias_operators.h>
@ -62,7 +61,7 @@ namespace sqlpp
bool _is_trivial() const
{
return _t == _value_t{};
return std::chrono::operator==(_t, _value_t{});
}
_value_t _t;
@ -76,7 +75,7 @@ namespace sqlpp
static Context& _(const Operand& t, Context& context)
{
const auto dp = ::date::floor<::date::days>(t._t);
const auto dp = ::sqlpp::chrono::floor<::date::days>(t._t);
const auto time = ::date::make_time(t._t - dp);
const auto ymd = ::date::year_month_day{dp};
context << "TIMESTAMP '" << ymd << ' ' << time << "'";

View File

@ -27,6 +27,7 @@
#ifndef SQLPP_TIME_POINT_RESULT_FIELD_H
#define SQLPP_TIME_POINT_RESULT_FIELD_H
#include <sqlpp11/chrono.h>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/result_field.h>
#include <sqlpp11/result_field_base.h>
@ -63,7 +64,7 @@ namespace sqlpp
}
else
{
const auto dp = ::date::floor<::date::days>(e.value());
const auto dp = ::sqlpp::chrono::floor<::date::days>(e.value());
const auto time = ::date::make_time(e.value() - dp);
const auto ymd = ::date::year_month_day{dp};
os << ymd << 'T' << time;

View File

@ -1,308 +0,0 @@
/*
* 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_DETAIL_WRAP_OPERAND_H
#define SQLPP_DETAIL_WRAP_OPERAND_H
#include <date.h>
#include <string>
#include <sqlpp11/date_time_fwd.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/basic_expression_operators.h>
namespace sqlpp
{
struct integral;
struct floating_point;
struct text;
struct day_point_operand : public alias_operators<day_point_operand>
{
using _traits = make_traits<day_point, tag::is_expression, tag::is_wrapped_value>;
using _nodes = detail::type_vector<>;
using _is_aggregate_expression = std::true_type;
using _value_t = ::sqlpp::chrono::day_point;
day_point_operand() : _t{}
{
}
day_point_operand(_value_t t) : _t(t)
{
}
day_point_operand(const day_point_operand&) = default;
day_point_operand(day_point_operand&&) = default;
day_point_operand& operator=(const day_point_operand&) = default;
day_point_operand& operator=(day_point_operand&&) = default;
~day_point_operand() = default;
bool _is_trivial() const
{
return _t == _value_t{};
}
_value_t _t;
};
template <typename Context>
struct serializer_t<Context, day_point_operand>
{
using _serialize_check = consistent_t;
using Operand = day_point_operand;
static Context& _(const Operand& t, Context& context)
{
const auto ymd = ::date::year_month_day{t._t};
context << "DATE '" << ymd << "'";
return context;
}
};
template <typename Period>
struct time_point_operand : public alias_operators<time_point_operand<Period>>
{
using _traits = make_traits<time_point, tag::is_expression, tag::is_wrapped_value>;
using _nodes = detail::type_vector<>;
using _is_aggregate_expression = std::true_type;
using _value_t = std::chrono::time_point<std::chrono::system_clock, Period>;
time_point_operand() : _t{}
{
}
time_point_operand(_value_t t) : _t(t)
{
}
time_point_operand(const time_point_operand&) = default;
time_point_operand(time_point_operand&&) = default;
time_point_operand& operator=(const time_point_operand&) = default;
time_point_operand& operator=(time_point_operand&&) = default;
~time_point_operand() = default;
bool _is_trivial() const
{
return _t == _value_t{};
}
_value_t _t;
};
template <typename Context, typename Period>
struct serializer_t<Context, time_point_operand<Period>>
{
using _serialize_check = consistent_t;
using Operand = time_point_operand<Period>;
static Context& _(const Operand& t, Context& context)
{
const auto dp = ::date::floor<::date::days>(t._t);
const auto time = ::date::make_time(t._t - dp);
const auto ymd = ::date::year_month_day{dp};
context << "TIMESTAMP '" << ymd << ' ' << time << "'";
return context;
}
};
struct integral_operand : public alias_operators<integral_operand>
{
using _traits = make_traits<integral, tag::is_expression, tag::is_wrapped_value>;
using _nodes = detail::type_vector<>;
using _is_aggregate_expression = std::true_type;
using _value_t = int64_t;
integral_operand() : _t{}
{
}
integral_operand(_value_t t) : _t(t)
{
}
integral_operand(const integral_operand&) = default;
integral_operand(integral_operand&&) = default;
integral_operand& operator=(const integral_operand&) = default;
integral_operand& operator=(integral_operand&&) = default;
~integral_operand() = default;
bool _is_trivial() const
{
return _t == 0;
}
_value_t _t;
};
template <typename Context>
struct serializer_t<Context, integral_operand>
{
using _serialize_check = consistent_t;
using Operand = integral_operand;
static Context& _(const Operand& t, Context& context)
{
context << t._t;
return context;
}
};
struct floating_point_operand : public alias_operators<floating_point_operand>
{
using _traits = make_traits<floating_point, tag::is_expression, tag::is_wrapped_value>;
using _nodes = detail::type_vector<>;
using _is_aggregate_expression = std::true_type;
using _value_t = double;
floating_point_operand() : _t{}
{
}
floating_point_operand(_value_t t) : _t(t)
{
}
floating_point_operand(const floating_point_operand&) = default;
floating_point_operand(floating_point_operand&&) = default;
floating_point_operand& operator=(const floating_point_operand&) = default;
floating_point_operand& operator=(floating_point_operand&&) = default;
~floating_point_operand() = default;
bool _is_trivial() const
{
return _t == 0;
}
_value_t _t;
};
template <typename Context>
struct serializer_t<Context, floating_point_operand>
{
using _serialize_check = consistent_t;
using Operand = floating_point_operand;
static Context& _(const Operand& t, Context& context)
{
context << t._t;
return context;
}
};
struct text_operand : public alias_operators<text_operand>
{
using _traits = make_traits<text, tag::is_expression, tag::is_wrapped_value>;
using _nodes = detail::type_vector<>;
using _is_aggregate_expression = std::true_type;
using _value_t = std::string;
text_operand() : _t{}
{
}
text_operand(_value_t t) : _t(t)
{
}
text_operand(const text_operand&) = default;
text_operand(text_operand&&) = default;
text_operand& operator=(const text_operand&) = default;
text_operand& operator=(text_operand&&) = default;
~text_operand() = default;
bool _is_trivial() const
{
return _t.empty();
}
_value_t _t;
};
template <typename Context>
struct serializer_t<Context, text_operand>
{
using _serialize_check = consistent_t;
using Operand = text_operand;
static Context& _(const Operand& t, Context& context)
{
context << '\'' << context.escape(t._t) << '\'';
return context;
}
};
template <typename T, typename Enable = void>
struct wrap_operand
{
using type = T;
};
template <>
struct wrap_operand<bool, void>
{
using type = boolean_operand;
};
template <typename Period>
struct wrap_operand<std::chrono::time_point<std::chrono::system_clock, Period>, void>
{
using type = time_point_operand<Period>;
};
template <>
struct wrap_operand<std::chrono::time_point<std::chrono::system_clock, sqlpp::chrono::days>, void>
{
using type = day_point_operand;
};
template <typename T>
struct wrap_operand<T, typename std::enable_if<std::is_integral<T>::value>::type>
{
using type = integral_operand;
};
template <typename T>
struct wrap_operand<T, typename std::enable_if<std::is_floating_point<T>::value>::type>
{
using type = floating_point_operand;
};
template <typename T>
struct wrap_operand<
T,
typename std::enable_if<std::is_convertible<T, std::string>::value and not is_result_field_t<T>::value>::type>
{
using type = text_operand;
};
}
#endif

View File

@ -0,0 +1,66 @@
/*
* 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.
*/
#ifndef SQLPP_DYNAMIC_JOIN_H
#define SQLPP_DYNAMIC_JOIN_H
#include <sqlpp11/dynamic_pre_join.h>
namespace sqlpp
{
template <typename PreJoin, typename On>
struct dynamic_join_t
{
using _traits = make_traits<no_value_t, tag::is_table, tag::is_dynamic_join>;
using _nodes = detail::type_vector<PreJoin, On>;
using _can_be_null = std::false_type;
using _provided_tables = provided_tables_of<PreJoin>;
using _required_tables = detail::make_difference_set_t<required_tables_of<On>, _provided_tables>;
static_assert(is_dynamic_pre_join_t<PreJoin>::value, "lhs argument for on() has to be a pre join");
static_assert(required_tables_of<PreJoin>::size::value == 0, "joined tables must not depend on other tables");
static_assert(is_on_t<On>::value, "invalid on expression in join().on()");
PreJoin _pre_join;
On _on;
};
template <typename Context, typename PreJoin, typename On>
struct serializer_t<Context, dynamic_join_t<PreJoin, On>>
{
using _serialize_check = serialize_check_of<Context, PreJoin, On>;
using T = dynamic_join_t<PreJoin, On>;
static Context& _(const T& t, Context& context)
{
serialize(t._pre_join, context);
serialize(t._on, context);
return context;
}
};
}
#endif

View File

@ -0,0 +1,170 @@
/*
* 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.
*/
#ifndef SQLPP_DYNAMIC_PRE_JOIN_H
#define SQLPP_DYNAMIC_PRE_JOIN_H
#include <sqlpp11/join_types.h>
#include <sqlpp11/on.h>
namespace sqlpp
{
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_pre_join_table_t, "argument of dynamic_join() has to be a table");
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_pre_join_no_join_t, "argument of dynamic_join() must not be a table");
template <typename Table>
struct check_dynamic_pre_join
{
using type =
static_combined_check_t<static_check_t<is_table_t<Table>::value, assert_dynamic_pre_join_table_t>,
static_check_t<not is_join_t<Table>::value, assert_dynamic_pre_join_no_join_t>>;
};
template <typename Table>
using check_dynamic_pre_join_t = typename check_dynamic_pre_join<Table>::type;
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_join_consist_of_pre_join_and_on_t,
"dynamic join has to consist of a dynamic pre_join and a join condition");
SQLPP_PORTABLE_STATIC_ASSERT(assert_dynamic_join_no_table_dependencies_t,
"dynamically joined tables must not depend on other tables");
template <typename PreJoin, typename On>
struct check_dynamic_join
{
using type = static_combined_check_t<
static_check_t<is_dynamic_pre_join_t<PreJoin>::value, assert_dynamic_join_consist_of_pre_join_and_on_t>,
static_check_t<is_on_t<On>::value, assert_dynamic_join_consist_of_pre_join_and_on_t>,
static_check_t<required_tables_of<PreJoin>::size::value == 0, assert_dynamic_join_no_table_dependencies_t>>;
};
template <typename PreJoin, typename On>
using check_dynamic_join_t = typename check_dynamic_join<PreJoin, On>::type;
template <typename PreJoin, typename Expr>
struct check_dynamic_join_on
{
using type = static_combined_check_t<check_on_t<Expr>, check_dynamic_join_t<PreJoin, on_t<Expr>>>;
};
template <typename PreJoin, typename Expr>
using check_dynamic_join_on_t = typename check_dynamic_join_on<PreJoin, Expr>::type;
template <typename PreJoin, typename On>
struct dynamic_join_t;
template <typename JoinType, typename Rhs>
struct dynamic_pre_join_t
{
using _traits = make_traits<no_value_t, tag::is_table, tag::is_dynamic_pre_join>;
using _nodes = detail::type_vector<Rhs>;
using _can_be_null = std::false_type;
static_assert(is_table_t<Rhs>::value, "rhs argument for dynamic_join() has to be a table");
static_assert(not is_join_t<Rhs>::value, "rhs argument for dynamic_join must not be a join");
static_assert(required_tables_of<dynamic_pre_join_t>::size::value == 0,
"joined tables must not depend on other tables");
template <typename Expr>
auto on(Expr expr) const -> typename std::conditional<check_dynamic_join_on_t<dynamic_pre_join_t, Expr>::value,
dynamic_join_t<dynamic_pre_join_t, on_t<Expr>>,
bad_statement>::type
{
check_dynamic_join_on_t<dynamic_pre_join_t, Expr>::_();
return {*this, {expr}};
}
Rhs _rhs;
};
template <typename Context, typename JoinType, typename Rhs>
struct serializer_t<Context, dynamic_pre_join_t<JoinType, Rhs>>
{
using _serialize_check = serialize_check_of<Context, Rhs>;
using T = dynamic_pre_join_t<JoinType, Rhs>;
static Context& _(const T& t, Context& context)
{
context << JoinType::_name;
context << " JOIN ";
serialize(t._rhs, context);
return context;
}
};
template <typename JoinType, typename Table>
using make_dynamic_pre_join_t = typename std::conditional<check_dynamic_pre_join_t<Table>::value,
dynamic_pre_join_t<JoinType, Table>,
bad_statement>::type;
template <typename Table>
auto dynamic_join(Table table) -> make_dynamic_pre_join_t<inner_join_t, Table>
{
check_dynamic_pre_join_t<Table>::_();
return {table};
}
template <typename Table>
auto dynamic_inner_join(Table table) -> make_dynamic_pre_join_t<inner_join_t, Table>
{
check_dynamic_pre_join_t<Table>::_();
return {table};
}
template <typename Table>
auto dynamic_left_outer_join(Table table) -> make_dynamic_pre_join_t<left_outer_join_t, Table>
{
check_dynamic_pre_join_t<Table>::_();
return {table};
}
template <typename Table>
auto dynamic_right_outer_join(Table table) -> make_dynamic_pre_join_t<right_outer_join_t, Table>
{
check_dynamic_pre_join_t<Table>::_();
return {table};
}
template <typename Table>
auto dynamic_outer_join(Table table) -> make_dynamic_pre_join_t<outer_join_t, Table>
{
check_dynamic_pre_join_t<Table>::_();
return {table};
}
template <typename Table>
auto dynamic_cross_join(Table table) ->
typename std::conditional<check_dynamic_pre_join_t<Table>::value,
dynamic_join_t<dynamic_pre_join_t<cross_join_t, Table>, on_t<unconditional_t>>,
bad_statement>::type
{
check_dynamic_pre_join_t<Table>::_();
return {dynamic_pre_join_t<cross_join_t, Table>{table}, {}};
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -29,6 +29,7 @@
#include <vector>
#include <string>
#include <sqlpp11/no_name.h>
#include <sqlpp11/named_interpretable.h>
namespace sqlpp
@ -56,13 +57,7 @@ namespace sqlpp
template <>
struct dynamic_select_column_list<void>
{
struct _names_t
{
static constexpr size_t size()
{
return 0;
}
};
using _names_t = no_name_t;
_names_t _dynamic_expression_names;
static constexpr bool empty()
@ -70,6 +65,37 @@ namespace sqlpp
return true;
}
};
template <typename Context, typename Db>
struct serializer_t<Context, dynamic_select_column_list<Db>>
{
using T = dynamic_select_column_list<Db>;
static Context& _(const T& t, Context& context)
{
bool first = true;
for (const auto column : t._dynamic_columns)
{
if (first)
first = false;
else
context << ',';
serialize(column, context);
}
return context;
}
};
template <typename Context>
struct serializer_t<Context, dynamic_select_column_list<void>>
{
using T = dynamic_select_column_list<void>;
static Context& _(const T&, Context& context)
{
return context;
}
};
}
#endif

View File

@ -48,7 +48,7 @@ namespace sqlpp
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
binary_expression_t(_lhs_t lhs, _rhs_t rhs) : _lhs(lhs), _rhs(rhs)
binary_expression_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs)
{
}
@ -96,7 +96,7 @@ namespace sqlpp
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
binary_expression_t(Lhs lhs, _rhs_t rhs) : _lhs(lhs), _rhs(rhs)
binary_expression_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs)
{
}

View File

@ -80,7 +80,7 @@ namespace sqlpp
struct return_type_plus
{
using check = assert_valid_operands;
using type = bad_expression<boolean>;
using type = bad_expression<value_type_of<L>>;
};
template <typename L, typename R>
using return_type_plus_t = typename return_type_plus<L, R>::type;
@ -89,7 +89,7 @@ namespace sqlpp
struct return_type_minus
{
using check = assert_valid_operands;
using type = bad_expression<boolean>;
using type = bad_expression<value_type_of<L>>;
};
template <typename L, typename R>
using return_type_minus_t = typename return_type_minus<L, R>::type;
@ -98,7 +98,7 @@ namespace sqlpp
struct return_type_multiplies
{
using check = assert_valid_operands;
using type = bad_expression<boolean>;
using type = bad_expression<value_type_of<L>>;
};
template <typename L, typename R>
using return_type_multiplies_t = typename return_type_multiplies<L, R>::type;
@ -107,7 +107,7 @@ namespace sqlpp
struct return_type_divides
{
using check = assert_valid_operands;
using type = bad_expression<boolean>;
using type = bad_expression<value_type_of<L>>;
};
template <typename L, typename R>
using return_type_divides_t = typename return_type_divides<L, R>::type;
@ -116,7 +116,7 @@ namespace sqlpp
struct return_type_modulus
{
using check = assert_valid_operands;
using type = bad_expression<boolean>;
using type = bad_expression<value_type_of<L>>;
};
template <typename L, typename R>
using return_type_modulus_t = typename return_type_modulus<L, R>::type;
@ -125,7 +125,7 @@ namespace sqlpp
struct return_type_unary_plus
{
using check = assert_valid_operands;
using type = bad_expression<boolean>;
using type = bad_expression<value_type_of<T>>;
};
template <typename T, typename Defer>
using return_type_unary_plus_t = typename return_type_unary_plus<T, Defer>::type;
@ -134,7 +134,7 @@ namespace sqlpp
struct return_type_unary_minus
{
using check = assert_valid_operands;
using type = bad_expression<boolean>;
using type = bad_expression<value_type_of<T>>;
};
template <typename T, typename Defer>
using return_type_unary_minus_t = typename return_type_unary_minus<T, Defer>::type;

View File

@ -1,220 +0,0 @@
/*
* 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_EXTRA_TABLES_H
#define SQLPP_EXTRA_TABLES_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/logic.h>
#include <sqlpp11/policy_update.h>
namespace sqlpp
{
template <typename... Tables>
struct extra_tables_data_t
{
extra_tables_data_t()
{
}
extra_tables_data_t(const extra_tables_data_t&) = default;
extra_tables_data_t(extra_tables_data_t&&) = default;
extra_tables_data_t& operator=(const extra_tables_data_t&) = default;
extra_tables_data_t& operator=(extra_tables_data_t&&) = default;
~extra_tables_data_t() = default;
};
// EXTRA_TABLES
template <typename... Tables>
struct extra_tables_t
{
using _traits = make_traits<no_value_t, tag::is_extra_tables>;
using _nodes = detail::type_vector<>;
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Tables>...>;
using _extra_tables = detail::type_set<Tables...>;
// Data
using _data_t = extra_tables_data_t<Tables...>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
_impl_t() = default;
_impl_t(const _data_t& data) : _data(data)
{
}
_data_t _data;
};
// Base template to be inherited by the statement
template <typename Policies>
struct _base_t
{
using _data_t = extra_tables_data_t<Tables...>;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
template <typename... Args>
_base_t(Args&&... args)
: extra_tables{std::forward<Args>(args)...}
{
}
_impl_t<Policies> extra_tables;
_impl_t<Policies>& operator()()
{
return extra_tables;
}
const _impl_t<Policies>& operator()() const
{
return extra_tables;
}
template <typename T>
static auto _get_member(T t) -> decltype(t.extra_tables)
{
return t.extra_tables;
}
using _consistency_check = consistent_t;
};
};
// NO EXTRA TABLES YET
struct no_extra_tables_t
{
using _traits = make_traits<no_value_t, tag::is_noop>;
using _nodes = detail::type_vector<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
_impl_t() = default;
_impl_t(const _data_t& data) : _data(data)
{
}
_data_t _data;
};
// Base template to be inherited by the statement
template <typename Policies>
struct _base_t
{
using _data_t = no_data_t;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
template <typename... Args>
_base_t(Args&&... args)
: no_extra_tables{std::forward<Args>(args)...}
{
}
_impl_t<Policies> no_extra_tables;
_impl_t<Policies>& operator()()
{
return no_extra_tables;
}
const _impl_t<Policies>& operator()() const
{
return no_extra_tables;
}
template <typename T>
static auto _get_member(T t) -> decltype(t.no_extra_tables)
{
return t.no_extra_tables;
}
template <typename Check, typename T>
using _new_statement_t = new_statement_t<Check::value, Policies, no_extra_tables_t, T>;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269
// template <typename... T>
// using _check = logic::all_t<is_table_t<T>::value...>;
template <typename... T>
struct _check : logic::all_t<is_table_t<T>::value...>
{
};
using _consistency_check = consistent_t;
template <typename... Tables>
auto extra_tables(Tables... tables) const -> _new_statement_t<_check<Tables...>, extra_tables_t<Tables...>>
{
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in extra_tables()");
return _extra_tables_impl<void>(_check<Tables...>{}, tables...);
}
private:
template <typename Database, typename... Tables>
auto _extra_tables_impl(const std::false_type&, Tables... tables) const -> bad_statement;
template <typename Database, typename... Tables>
auto _extra_tables_impl(const std::true_type&, Tables...) const
-> _new_statement_t<std::true_type, extra_tables_t<Tables...>>
{
static_assert(required_tables_of<extra_tables_t<Tables...>>::size::value == 0,
"at least one table depends on another table in extra_tables()");
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/feedback/details/2173198
// using _unique_table_names = detail::transform_set_t<name_of, _unique_tables>;
using _unique_table_names = detail::make_name_of_set_t<_unique_tables>;
static_assert(_number_of_tables == _unique_tables::size::value,
"at least one duplicate table detected in extra_tables()");
static_assert(_number_of_tables == _unique_table_names::size::value,
"at least one duplicate table name detected in extra_tables()");
return {static_cast<const derived_statement_t<Policies>&>(*this), extra_tables_data_t<Tables...>{}};
}
};
};
// Interpreters
template <typename Context, typename Database, typename... Tables>
struct serializer_t<Context, extra_tables_data_t<Database, Tables...>>
{
using _serialize_check = serialize_check_of<Context, Tables...>;
using T = extra_tables_data_t<Database, Tables...>;
static Context& _(const T&, Context& context)
{
return context;
}
};
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -35,14 +35,15 @@
#include <sqlpp11/logic.h>
#include <sqlpp11/detail/sum.h>
#include <sqlpp11/policy_update.h>
#include <sqlpp11/dynamic_join.h>
namespace sqlpp
{
// FROM DATA
template <typename Database, typename... Tables>
template <typename Database, typename Table>
struct from_data_t
{
from_data_t(Tables... tables) : _tables(tables...)
from_data_t(Table table) : _table(table)
{
}
@ -52,60 +53,86 @@ namespace sqlpp
from_data_t& operator=(from_data_t&&) = default;
~from_data_t() = default;
std::tuple<Tables...> _tables;
Table _table;
interpretable_list_t<Database> _dynamic_tables;
};
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_add_dynamic, "from::add() requires a dynamic_from");
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_add_not_dynamic_pre_join, "join condition missing");
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_add_dynamic_join, "from::add(X) requires X to be a dynamic join");
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_add_unique_names,
"from::add() must not add table names already used in from");
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_add_no_required_tables,
"from::add():dynamic join condition depends on "
"tables not statically known, use "
"without_table_check() to express the intent");
template <typename From, typename DynamicJoin>
struct check_from_add
{
using _known_tables = provided_tables_of<typename From::_table_t>; // Hint: Joins contain more than one table
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/feedback/details/2173198
// using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
using _known_table_names = detail::make_name_of_set_t<_known_tables>;
using _joined_tables = provided_tables_of<DynamicJoin>;
using _joined_table_names = detail::make_name_of_set_t<_joined_tables>;
using _required_tables = required_tables_of<DynamicJoin>;
using type = static_combined_check_t<
static_check_t<From::_is_dynamic::value, assert_from_add_dynamic>,
static_check_t<not is_dynamic_pre_join_t<DynamicJoin>::value, assert_from_add_not_dynamic_pre_join>,
static_check_t<is_dynamic_join_t<DynamicJoin>::value, assert_from_add_dynamic_join>,
static_check_t<detail::is_disjunct_from<_joined_table_names, _known_table_names>::value,
assert_from_add_unique_names>,
static_check_t<detail::is_subset_of<_required_tables, _known_tables>::value,
assert_from_add_no_required_tables>,
sqlpp::serialize_check_t<serializer_context_of<typename From::_database_t>, DynamicJoin>>;
};
template <typename From, typename DynamicJoin>
using check_from_add_t = typename check_from_add<From, DynamicJoin>::type;
// FROM
template <typename Database, typename... Tables>
template <typename Database, typename Table>
struct from_t
{
using _traits = make_traits<no_value_t, tag::is_from>;
using _nodes = detail::type_vector<Tables...>;
using _is_dynamic = is_database<Database>;
using _nodes = detail::type_vector<Table>;
// Data
using _data_t = from_data_t<Database, Tables...>;
using _data_t = from_data_t<Database, Table>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
using _database_t = Database;
using _is_dynamic = is_database<_database_t>;
using _table_t = Table;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
_impl_t() = default;
_impl_t(const _data_t& data) : _data(data)
{
}
template <typename Table>
void add(Table table)
template <typename DynamicJoin>
auto add(DynamicJoin dynamicJoin) ->
typename std::conditional<check_from_add_t<_impl_t, DynamicJoin>::value, void, bad_statement>::type
{
static_assert(_is_dynamic::value, "from::add() must not be called for static from()");
static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
using _known_tables =
detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/feedback/details/2173198
// using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
using _known_table_names = detail::make_name_of_set_t<_known_tables>;
static_assert(not detail::is_element_of<typename Table::_alias_t, _known_table_names>::value,
"Must not use the same table name twice in from()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Table>;
_serialize_check::_();
using ok = logic::all_t<_is_dynamic::value, is_table_t<Table>::value, _serialize_check::type::value>;
_add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
using Check = check_from_add_t<_impl_t, DynamicJoin>;
Check::_();
return _add_impl(dynamicJoin, Check{});
}
private:
template <typename Table>
void _add_impl(Table table, const std::true_type&)
template <typename DynamicJoin>
auto _add_impl(DynamicJoin dynamicJoin, const std::true_type&) -> void
{
return _data._dynamic_tables.emplace_back(from_table(table));
_data._dynamic_tables.emplace_back(from_table(dynamicJoin));
}
template <typename Table>
void _add_impl(Table table, const std::false_type&);
template <typename DynamicJoin>
auto _add_impl(DynamicJoin dynamicJoin, const std::false_type&) -> bad_statement;
public:
_data_t _data;
@ -115,7 +142,7 @@ namespace sqlpp
template <typename Policies>
struct _base_t
{
using _data_t = from_data_t<Database, Tables...>;
using _data_t = from_data_t<Database, Table>;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
template <typename... Args>
@ -145,6 +172,39 @@ namespace sqlpp
};
};
SQLPP_PORTABLE_STATIC_ASSERT(
assert_from_not_pre_join_t,
"from() argument is a pre join, please use an explicit on() condition or unconditionally()");
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_table_t, "from() argument has to be a table or join expression");
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_dependency_free_t, "at least one table depends on another table in from()");
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_no_duplicates_t, "at least one duplicate table name detected in from()");
SQLPP_PORTABLE_STATIC_ASSERT(assert_from_dynamic_statement_dynamic_t,
"dynamic_from must not be called in a static statement");
template <typename Table>
struct check_from
{
using type = static_combined_check_t<
static_check_t<not is_pre_join_t<Table>::value, assert_from_not_pre_join_t>,
static_check_t<is_table_t<Table>::value, assert_from_table_t>,
static_check_t<required_tables_of<Table>::size::value == 0, assert_from_dependency_free_t>,
static_check_t<provided_tables_of<Table>::size::value ==
detail::make_name_of_set_t<provided_tables_of<Table>>::size::value,
assert_from_no_duplicates_t>>;
};
template <typename Table>
using check_from_t = typename check_from<Table>::type;
template <typename Table>
using check_from_static_t = check_from_t<Table>;
template <typename Database, typename Table>
using check_from_dynamic_t = static_combined_check_t<
static_check_t<not std::is_same<Database, void>::value, assert_from_dynamic_statement_dynamic_t>,
check_from_t<Table>>;
struct no_from_t
{
using _traits = make_traits<no_value_t, tag::is_noop>;
@ -197,86 +257,72 @@ namespace sqlpp
using _database_t = typename Policies::_database_t;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269
// template <typename... T>
// using _check = logic::all_t<is_table_t<T>::value...>;
template <typename... T>
struct _check : logic::all_t<is_table_t<T>::value...>
{
};
template <typename Check, typename T>
using _new_statement_t = new_statement_t<Check::value, Policies, no_from_t, T>;
using _consistency_check = consistent_t;
template <typename... Tables>
auto from(Tables... tables) const -> _new_statement_t<_check<Tables...>, from_t<void, from_table_t<Tables>...>>
template <typename Table>
auto from(Table table) const -> _new_statement_t<check_from_static_t<Table>, from_t<void, from_table_t<Table>>>
{
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()");
return _from_impl<void>(_check<Tables...>{}, tables...);
using Check = check_from_static_t<Table>;
Check{}._();
return _from_impl<void>(Check{}, table);
}
template <typename... Tables>
auto dynamic_from(Tables... tables) const
-> _new_statement_t<_check<Tables...>, from_t<_database_t, from_table_t<Tables>...>>
template <typename Table>
auto dynamic_from(Table table) const
-> _new_statement_t<check_from_dynamic_t<_database_t, Table>, from_t<_database_t, from_table_t<Table>>>
{
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()");
return _from_impl<_database_t>(_check<Tables...>{}, tables...);
using Check = check_from_dynamic_t<_database_t, Table>;
Check{}._();
return _from_impl<_database_t>(Check{}, table);
}
private:
template <typename Database, typename... Tables>
auto _from_impl(const std::false_type&, Tables... tables) const -> bad_statement;
template <typename Database, typename Table>
auto _from_impl(const std::false_type&, Table table) const -> bad_statement;
template <typename Database, typename... Tables>
auto _from_impl(const std::true_type&, Tables... tables) const
-> _new_statement_t<std::true_type, from_t<Database, from_table_t<Tables>...>>
template <typename Database, typename Table>
auto _from_impl(const std::true_type&, Table table) const
-> _new_statement_t<std::true_type, from_t<Database, from_table_t<Table>>>
{
static_assert(required_tables_of<from_t<Database, Tables...>>::size::value == 0,
"at least one table depends on another table in from()");
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
using _unique_table_names = detail::make_name_of_set_t<_unique_tables>;
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()");
return {static_cast<const derived_statement_t<Policies>&>(*this),
from_data_t<Database, from_table_t<Tables>...>{from_table(tables)...}};
from_data_t<Database, from_table_t<Table>>{from_table(table)}};
}
};
};
// Interpreters
template <typename Context, typename Database, typename... Tables>
struct serializer_t<Context, from_data_t<Database, Tables...>>
template <typename Context, typename Database, typename Table>
struct serializer_t<Context, from_data_t<Database, Table>>
{
using _serialize_check = serialize_check_of<Context, Tables...>;
using T = from_data_t<Database, Tables...>;
using _serialize_check = serialize_check_of<Context, Table>;
using T = from_data_t<Database, Table>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Tables) == 0 and t._dynamic_tables.empty())
return context;
context << " FROM ";
interpret_tuple(t._tables, ',', context);
if (sizeof...(Tables) and not t._dynamic_tables.empty())
context << ',';
interpret_list(t._dynamic_tables, ',', context);
serialize(t._table, context);
if (not t._dynamic_tables.empty())
{
interpret_list(t._dynamic_tables, "", context);
}
return context;
}
};
template <typename... T>
auto from(T&&... t) -> decltype(statement_t<void, no_from_t>().from(std::forward<T>(t)...))
template <typename T>
auto from(T&& t) -> decltype(statement_t<void, no_from_t>().from(std::forward<T>(t)))
{
return statement_t<void, no_from_t>().from(std::forward<T>(t)...);
return statement_t<void, no_from_t>().from(std::forward<T>(t));
}
template <typename Database, typename T>
auto dynamic_from(const Database&, T&& t)
-> decltype(statement_t<Database, no_from_t>().dynamic_from(std::forward<T>(t)))
{
return statement_t<Database, no_from_t>().dynamic_from(std::forward<T>(t));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -42,19 +42,12 @@
#include <sqlpp11/value_type.h>
#include <sqlpp11/verbatim.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim
#include <sqlpp11/verbatim_table.h>
#include <sqlpp11/value.h>
#include <sqlpp11/value_or_null.h>
#include <sqlpp11/eval.h>
namespace sqlpp
{
template <typename T>
auto value(T t) -> wrap_operand_t<T>
{
static_assert(is_wrapped_value_t<wrap_operand_t<T>>::value,
"value() is to be called with non-sql-type like int, or string");
return {t};
}
template <typename Expression, typename Db>
auto flatten(const Expression& exp, Db& db) -> verbatim_t<value_type_of<Expression>>
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -85,17 +85,11 @@ namespace sqlpp
}
template <typename Expression>
void add_ntc(Expression expression)
{
add<Expression, std::false_type>(expression);
}
template <typename Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
{
static_assert(_is_dynamic::value, "add() must not be called for static group_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in group_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value,
static_assert(Policies::template _no_unknown_tables<Expression>::value,
"expression uses tables unknown to this statement in group_by::add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
_serialize_check::_();
@ -277,6 +271,19 @@ namespace sqlpp
return context;
}
};
template <typename... T>
auto group_by(T&&... t) -> decltype(statement_t<void, no_group_by_t>().group_by(std::forward<T>(t)...))
{
return statement_t<void, no_group_by_t>().group_by(std::forward<T>(t)...);
}
template <typename Database, typename... T>
auto dynamic_group_by(const Database&, T&&... t)
-> decltype(statement_t<Database, no_group_by_t>().dynamic_group_by(std::forward<T>(t)...))
{
return statement_t<Database, no_group_by_t>().dynamic_group_by(std::forward<T>(t)...);
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -28,6 +28,7 @@
#define SQLPP_HAVING_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/value.h>
#include <sqlpp11/expression.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h>
@ -37,10 +38,10 @@
namespace sqlpp
{
// HAVING DATA
template <typename Database, typename... Expressions>
template <typename Database, typename Expression>
struct having_data_t
{
having_data_t(Expressions... expressions) : _expressions(expressions...)
having_data_t(Expression expression) : _expression(expression)
{
}
@ -50,25 +51,28 @@ namespace sqlpp
having_data_t& operator=(having_data_t&&) = default;
~having_data_t() = default;
std::tuple<Expressions...> _expressions;
Expression _expression;
interpretable_list_t<Database> _dynamic_expressions;
};
SQLPP_PORTABLE_STATIC_ASSERT(
assert_no_unknown_tables_in_having_t,
assert_having_no_unknown_tables_t,
"at least one having-expression requires a table which is otherwise not known in the statement");
SQLPP_PORTABLE_STATIC_ASSERT(assert_having_no_non_aggregates_t,
"having expression not built out of aggregate expressions");
// HAVING
template <typename Database, typename... Expressions>
template <typename Database, typename Expression>
struct having_t
{
using _traits = make_traits<no_value_t, tag::is_having>;
using _nodes = detail::type_vector<Expressions...>;
using _nodes = detail::type_vector<Expression>;
using _is_dynamic = is_database<Database>;
// Data
using _data_t = having_data_t<Database, Expressions...>;
using _data_t = having_data_t<Database, Expression>;
// Member implementation with data and methods
template <typename Policies>
@ -80,36 +84,30 @@ namespace sqlpp
{
}
template <typename Expression>
void add_ntc(Expression expression)
{
add<Expression, std::false_type>(expression);
}
template <typename Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
template <typename Expr>
void add(Expr expression)
{
static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value,
static_assert(is_expression_t<Expr>::value, "invalid expression argument in having::add()");
static_assert(Policies::template _no_unknown_tables<Expr>::value,
"expression uses tables unknown to this statement in having::add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expr>;
_serialize_check::_();
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expression>::value, _serialize_check::type::value>;
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expr>::value, _serialize_check::type::value>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template <typename Expression>
void _add_impl(Expression expression, const std::true_type&)
template <typename Expr>
void _add_impl(Expr expression, const std::true_type&)
{
return _data._dynamic_expressions.emplace_back(expression);
}
template <typename Expression>
void _add_impl(Expression expression, const std::false_type&);
template <typename Expr>
void _add_impl(Expr expression, const std::false_type&);
public:
_data_t _data;
@ -119,7 +117,7 @@ namespace sqlpp
template <typename Policies>
struct _base_t
{
using _data_t = having_data_t<Database, Expressions...>;
using _data_t = having_data_t<Database, Expression>;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
template <typename... Args>
@ -144,12 +142,46 @@ namespace sqlpp
return t.having;
}
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<having_t>::value,
using _table_check = typename std::conditional<Policies::template _no_unknown_tables<having_t>::value,
consistent_t,
assert_no_unknown_tables_in_having_t>::type;
assert_having_no_unknown_tables_t>::type;
using _aggregate_check = typename std::conditional<Policies::template _no_non_aggregates<Expression>::value,
consistent_t,
assert_having_no_non_aggregates_t>::type;
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t, _table_check, _aggregate_check>;
};
};
SQLPP_PORTABLE_STATIC_ASSERT(assert_having_not_cpp_bool_t,
"having() argument has to be an sqlpp boolean expression. Please use "
"sqlpp::value(bool_expresson) if you really want to use a bool value here");
SQLPP_PORTABLE_STATIC_ASSERT(assert_having_boolean_expression_t,
"having() argument has to be an sqlpp boolean expression.");
SQLPP_PORTABLE_STATIC_ASSERT(assert_having_dynamic_statement_dynamic_t,
"dynamic_having() must not be called in a static statement");
template <typename Expression>
struct check_having
{
using type =
static_combined_check_t<static_check_t<is_not_cpp_bool_t<Expression>::value, assert_having_not_cpp_bool_t>,
static_check_t<is_expression_t<Expression>::value, assert_having_boolean_expression_t>,
static_check_t<is_boolean_t<Expression>::value, assert_having_boolean_expression_t>>;
};
template <typename Expression>
using check_having_t = typename check_having<Expression>::type;
template <typename Expression>
using check_having_static_t = check_having_t<Expression>;
template <typename Database, typename Expression>
using check_having_dynamic_t = static_combined_check_t<
static_check_t<not std::is_same<Database, void>::value, assert_having_dynamic_statement_dynamic_t>,
check_having_t<Expression>>;
// NO HAVING YET
struct no_having_t
{
@ -216,59 +248,76 @@ namespace sqlpp
using _consistency_check = consistent_t;
template <typename... Expressions>
auto having(Expressions... expressions) const
-> _new_statement_t<_check<Expressions...>, having_t<void, Expressions...>>
template <typename Expression>
auto having(Expression expression) const
-> _new_statement_t<check_having_static_t<Expression>, having_t<void, Expression>>
{
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in having()");
static_assert(sizeof...(Expressions), "at least one expression argument required in having()");
using Check = check_having_static_t<Expression>;
Check{}._();
return _having_impl<void>(_check<Expressions...>{}, expressions...);
return _having_impl<void>(Check{}, expression);
}
template <typename... Expressions>
auto dynamic_having(Expressions... expressions) const
-> _new_statement_t<_check<Expressions...>, having_t<_database_t, Expressions...>>
template <typename Expression>
auto dynamic_having(Expression expression) const
-> _new_statement_t<check_having_dynamic_t<_database_t, Expression>, having_t<_database_t, Expression>>
{
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in having()");
static_assert(not std::is_same<_database_t, void>::value,
"dynamic_having must not be called in a static statement");
return _having_impl<_database_t>(_check<Expressions...>{}, expressions...);
using Check = check_having_dynamic_t<_database_t, Expression>;
Check{}._();
return _having_impl<_database_t>(Check{}, expression);
}
auto dynamic_having() const -> _new_statement_t<check_where_dynamic_t<_database_t, boolean_operand>,
having_t<_database_t, boolean_operand>>
{
return dynamic_having(::sqlpp::value(true));
}
private:
template <typename Database, typename... Expressions>
auto _having_impl(const std::false_type&, Expressions... expressions) const -> bad_statement;
template <typename Database, typename Expression>
auto _having_impl(const std::false_type&, Expression expression) const -> bad_statement;
template <typename Database, typename... Expressions>
auto _having_impl(const std::true_type&, Expressions... expressions) const
-> _new_statement_t<std::true_type, having_t<Database, Expressions...>>
template <typename Database, typename Expression>
auto _having_impl(const std::true_type&, Expression expression) const
-> _new_statement_t<std::true_type, having_t<Database, Expression>>
{
return {static_cast<const derived_statement_t<Policies>&>(*this),
having_data_t<Database, Expressions...>{expressions...}};
having_data_t<Database, Expression>{expression}};
}
};
};
// Interpreters
template <typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, having_data_t<Database, Expressions...>>
template <typename Context, typename Database, typename Expression>
struct serializer_t<Context, having_data_t<Database, Expression>>
{
using _serialize_check = serialize_check_of<Context, Expressions...>;
using T = having_data_t<Database, Expressions...>;
using _serialize_check = serialize_check_of<Context, Expression>;
using T = having_data_t<Database, Expression>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " HAVING ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
serialize(t._expression, context);
if (not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
template <typename T>
auto having(T&& t) -> decltype(statement_t<void, no_having_t>().having(std::forward<T>(t)))
{
return statement_t<void, no_having_t>().having(std::forward<T>(t));
}
template <typename Database, typename T>
auto dynamic_having(const Database&, T&& t)
-> decltype(statement_t<Database, no_having_t>().dynamic_having(std::forward<T>(t)))
{
return statement_t<Database, no_having_t>().dynamic_having(std::forward<T>(t));
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -252,12 +252,6 @@ namespace sqlpp
}
template <typename Assignment>
void add_ntc(Assignment assignment)
{
add<Assignment, std::false_type>(assignment);
}
template <typename Assignment, typename TableCheckRequired = std::true_type>
void add(Assignment assignment)
{
static_assert(_is_dynamic::value, "add must not be called for static from()");
@ -266,7 +260,7 @@ namespace sqlpp
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value,
"Must not assign value to column twice");
static_assert(not must_not_insert_t<lhs_t<Assignment>>::value, "add() argument must not be used in insert");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value,
static_assert(Policies::template _no_unknown_tables<Assignment>::value,
"add() contains a column from a foreign table");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Assignment>;
_serialize_check::_();
@ -641,6 +635,20 @@ namespace sqlpp
return context;
}
};
template <typename... Assignments>
auto insert_set(Assignments... assignments)
-> decltype(statement_t<void, no_insert_value_list_t>().set(assignments...))
{
return statement_t<void, no_insert_value_list_t>().set(assignments...);
}
template <typename Database, typename... Assignments>
auto dynamic_insert_set(Assignments... assignments)
-> decltype(statement_t<Database, no_insert_value_list_t>().dynamic_set(assignments...))
{
return statement_t<Database, no_insert_value_list_t>().dynamic_set(assignments...);
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,125 +27,70 @@
#ifndef SQLPP_JOIN_H
#define SQLPP_JOIN_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/join_types.h>
#include <sqlpp11/pre_join.h>
#include <sqlpp11/on.h>
#include <sqlpp11/noop.h>
namespace sqlpp
{
struct inner_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables =
detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " INNER ";
};
struct outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
static constexpr const char* _name = " OUTER ";
};
struct left_outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " LEFT OUTER ";
};
struct right_outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
static constexpr const char* _name = " RIGHT OUTER ";
};
template <typename JoinType, typename Lhs, typename Rhs, typename On = noop>
template <typename PreJoin, typename On>
struct join_t
{
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
using _nodes = detail::type_vector<Lhs, Rhs>;
using _nodes = detail::type_vector<PreJoin, On>;
using _can_be_null = std::false_type;
using _provided_tables = provided_tables_of<PreJoin>;
using _required_tables = detail::make_difference_set_t<required_tables_of<On>, _provided_tables>;
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(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
static_assert(is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value,
"joined tables must not be identical");
static_assert(required_tables_of<join_t>::size::value == 0, "joined tables must not depend on other tables");
template <typename OnT>
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
template <typename... Expr>
auto on(Expr... expr) -> set_on_t<on_t<void, Expr...>>
template <typename T>
auto join(T t) const -> decltype(::sqlpp::join(*this, t))
{
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
static_assert(logic::all_t<is_expression_t<Expr>::value...>::value,
"at least one argument is not an expression in on()");
return {_lhs, _rhs, {std::tuple<Expr...>{expr...}, {}}};
return ::sqlpp::join(*this, t);
}
template <typename T>
join_t<inner_join_t, join_t, T> join(T t)
auto inner_join(T t) const -> decltype(::sqlpp::inner_join(*this, t))
{
static_assert(not is_noop<On>::value, "join type requires on()");
return {*this, t, {}};
return ::sqlpp::inner_join(*this, t);
}
template <typename T>
join_t<inner_join_t, join_t, T> inner_join(T t)
auto left_outer_join(T t) const -> decltype(::sqlpp::left_outer_join(*this, t))
{
static_assert(not is_noop<On>::value, "join type requires on()");
return {*this, t, {}};
return ::sqlpp::left_outer_join(*this, t);
}
template <typename T>
join_t<outer_join_t, join_t, T> outer_join(T t)
auto right_outer_join(T t) const -> decltype(::sqlpp::right_outer_join(*this, t))
{
static_assert(not is_noop<On>::value, "join type requires on()");
return {*this, t, {}};
return ::sqlpp::right_outer_join(*this, t);
}
template <typename T>
join_t<left_outer_join_t, join_t, T> left_outer_join(T t)
auto outer_join(T t) const -> decltype(::sqlpp::outer_join(*this, t))
{
static_assert(not is_noop<On>::value, "join type requires on()");
return {*this, t, {}};
return ::sqlpp::outer_join(*this, t);
}
template <typename T>
join_t<right_outer_join_t, join_t, T> right_outer_join(T t)
auto cross_join(T t) const -> decltype(::sqlpp::cross_join(*this, t))
{
static_assert(not is_noop<On>::value, "join type requires on()");
return {*this, t, {}};
return ::sqlpp::cross_join(*this, t);
}
Lhs _lhs;
Rhs _rhs;
PreJoin _pre_join;
On _on;
};
template <typename Context, typename JoinType, typename Lhs, typename Rhs, typename On>
struct serializer_t<Context, join_t<JoinType, Lhs, Rhs, On>>
template <typename Context, typename PreJoin, typename On>
struct serializer_t<Context, join_t<PreJoin, On>>
{
using _serialize_check = serialize_check_of<Context, Lhs, Rhs, On>;
using T = join_t<JoinType, Lhs, Rhs, On>;
using _serialize_check = serialize_check_of<Context, PreJoin, On>;
using T = join_t<PreJoin, On>;
static Context& _(const T& t, Context& context)
{
static_assert(not is_noop<On>::value, "joined tables require on()");
serialize(t._lhs, context);
context << JoinType::_name;
context << " JOIN ";
serialize(t._rhs, context);
serialize(t._pre_join, context);
serialize(t._on, context);
return context;
}

View File

@ -0,0 +1,73 @@
/*
* 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_JOIN_TYPES_H
#define SQLPP_JOIN_TYPES_H
#include <sqlpp11/type_traits.h>
namespace sqlpp
{
struct inner_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables =
detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " INNER";
};
struct outer_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
static constexpr const char* _name = " OUTER";
};
struct left_outer_join_t
{
template <typename Lhs, typename 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";
};
struct right_outer_join_t
{
template <typename Lhs, typename 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";
};
struct cross_join_t
{
template <typename Lhs, typename Rhs>
using _provided_outer_tables =
detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
static constexpr const char* _name = " CROSS";
};
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -312,6 +312,18 @@ namespace sqlpp
return context;
}
};
template <typename T>
auto limit(T&& t) -> decltype(statement_t<void, no_limit_t>().limit(std::forward<T>(t)))
{
return statement_t<void, no_limit_t>().limit(std::forward<T>(t));
}
template <typename Database>
auto dynamic_limit(const Database&) -> decltype(statement_t<Database, no_limit_t>().dynamic_limit())
{
return statement_t<Database, no_limit_t>().dynamic_limit();
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -328,6 +328,18 @@ namespace sqlpp
return context;
}
};
template <typename T>
auto offset(T&& t) -> decltype(statement_t<void, no_offset_t>().offset(std::forward<T>(t)))
{
return statement_t<void, no_offset_t>().offset(std::forward<T>(t));
}
template <typename Database>
auto dynamic_offset(const Database&) -> decltype(statement_t<Database, no_offset_t>().dynamic_offset())
{
return statement_t<Database, no_offset_t>().dynamic_offset();
}
}
#endif

View File

@ -28,65 +28,63 @@
#define SQLPP_ON_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h>
#include <sqlpp11/unconditional.h>
#include <sqlpp11/logic.h>
namespace sqlpp
{
template <typename Database, typename... Expressions>
SQLPP_PORTABLE_STATIC_ASSERT(assert_on_is_expression_t, "argument is not an expression in on()");
SQLPP_PORTABLE_STATIC_ASSERT(assert_on_is_boolean_expression_t, "argument is not a boolean expression in on()");
template <typename Expr>
struct check_on
{
using type = static_combined_check_t<static_check_t<is_expression_t<Expr>::value, assert_on_is_expression_t>,
static_check_t<is_boolean_t<Expr>::value, assert_on_is_boolean_expression_t>>;
};
template <typename Expr>
using check_on_t = typename check_on<Expr>::type;
template <typename Expression>
struct on_t
{
using _traits = make_traits<no_value_t, tag::is_on>;
using _nodes = detail::type_vector<Expressions...>;
using _nodes = detail::type_vector<Expression>;
using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in on()");
template <typename Expr>
void add(Expr expr)
{
static_assert(_is_dynamic::value, "on::add() must not be called for static on()");
static_assert(is_expression_t<Expr>::value, "invalid expression argument in on::add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expr>;
_serialize_check::_();
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expr>::value, _serialize_check::type::value>;
_add_impl(expr, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template <typename Expr>
void _add_impl(Expr expr, const std::true_type&)
{
return _dynamic_expressions.emplace_back(expr);
}
template <typename Expr>
void _add_impl(Expr expr, const std::false_type&);
public:
std::tuple<Expressions...> _expressions;
interpretable_list_t<Database> _dynamic_expressions;
Expression _expression;
};
template <typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, on_t<Database, Expressions...>>
template <>
struct on_t<unconditional_t>
{
using _serialize_check = serialize_check_of<Context, Expressions...>;
using T = on_t<Database, Expressions...>;
using _traits = make_traits<no_value_t, tag::is_on>;
using _nodes = detail::type_vector<>;
};
template <typename Context>
struct serializer_t<Context, on_t<unconditional_t>>
{
using _serialize_check = consistent_t;
using T = on_t<unconditional_t>;
static Context& _(const T&, Context& context)
{
return context;
}
};
template <typename Context, typename Expression>
struct serializer_t<Context, on_t<Expression>>
{
using _serialize_check = serialize_check_of<Context, Expression>;
using T = on_t<Expression>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " ON ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
serialize(t._expression, context);
return context;
}
};

View File

@ -38,13 +38,16 @@ namespace sqlpp
};
template <typename T, template <typename> class Pred>
struct unary_operand_check<T, Pred, detail::enable_if_t<Pred<wrap_operand_t<T>>::value>>
struct unary_operand_check<T, Pred, detail::enable_if_t<Pred<T>::value>>
{
using type = void;
};
template <typename T, template <typename> class Pred>
using unary_operand_check_t = typename unary_operand_check<T, Pred>::type;
using unary_operand_check_t = typename unary_operand_check<wrap_operand_t<T>, Pred>::type;
template <typename T, template <typename> class Pred>
using unwrapped_unary_operand_check_t = typename unary_operand_check<T, Pred>::type;
template <typename L,
template <typename> class LPred,
@ -56,17 +59,17 @@ namespace sqlpp
};
template <typename L, template <typename> class LPred, typename R, template <typename> class RPred>
struct binary_operand_check<L,
LPred,
R,
RPred,
detail::enable_if_t<LPred<wrap_operand_t<L>>::value and RPred<wrap_operand_t<R>>::value>>
struct binary_operand_check<L, LPred, R, RPred, detail::enable_if_t<LPred<L>::value and RPred<R>::value>>
{
using type = void;
};
template <typename L, template <typename> class LPred, typename R, template <typename> class RPred>
using binary_operand_check_t = typename binary_operand_check<L, LPred, R, RPred>::type;
using binary_operand_check_t =
typename binary_operand_check<wrap_operand_t<L>, LPred, wrap_operand_t<R>, RPred>::type;
template <typename L, template <typename> class LPred, typename R, template <typename> class RPred>
using unwrapped_binary_operand_check_t = typename binary_operand_check<L, LPred, R, RPred>::type;
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -82,17 +82,11 @@ namespace sqlpp
}
template <typename Expression>
void add_ntc(Expression expression)
{
add<Expression, std::false_type>(expression);
}
template <typename Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
{
static_assert(_is_dynamic::value, "add() must not be called for static order_by");
static_assert(is_sort_order_t<Expression>::value, "invalid expression argument in order_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value,
static_assert(Policies::template _no_unknown_tables<Expression>::value,
"expression uses tables unknown to this statement in order_by::add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
_serialize_check::_();
@ -274,6 +268,19 @@ namespace sqlpp
return context;
}
};
template <typename... T>
auto order_by(T&&... t) -> decltype(statement_t<void, no_order_by_t>().order_by(std::forward<T>(t)...))
{
return statement_t<void, no_order_by_t>().order_by(std::forward<T>(t)...);
}
template <typename Database, typename... T>
auto dynamic_order_by(const Database&, T&&... t)
-> decltype(statement_t<Database, no_order_by_t>().dynamic_order_by(std::forward<T>(t)...))
{
return statement_t<Database, no_order_by_t>().dynamic_order_by(std::forward<T>(t)...);
}
}
#endif

View File

@ -27,7 +27,9 @@
#ifndef _sqlpp__ppgen__colops__auto_increment_h
#define _sqlpp__ppgen__colops__auto_increment_h
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_AUTO_INCREMENT PROC_SQLPP_AUTO_INCREMENT
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_AUTO_INCREMENT(...) ::sqlpp::tag::must_not_update
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_AUTO_INCREMENT \
PROC_SQLPP_AUTO_INCREMENT
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_AUTO_INCREMENT(...) \
::sqlpp::tag::must_not_insert, ::sqlpp::tag::must_not_update
#endif // _sqlpp__ppgen__colops__auto_increment_h

View File

@ -27,8 +27,9 @@
#ifndef _sqlpp__ppgen__colops__primary_key_h
#define _sqlpp__ppgen__colops__primary_key_h
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_PRIMARY_KEY PROC_SQLPP_PRIMARY_KEY
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_PRIMARY_KEY \
PROC_SQLPP_PRIMARY_KEY
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_PRIMARY_KEY(...) \
::sqlpp::tag::must_not_insert, ::sqlpp::tag::must_not_update
::sqlpp::tag::must_not_update
#endif // _sqlpp__ppgen__colops__primary_key_h

210
include/sqlpp11/pre_join.h Normal file
View File

@ -0,0 +1,210 @@
/*
* Copyright (c) 2013-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.
*/
#ifndef SQLPP_PRE_JOIN_H
#define SQLPP_PRE_JOIN_H
#include <sqlpp11/bad_statement.h>
#include <sqlpp11/join_types.h>
#include <sqlpp11/on.h>
#include <sqlpp11/noop.h>
namespace sqlpp
{
SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_lhs_table_t, "lhs argument of join() has to be a table or a join");
SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_rhs_table_t, "rhs argument of join() has to be a table");
SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_rhs_no_join_t, "rhs argument of join() must not be a join");
SQLPP_PORTABLE_STATIC_ASSERT(assert_pre_join_unique_names_t, "joined table names have to be unique");
template <typename Lhs, typename Rhs>
struct check_pre_join
{
using type = static_combined_check_t<
static_check_t<is_table_t<Lhs>::value, assert_pre_join_lhs_table_t>,
static_check_t<is_table_t<Rhs>::value, assert_pre_join_rhs_table_t>,
static_check_t<not is_join_t<Rhs>::value, assert_pre_join_rhs_no_join_t>,
static_check_t<detail::is_disjunct_from<detail::make_name_of_set_t<provided_tables_of<Lhs>>,
detail::make_name_of_set_t<provided_tables_of<Rhs>>>::value,
assert_pre_join_unique_names_t>>;
};
template <typename Lhs, typename Rhs>
using check_pre_join_t = typename check_pre_join<Lhs, Rhs>::type;
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_consist_of_pre_join_and_on_t,
"join has to consist of a pre_join and a join condition");
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_no_table_dependencies_t, "joined tables must not depend on other tables");
SQLPP_PORTABLE_STATIC_ASSERT(assert_join_on_no_foreign_table_dependencies_t,
"on() condition must not depend on other tables");
template <typename PreJoin, typename On>
struct check_join
{
using type = static_combined_check_t<
static_check_t<is_pre_join_t<PreJoin>::value, assert_join_consist_of_pre_join_and_on_t>,
static_check_t<is_on_t<On>::value, assert_join_consist_of_pre_join_and_on_t>,
static_check_t<required_tables_of<PreJoin>::size::value == 0, assert_join_no_table_dependencies_t>,
static_check_t<detail::is_subset_of<required_tables_of<On>, provided_tables_of<PreJoin>>::value,
assert_join_on_no_foreign_table_dependencies_t>>;
};
template <typename PreJoin, typename On>
using check_join_t = typename check_join<PreJoin, On>::type;
template <typename PreJoin, typename Expr>
struct check_join_on
{
using type = static_combined_check_t<check_on_t<Expr>, check_join_t<PreJoin, on_t<Expr>>>;
};
template <typename PreJoin, typename Expr>
using check_join_on_t = typename check_join_on<PreJoin, Expr>::type;
template <typename PreJoin, typename On>
struct join_t;
template <typename JoinType, typename Lhs, typename Rhs>
struct pre_join_t
{
using _traits = make_traits<no_value_t, tag::is_pre_join>;
using _nodes = detail::type_vector<Lhs, Rhs>;
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<Rhs>::value, "rhs argument for join() has to be a table");
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value,
"joined tables must not be identical");
static_assert(required_tables_of<pre_join_t>::size::value == 0, "joined tables must not depend on other tables");
template <typename Expr>
auto on(Expr expr) const -> typename std::conditional<check_join_on_t<pre_join_t, Expr>::value,
join_t<pre_join_t, on_t<Expr>>,
bad_statement>::type
{
using Check = check_join_on_t<pre_join_t, Expr>;
Check::_();
return on_impl(Check{}, expr);
}
private:
template <typename Expr>
auto on_impl(const std::false_type&, const Expr&) const -> bad_statement;
template <typename Expr>
auto on_impl(const std::true_type&, const Expr& expr) const -> join_t<pre_join_t, on_t<Expr>>
{
return {*this, {expr}};
}
public:
Lhs _lhs;
Rhs _rhs;
};
template <typename Context, typename JoinType, typename Lhs, typename Rhs>
struct serializer_t<Context, pre_join_t<JoinType, Lhs, Rhs>>
{
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
using T = pre_join_t<JoinType, Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
serialize(t._lhs, context);
context << JoinType::_name;
context << " JOIN ";
serialize(t._rhs, context);
return context;
}
};
template <typename Lhs, typename Rhs>
auto join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
pre_join_t<inner_join_t, Lhs, Rhs>,
bad_statement>::type
{
check_pre_join_t<Lhs, Rhs>::_();
return {lhs, rhs};
}
template <typename Lhs, typename Rhs>
auto inner_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
pre_join_t<inner_join_t, Lhs, Rhs>,
bad_statement>::type
{
check_pre_join_t<Lhs, Rhs>::_();
return {lhs, rhs};
}
template <typename Lhs, typename Rhs>
auto left_outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
pre_join_t<left_outer_join_t, Lhs, Rhs>,
bad_statement>::type
{
check_pre_join_t<Lhs, Rhs>::_();
return {lhs, rhs};
}
template <typename Lhs, typename Rhs>
auto right_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>,
bad_statement>::type
{
check_pre_join_t<Lhs, Rhs>::_();
return {lhs, rhs};
}
template <typename Lhs, typename Rhs>
auto outer_join(Lhs lhs, Rhs rhs) -> typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
pre_join_t<outer_join_t, Lhs, Rhs>,
bad_statement>::type
{
check_pre_join_t<Lhs, Rhs>::_();
return {lhs, rhs};
}
template <typename Lhs, typename Rhs>
auto cross_join(Lhs lhs, Rhs rhs) ->
typename std::conditional<check_pre_join_t<Lhs, Rhs>::value,
join_t<pre_join_t<cross_join_t, Lhs, Rhs>, on_t<unconditional_t>>,
bad_statement>::type
{
check_pre_join_t<Lhs, Rhs>::_();
return {pre_join_t<cross_join_t, Lhs, Rhs>{lhs, rhs}, {}};
}
}
#endif

View File

@ -34,7 +34,6 @@
#include <sqlpp11/prepared_remove.h>
#include <sqlpp11/noop.h>
#include <sqlpp11/from.h>
#include <sqlpp11/extra_tables.h>
#include <sqlpp11/using.h>
#include <sqlpp11/where.h>
@ -103,7 +102,7 @@ namespace sqlpp
};
template <typename Database>
using blank_remove_t = statement_t<Database, remove_t, no_from_t, no_using_t, no_extra_tables_t, no_where_t<true>>;
using blank_remove_t = statement_t<Database, remove_t, no_from_t, no_using_t, no_where_t<true>>;
inline auto remove() -> blank_remove_t<void>
{

View File

@ -35,7 +35,6 @@
#include <sqlpp11/select_flag_list.h>
#include <sqlpp11/select_column_list.h>
#include <sqlpp11/from.h>
#include <sqlpp11/extra_tables.h>
#include <sqlpp11/where.h>
#include <sqlpp11/group_by.h>
#include <sqlpp11/having.h>
@ -77,7 +76,6 @@ namespace sqlpp
no_select_flag_list_t,
no_select_column_list_t,
no_from_t,
no_extra_tables_t,
no_where_t<true>,
no_group_by_t,
no_having_t,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -66,37 +66,6 @@ namespace sqlpp
};
}
template <typename Context, typename Db>
struct serializer_t<Context, dynamic_select_column_list<Db>>
{
using T = dynamic_select_column_list<Db>;
static Context& _(const T& t, Context& context)
{
bool first = true;
for (const auto column : t._dynamic_columns)
{
if (first)
first = false;
else
context << ',';
serialize(column, context);
}
return context;
}
};
template <typename Context>
struct serializer_t<Context, dynamic_select_column_list<void>>
{
using T = dynamic_select_column_list<void>;
static Context& _(const T&, Context& context)
{
return context;
}
};
// SELECTED COLUMNS DATA
template <typename Database, typename... Columns>
struct select_column_list_data_t
@ -122,7 +91,7 @@ namespace sqlpp
SQLPP_PORTABLE_STATIC_ASSERT(
assert_no_unknown_tables_in_selected_columns_t,
"at least one selected column requires a table which is otherwise not known in the statement");
SQLPP_PORTABLE_STATIC_ASSERT(assert_aggregates_t,
SQLPP_PORTABLE_STATIC_ASSERT(assert_no_unknown_aggregates_t,
"not all columns are made of aggregates, despite group_by or similar");
// SELECTED COLUMNS
@ -154,19 +123,13 @@ namespace sqlpp
}
template <typename NamedExpression>
void add_ntc(NamedExpression namedExpression)
{
add<NamedExpression, std::false_type>(namedExpression);
}
template <typename NamedExpression, typename TableCheckRequired = std::true_type>
void add(NamedExpression namedExpression)
{
using named_expression = auto_alias_t<NamedExpression>;
static_assert(_is_dynamic::value, "selected_columns::add() can only be called for dynamic_column");
static_assert(is_selectable_t<named_expression>::value,
"invalid named expression argument in selected_columns::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<named_expression>::value,
static_assert(Policies::template _no_unknown_tables<named_expression>::value,
"named expression uses tables unknown to this statement in selected_columns::add()");
using column_names = detail::make_type_set_t<typename Columns::_alias_t...>;
static_assert(not detail::is_element_of<typename named_expression::_alias_t, column_names>::value,
@ -232,16 +195,15 @@ namespace sqlpp
return t.selected_columns;
}
using _column_check =
typename std::conditional<Policies::template _no_unknown_tables<select_column_list_t>::value,
using _table_check = typename std::conditional<Policies::template _no_unknown_tables<select_column_list_t>::value,
consistent_t,
assert_no_unknown_tables_in_selected_columns_t>::type;
using _aggregate_check = typename std::conditional<Policies::template _no_unknown_aggregates<Columns...>::value,
consistent_t,
assert_aggregates_t>::type;
assert_no_unknown_aggregates_t>::type;
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t, _column_check, _aggregate_check>;
using _consistency_check = detail::get_first_if<is_inconsistent_t, consistent_t, _table_check, _aggregate_check>;
};
// Result methods
@ -484,6 +446,13 @@ namespace sqlpp
{
return statement_t<void, no_select_column_list_t>().columns(std::forward<T>(t)...);
}
template <typename Database, typename... T>
auto dynamic_select_columns(const Database&, T&&... t)
-> decltype(statement_t<Database, no_select_column_list_t>().dynamic_columns(std::forward<T>(t)...))
{
return statement_t<Database, no_select_column_list_t>().dynamic_columns(std::forward<T>(t)...);
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -78,17 +78,11 @@ namespace sqlpp
}
template <typename Flag>
void add_ntc(Flag flag)
{
add<Flag, std::false_type>(flag);
}
template <typename Flag, typename TableCheckRequired = std::true_type>
void add(Flag flag)
{
static_assert(_is_dynamic::value, "select_flags::add() must not be called for static select flags");
static_assert(is_select_flag_t<Flag>::value, "invalid select flag argument in select_flags::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Flag>::value,
static_assert(Policies::template _no_unknown_tables<Flag>::value,
"flag uses tables unknown to this statement in select_flags::add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Flag>;
_serialize_check::_();
@ -264,6 +258,19 @@ namespace sqlpp
return context;
}
};
template <typename T>
auto select_flags(T&& t) -> decltype(statement_t<void, no_select_flag_list_t>().flags(std::forward<T>(t)))
{
return statement_t<void, no_select_flag_list_t>().flags(std::forward<T>(t));
}
template <typename Database, typename T>
auto dynamic_select_flags(const Database&, T&& t)
-> decltype(statement_t<Database, no_select_flag_list_t>().dynamic_flags(std::forward<T>(t)))
{
return statement_t<Database, no_select_flag_list_t>().dynamic_flags(std::forward<T>(t));
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -36,6 +36,8 @@
#include <sqlpp11/functions.h>
#include <sqlpp11/transaction.h>
#include <sqlpp11/boolean_expression.h>
#include <sqlpp11/without_table_check.h>
#include <sqlpp11/schema_qualified_table.h>
#include <sqlpp11/custom_query.h>
#endif

View File

@ -76,13 +76,10 @@ namespace sqlpp
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_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _all_provided_aggregates = detail::make_joined_set_t<provided_aggregates_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
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>, _all_provided_tables>;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2086629
// template <typename... Expressions>
@ -96,15 +93,15 @@ namespace sqlpp
logic::all_t<detail::is_aggregate_expression_impl<_all_provided_aggregates,
Expressions>::type::value...>::value>;
template <typename... Expressions>
using _no_non_aggregates = logic::any_t<logic::all_t<
detail::is_aggregate_expression_impl<_all_provided_aggregates, Expressions>::type::value...>::value>;
template <template <typename> class Predicate>
using any_t = logic::any_t<Predicate<Policies>::value...>;
// The tables not covered by the from.
using _required_tables =
detail::make_difference_set_t<_all_required_tables,
_all_provided_tables // Hint: extra_tables are not used here because they are
// just a helper for dynamic .add_*()
>;
using _required_tables = detail::make_difference_set_t<_all_required_tables, _all_provided_tables>;
// The common table expressions not covered by the with.
using _required_ctes = detail::make_difference_set_t<_all_required_ctes, _all_provided_ctes>;

View File

@ -62,33 +62,33 @@ namespace sqlpp
using _alias_t = table_alias_t<AliasProvider, Table, ColumnSpec...>;
template <typename T>
join_t<inner_join_t, Table, T> join(T t) const
auto join(T t) const -> decltype(::sqlpp::join(std::declval<Table>(), t))
{
return {*static_cast<const Table*>(this), t, {}};
return ::sqlpp::join(*static_cast<const Table*>(this), t);
}
template <typename T>
join_t<inner_join_t, Table, T> inner_join(T t) const
auto inner_join(T t) const -> decltype(::sqlpp::inner_join(std::declval<Table>(), t))
{
return {*static_cast<const Table*>(this), t, {}};
return ::sqlpp::inner_join(*static_cast<const Table*>(this), t);
}
template <typename T>
join_t<outer_join_t, Table, T> outer_join(T t) const
auto left_outer_join(T t) const -> decltype(::sqlpp::left_outer_join(std::declval<Table>(), t))
{
return {*static_cast<const Table*>(this), t, {}};
return ::sqlpp::left_outer_join(*static_cast<const Table*>(this), t);
}
template <typename T>
join_t<left_outer_join_t, Table, T> left_outer_join(T t) const
auto right_outer_join(T t) const -> decltype(::sqlpp::right_outer_join(std::declval<Table>(), t))
{
return {*static_cast<const Table*>(this), t, {}};
return ::sqlpp::right_outer_join(*static_cast<const Table*>(this), t);
}
template <typename T>
join_t<right_outer_join_t, Table, T> right_outer_join(T t) const
auto outer_join(T t) const -> decltype(::sqlpp::outer_join(std::declval<Table>(), t))
{
return {*static_cast<const Table*>(this), t, {}};
return ::sqlpp::outer_join(*static_cast<const Table*>(this), t);
}
template <typename AliasProvider>
@ -97,6 +97,12 @@ namespace sqlpp
return {*static_cast<const Table*>(this)};
}
template <typename T>
auto cross_join(T t) const -> decltype(::sqlpp::cross_join(std::declval<Table>(), t))
{
return ::sqlpp::cross_join(*static_cast<const Table*>(this), t);
}
const Table& ref() const
{
return *static_cast<const Table*>(this);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -30,6 +30,7 @@
#include <sqlpp11/column_fwd.h>
#include <sqlpp11/interpret.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/join.h>
#include <sqlpp11/alias.h>
#include <sqlpp11/detail/type_set.h>
@ -41,7 +42,6 @@ namespace sqlpp
template <typename AliasProvider, typename Table, typename... ColumnSpec>
struct table_alias_t : public ColumnSpec::_alias_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
{
// FIXME: Need to add join functionality
using _traits = make_traits<value_type_of<Table>,
tag::is_table,
tag::is_alias,
@ -60,6 +60,42 @@ namespace sqlpp
{
}
template <typename T>
auto join(T t) const -> decltype(::sqlpp::join(*this, t))
{
return ::sqlpp::join(*this, t);
}
template <typename T>
auto inner_join(T t) const -> decltype(::sqlpp::inner_join(*this, t))
{
return ::sqlpp::inner_join(*this, t);
}
template <typename T>
auto left_outer_join(T t) const -> decltype(::sqlpp::left_outer_join(*this, t))
{
return ::sqlpp::left_outer_join(*this, t);
}
template <typename T>
auto right_outer_join(T t) const -> decltype(::sqlpp::right_outer_join(*this, t))
{
return ::sqlpp::right_outer_join(*this, t);
}
template <typename T>
auto outer_join(T t) const -> decltype(::sqlpp::outer_join(*this, t))
{
return ::sqlpp::outer_join(*this, t);
}
template <typename T>
auto cross_join(T t) const -> decltype(::sqlpp::cross_join(*this, t))
{
return ::sqlpp::cross_join(*this, t);
}
Table _table;
};

View File

@ -56,6 +56,12 @@ namespace sqlpp
template <typename T>
using value_type_of = typename detail::value_type_of_impl<T>::type;
template <typename T>
struct is_not_cpp_bool_t
{
static constexpr bool value = not std::is_same<T, bool>::value;
};
// data types
struct boolean;
template <typename T>
@ -163,7 +169,10 @@ namespace sqlpp
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value)
SQLPP_VALUE_TRAIT_GENERATOR(is_table)
SQLPP_VALUE_TRAIT_GENERATOR(is_raw_table)
SQLPP_VALUE_TRAIT_GENERATOR(is_pre_join)
SQLPP_VALUE_TRAIT_GENERATOR(is_join)
SQLPP_VALUE_TRAIT_GENERATOR(is_dynamic_pre_join)
SQLPP_VALUE_TRAIT_GENERATOR(is_dynamic_join)
SQLPP_VALUE_TRAIT_GENERATOR(is_pseudo_table)
SQLPP_VALUE_TRAIT_GENERATOR(is_column)
SQLPP_VALUE_TRAIT_GENERATOR(is_select)
@ -172,7 +181,6 @@ namespace sqlpp
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)
@ -250,7 +258,6 @@ namespace sqlpp
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(required_tables)
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_tables)
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_outer_tables)
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(extra_tables)
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_aggregates)
#define SQLPP_RECURSIVE_TRAIT_GENERATOR(trait) \
@ -373,6 +380,7 @@ namespace sqlpp
using serialize_check_of =
detail::get_first_if<is_inconsistent_t, consistent_t, typename serializer_t<Context, T>::_serialize_check...>;
SQLPP_PORTABLE_STATIC_ASSERT(assert_sqlpp_type_t, "expression is not an sqlpp type, consistency cannot be verified");
SQLPP_PORTABLE_STATIC_ASSERT(assert_run_statement_or_prepared_t,
"connection cannot run something that is neither statement nor prepared statement");
SQLPP_PORTABLE_STATIC_ASSERT(assert_prepare_statement_t,
@ -381,12 +389,11 @@ namespace sqlpp
template <typename T, typename Enable = void>
struct consistency_check
{
using type = assert_run_statement_or_prepared_t;
using type = assert_sqlpp_type_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>
struct consistency_check<T, detail::void_t<typename T::_consistency_check>>
{
using type = typename T::_consistency_check;
};
@ -495,6 +502,24 @@ namespace sqlpp
template <typename Statement, template <typename> class Predicate>
using has_policy_t = typename has_policy_impl<Statement, Predicate>::type;
struct no_context_t
{
};
template <typename Db, typename = void>
struct serializer_context_of_impl
{
using type = no_context_t;
};
template <typename Db>
struct serializer_context_of_impl<Db, detail::void_t<typename Db::_serializer_context_t>>
{
using type = typename Db::_serializer_context_t;
};
template <typename Db>
using serializer_context_of = typename serializer_context_of_impl<Db>::type;
}
#endif

View File

@ -24,32 +24,13 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_OPERATORS_H
#define SQLPP_OPERATORS_H
#include <sqlpp11/wrap_operand.h>
#include <sqlpp11/expression_return_types.h>
#ifndef SQLPP_UNCONDITIONAL_H
#define SQLPP_UNCONDITIONAL_H
namespace sqlpp
{
template <typename L, typename R>
auto operator and(const L& l, const R& r) -> return_type_and_t<L, R>
struct unconditional_t
{
return_type_and<L, R>::check::_();
return {wrap_operand_t<L>{l}, wrap_operand_t<R>{r}};
}
template <typename L, typename R>
auto operator or(const L& l, const R& r) -> return_type_or_t<L, R>
{
return_type_or<L, R>::check::_();
return {wrap_operand_t<L>{l}, wrap_operand_t<R>{r}};
}
template <typename T>
auto operator not(const T& t) -> return_type_not_t<T>
{
return_type_not<T>::check::_();
return {wrap_operand_t<T>{t}};
}
};
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -250,6 +250,18 @@ namespace sqlpp
}
};
};
template <typename T>
auto union_all(T&& t) -> decltype(statement_t<void, no_union_t>().union_all(std::forward<T>(t)))
{
return statement_t<void, no_union_t>().union_all(std::forward<T>(t));
}
template <typename T>
auto union_distinct(T&& t) -> decltype(statement_t<void, no_union_t>().union_distinct(std::forward<T>(t)))
{
return statement_t<void, no_union_t>().union_distinct(std::forward<T>(t));
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -78,12 +78,6 @@ namespace sqlpp
}
template <typename Assignment>
void add_ntc(Assignment assignment)
{
add<Assignment, std::false_type>(assignment);
}
template <typename Assignment, typename TableCheckRequired = std::true_type>
void add(Assignment assignment)
{
static_assert(_is_dynamic::value, "add must not be called for static from()");
@ -92,7 +86,7 @@ namespace sqlpp
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value,
"Must not assign value to column twice");
static_assert(logic::not_t<must_not_update_t, lhs_t<Assignment>>::value, "add() argument must not be updated");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value,
static_assert(Policies::template _no_unknown_tables<Assignment>::value,
"assignment uses tables unknown to this statement in add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Assignment>;
_serialize_check::_();

43
include/sqlpp11/value.h Normal file
View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2013-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.
*/
#ifndef SQLPP_VALUE_H
#define SQLPP_VALUE_H
#include <sqlpp11/type_traits.h>
namespace sqlpp
{
template <typename T>
auto value(T t) -> wrap_operand_t<T>
{
static_assert(is_wrapped_value_t<wrap_operand_t<T>>::value,
"value() is to be called with non-sql-type like int, or string");
return {t};
}
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -27,6 +27,7 @@
#ifndef SQLPP_VERBATIM_TABLE_H
#define SQLPP_VERBATIM_TABLE_H
#include <sqlpp11/table.h>
#include <sqlpp11/data_types/no_value.h>
namespace sqlpp

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -29,19 +29,21 @@
#include <sqlpp11/statement_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/value.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/expression.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h>
#include <sqlpp11/unconditional.h>
#include <sqlpp11/logic.h>
namespace sqlpp
{
// WHERE DATA
template <typename Database, typename... Expressions>
template <typename Database, typename Expression>
struct where_data_t
{
where_data_t(Expressions... expressions) : _expressions(expressions...)
where_data_t(Expression expression) : _expression(expression)
{
}
@ -51,7 +53,7 @@ namespace sqlpp
where_data_t& operator=(where_data_t&&) = default;
~where_data_t() = default;
std::tuple<Expressions...> _expressions;
Expression _expression;
interpretable_list_t<Database> _dynamic_expressions;
};
@ -60,16 +62,16 @@ namespace sqlpp
"at least one expression in where() requires a table which is otherwise not known in the statement");
// WHERE(EXPR)
template <typename Database, typename... Expressions>
template <typename Database, typename Expression>
struct where_t
{
using _traits = make_traits<no_value_t, tag::is_where>;
using _nodes = detail::type_vector<Expressions...>;
using _nodes = detail::type_vector<Expression>;
using _is_dynamic = is_database<Database>;
// Data
using _data_t = where_data_t<Database, Expressions...>;
using _data_t = where_data_t<Database, Expression>;
// Member implementation with data and methods
template <typename Policies>
@ -81,38 +83,33 @@ namespace sqlpp
{
}
template <typename Expression>
void add_ntc(Expression expression)
{
add<Expression, std::false_type>(expression);
}
template <typename Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
template <typename Expr>
void add(Expr expression)
{
static_assert(_is_dynamic::value, "where::add() can only be called for dynamic_where");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in where::add()");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value,
static_assert(is_expression_t<Expr>::value, "invalid expression argument in where::add()");
static_assert(is_boolean_t<Expr>::value, "invalid expression argument in where::add()");
static_assert(Policies::template _no_unknown_tables<Expr>::value,
"expression uses tables unknown to this statement in where::add()");
static_assert(not contains_aggregate_function_t<Expression>::value,
static_assert(not contains_aggregate_function_t<Expr>::value,
"where expression must not contain aggregate functions");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expr>;
_serialize_check::_();
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expression>::value, _serialize_check::type::value>;
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expr>::value, _serialize_check::type::value>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template <typename Expression>
void _add_impl(Expression expression, const std::true_type&)
template <typename Expr>
void _add_impl(Expr expression, const std::true_type&)
{
return _data._dynamic_expressions.emplace_back(expression);
}
template <typename Expression>
void _add_impl(Expression expression, const std::false_type&);
template <typename Expr>
void _add_impl(Expr expression, const std::false_type&);
public:
_data_t _data;
@ -122,7 +119,7 @@ namespace sqlpp
template <typename Policies>
struct _base_t
{
using _data_t = where_data_t<Database, Expressions...>;
using _data_t = where_data_t<Database, Expression>;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269
template <typename... Args>
@ -154,20 +151,19 @@ namespace sqlpp
};
template <>
struct where_data_t<void, bool>
struct where_data_t<void, unconditional_t>
{
bool _condition;
};
// WHERE(BOOL)
// WHERE() UNCONDITIONALLY
template <>
struct where_t<void, bool>
struct where_t<void, unconditional_t>
{
using _traits = make_traits<no_value_t, tag::is_where>;
using _nodes = detail::type_vector<>;
// Data
using _data_t = where_data_t<void, bool>;
using _data_t = where_data_t<void, unconditional_t>;
// Member implementation with data and methods
template <typename Policies>
@ -186,7 +182,7 @@ namespace sqlpp
template <typename Policies>
struct _base_t
{
using _data_t = where_data_t<void, bool>;
using _data_t = where_data_t<void, unconditional_t>;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269
template <typename... Args>
@ -215,14 +211,15 @@ namespace sqlpp
};
};
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_t, "where expression required, e.g. where(true)");
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_t, "calling where() or uncontionally() required");
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_expressions_t,
"at least one argument is not a boolean expression in where()");
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_boolean_t, "at least one argument is not a boolean expression in where()");
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_not_cpp_bool_t,
"where() argument has to be an sqlpp boolean expression. Please use "
".unconditionally() instead of .where(true), or sqlpp::value(bool)");
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_boolean_expression_t,
"where() argument has to be an sqlpp boolean expression.");
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_no_aggregate_functions_t,
"at least one aggregate function used in where()");
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_static_count_args_t, "missing argument in where()");
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_dynamic_statement_dynamic_t,
"dynamic_where() must not be called in a static statement");
@ -230,33 +227,33 @@ namespace sqlpp
// https://connect.microsoft.com/VisualStudio/feedback/details/2173198
// template <typename... Expressions>
// using check_where_t = static_combined_check_t<
// static_check_t<logic::all_t<is_expression_t<Expressions>::value...>::value, assert_where_expressions_t>,
// static_check_t<logic::all_t<is_boolean_t<Expressions>::value...>::value, assert_where_boolean_t>,
// static_check_t<logic::all_t<is_not_cpp_bool_t<Expressions>::value...>::value,
// assert_where_not_cpp_bool_t>,
// static_check_t<logic::all_t<is_expression_t<Expressions>::value...>::value,
// assert_where_boolean_expressions_t>,
// static_check_t<logic::all_t<is_boolean_t<Expressions>::value...>::value, assert_where_boolean_expression_t>,
// static_check_t<logic::all_t<(not contains_aggregate_function_t<Expressions>::value)...>::value,
// assert_where_no_aggregate_functions_t>>;
template <typename... Expressions>
template <typename Expression>
struct check_where
{
using type = static_combined_check_t<
static_check_t<logic::all_t<detail::is_expression_impl<Expressions>::type::value...>::value,
assert_where_expressions_t>,
static_check_t<logic::all_t<is_boolean_t<Expressions>::value...>::value, assert_where_boolean_t>,
static_check_t<logic::all_t<(not detail::contains_aggregate_function_impl<Expressions>::type::value)...>::value,
assert_where_no_aggregate_functions_t>>;
static_check_t<is_not_cpp_bool_t<Expression>::value, assert_where_not_cpp_bool_t>,
static_check_t<is_expression_t<Expression>::value, assert_where_boolean_expression_t>,
static_check_t<is_boolean_t<Expression>::value, assert_where_boolean_expression_t>,
static_check_t<not contains_aggregate_function_t<Expression>::value, assert_where_no_aggregate_functions_t>>;
};
template <typename... Expressions>
using check_where_t = typename check_where<Expressions...>::type;
template <typename Expression>
using check_where_t = typename check_where<Expression>::type;
template <typename... Expressions>
using check_where_static_t =
static_combined_check_t<check_where_t<Expressions...>,
static_check_t<sizeof...(Expressions) != 0, assert_where_static_count_args_t>>;
template <typename Expression>
using check_where_static_t = check_where_t<Expression>;
template <typename Database, typename... Expressions>
template <typename Database, typename Expression>
using check_where_dynamic_t = static_combined_check_t<
static_check_t<not std::is_same<Database, void>::value, assert_where_dynamic_statement_dynamic_t>,
check_where_t<Expressions...>>;
check_where_t<Expression>>;
// NO WHERE YET
template <bool WhereRequired>
@ -312,14 +309,6 @@ namespace sqlpp
using _database_t = typename Policies::_database_t;
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269
// template <typename... T>
// using _check = logic::all_t<is_expression_t<T>::value...>;
template <typename... T>
struct _check : logic::all_t<is_expression_t<T>::value...>
{
};
template <typename Check, typename T>
using _new_statement_t = new_statement_t<Check::value, Policies, no_where_t, T>;
@ -328,59 +317,63 @@ namespace sqlpp
assert_where_t,
consistent_t>::type;
auto where(bool b) const -> _new_statement_t<std::true_type, where_t<void, bool>>
auto unconditionally() const -> _new_statement_t<std::true_type, where_t<void, unconditional_t>>
{
return {static_cast<const derived_statement_t<Policies>&>(*this), where_data_t<void, bool>{b}};
return {static_cast<const derived_statement_t<Policies>&>(*this), where_data_t<void, unconditional_t>{}};
}
template <typename... Expressions>
auto where(Expressions... expressions) const
-> _new_statement_t<check_where_static_t<Expressions...>, where_t<void, Expressions...>>
template <typename Expression>
auto where(Expression expression) const
-> _new_statement_t<check_where_static_t<Expression>, where_t<void, Expression>>
{
using Check = check_where_static_t<Expressions...>;
using Check = check_where_static_t<Expression>;
Check{}._();
return _where_impl<void>(Check{}, expressions...);
return _where_impl<void>(Check{}, expression);
}
template <typename... Expressions>
auto dynamic_where(Expressions... expressions) const
-> _new_statement_t<check_where_dynamic_t<_database_t, Expressions...>, where_t<_database_t, Expressions...>>
template <typename Expression>
auto dynamic_where(Expression expression) const
-> _new_statement_t<check_where_dynamic_t<_database_t, Expression>, where_t<_database_t, Expression>>
{
using Check = check_where_dynamic_t<_database_t, Expressions...>;
using Check = check_where_dynamic_t<_database_t, Expression>;
Check{}._();
return _where_impl<_database_t>(Check{}, expressions...);
return _where_impl<_database_t>(Check{}, expression);
}
auto dynamic_where() const -> _new_statement_t<check_where_dynamic_t<_database_t, boolean_operand>,
where_t<_database_t, boolean_operand>>
{
return dynamic_where(::sqlpp::value(true));
}
private:
template <typename Database, typename... Expressions>
auto _where_impl(const std::false_type&, Expressions... expressions) const -> bad_statement;
template <typename Database, typename Expression>
auto _where_impl(const std::false_type&, Expression expression) const -> bad_statement;
template <typename Database, typename... Expressions>
auto _where_impl(const std::true_type&, Expressions... expressions) const
-> _new_statement_t<std::true_type, where_t<Database, Expressions...>>
template <typename Database, typename Expression>
auto _where_impl(const std::true_type&, Expression expression) const
-> _new_statement_t<std::true_type, where_t<Database, Expression>>
{
return {static_cast<const derived_statement_t<Policies>&>(*this),
where_data_t<Database, Expressions...>{expressions...}};
where_data_t<Database, Expression>{expression}};
}
};
};
// Interpreters
template <typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, where_data_t<Database, Expressions...>>
template <typename Context, typename Database, typename Expression>
struct serializer_t<Context, where_data_t<Database, Expression>>
{
using _serialize_check = serialize_check_of<Context, Expressions...>;
using T = where_data_t<Database, Expressions...>;
using _serialize_check = serialize_check_of<Context, Expression>;
using T = where_data_t<Database, Expression>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " WHERE ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
serialize(t._expression, context);
if (not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
@ -388,23 +381,33 @@ namespace sqlpp
};
template <typename Context>
struct serializer_t<Context, where_data_t<void, bool>>
struct serializer_t<Context, where_data_t<void, unconditional_t>>
{
using _serialize_check = consistent_t;
using T = where_data_t<void, bool>;
using T = where_data_t<void, unconditional_t>;
static Context& _(const T& t, Context& context)
static Context& _(const T&, Context& context)
{
if (not t._condition)
context << " WHERE NULL";
return context;
}
};
template <typename... T>
auto where(T&&... t) -> decltype(statement_t<void, no_where_t<false>>().where(std::forward<T>(t)...))
template <typename T>
auto where(T&& t) -> decltype(statement_t<void, no_where_t<false>>().where(std::forward<T>(t)))
{
return statement_t<void, no_where_t<false>>().where(std::forward<T>(t)...);
return statement_t<void, no_where_t<false>>().where(std::forward<T>(t));
}
template <typename Database, typename T>
auto dynamic_where(const Database&, T&& t)
-> decltype(statement_t<Database, no_where_t<false>>().dynamic_where(std::forward<T>(t)))
{
return statement_t<Database, no_where_t<false>>().dynamic_where(std::forward<T>(t));
}
inline auto unconditionally() -> decltype(statement_t<void, no_where_t<false>>().unconditionally())
{
return statement_t<void, no_where_t<false>>().unconditionally();
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.
*/
#ifndef SQLPP_WITHOUT_TABLE_CHECK_H
#define SQLPP_ALIAS_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/serializer.h>
namespace sqlpp
{
template <typename Expression>
struct without_table_check_t : Expression
{
using _required_tables = detail::type_set<>;
without_table_check_t(Expression expression) : Expression(expression)
{
}
};
template <typename Context, typename Expression>
struct serializer_t<Context, without_table_check_t<Expression>>
{
using _serialize_check = serialize_check_of<Context, Expression>;
using T = without_table_check_t<Expression>;
static Context& _(const T& t, Context& context)
{
serialize<Expression>(t, context);
return context;
}
};
template <typename Expression>
auto without_table_check(Expression expr) -> without_table_check_t<Expression>
{
static_assert(is_expression_t<Expression>::value, "invalid argument (expression expected)");
return {expr};
}
}
#endif

View File

@ -36,7 +36,7 @@ int main()
static_assert(sqlpp::can_be_null_t<decltype(t.alpha)>::value, "t.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(t.alpha)>::value, "t.alpha does not say null_is_trivial");
for (const auto& row : edb(select(all_of(t)).from(t).where(true)))
for (const auto& row : edb(select(all_of(t)).from(t).unconditionally()))
{
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,

View File

@ -0,0 +1,41 @@
# Copyright (c) 2013-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.
set(test_serializer_names
CustomQuery
From
In
Where
)
create_test_sourcelist(test_serializer_sources test_serializer_main.cpp ${test_serializer_names})
add_executable(sqlpp11_test_serializer ${test_serializer_sources})
target_link_libraries(sqlpp11_test_serializer PRIVATE sqlpp11 sqlpp11_testing)
foreach(test_serializer IN LISTS test_serializer_names)
add_test(NAME sqlpp11.test_serializer.${test_serializer}
COMMAND sqlpp11_test_serializer ${test_serializer}
)
endforeach()

View File

@ -0,0 +1,63 @@
/*
* 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 "compare.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
#include <iostream>
int CustomQuery(int, char* [])
{
const auto foo = test::TabFoo{};
const auto bar = test::TabBar{};
auto db = MockDb{};
// Unconditionally
compare(__LINE__, custom_query(sqlpp::select(), select_flags(sqlpp::distinct), select_columns(foo.omega), from(foo),
sqlpp::unconditionally()),
"SELECT DISTINCT tab_foo.omega FROM tab_foo ");
// A full select statement made individual clauses
compare(__LINE__,
custom_query(sqlpp::select(), select_flags(sqlpp::distinct), select_columns(foo.omega),
from(foo.join(bar).on(foo.omega == bar.alpha)), where(bar.alpha > 17), group_by(foo.omega),
having(avg(bar.alpha) > 19), order_by(foo.omega.asc()), sqlpp::limit(10), sqlpp::offset(100)),
"SELECT DISTINCT tab_foo.omega FROM tab_foo INNER JOIN tab_bar ON (tab_foo.omega=tab_bar.alpha) WHERE "
"(tab_bar.alpha>17) GROUP BY tab_foo.omega HAVING (AVG(tab_bar.alpha)>19) ORDER BY tab_foo.omega ASC "
"LIMIT 10 OFFSET 100");
// A full select statement made individual clauses
compare(
__LINE__,
custom_query(sqlpp::select(), dynamic_select_flags(db, sqlpp::distinct), dynamic_select_columns(db, foo.omega),
dynamic_from(db, foo.join(bar).on(foo.omega == bar.alpha)), dynamic_where(db, bar.alpha > 17),
dynamic_group_by(db, foo.omega), dynamic_having(db, avg(bar.alpha) > 19),
dynamic_order_by(db, foo.omega.asc()), sqlpp::dynamic_limit(db), sqlpp::dynamic_offset(db)),
"SELECT DISTINCT tab_foo.omega FROM tab_foo INNER JOIN tab_bar ON (tab_foo.omega=tab_bar.alpha) WHERE "
"(tab_bar.alpha>17) GROUP BY tab_foo.omega HAVING (AVG(tab_bar.alpha)>19) ORDER BY tab_foo.omega ASC ");
return 0;
}

130
test_serializer/From.cpp Normal file
View File

@ -0,0 +1,130 @@
/*
* 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 "compare.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
MockDb db = {};
}
int From(int, char* [])
{
const auto foo = test::TabFoo{};
const auto bar = test::TabBar{};
const auto aFoo = foo.as(sqlpp::alias::a);
const auto bFoo = foo.as(sqlpp::alias::b);
const auto cFoo = foo.as(sqlpp::alias::c);
// Single table
compare(__LINE__, from(foo), " FROM tab_foo");
compare(__LINE__, from(bar), " FROM tab_bar");
// Static joins
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)),
" 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)),
" FROM tab_foo AS a INNER JOIN tab_foo AS b ON (a.omega>b.omega)");
compare(
__LINE__, from(aFoo.join(bFoo).on(aFoo.omega > bFoo.omega).join(cFoo).on(bFoo.omega > cFoo.omega)),
" FROM tab_foo AS a INNER JOIN tab_foo AS b ON (a.omega>b.omega) INNER JOIN tab_foo AS c ON (b.omega>c.omega)");
// Static joins involving verbatim tables
compare(__LINE__, from(aFoo.join(sqlpp::verbatim_table("unknown_table"))
.on(aFoo.omega > sqlpp::verbatim<sqlpp::floating_point>("unknown_table.column_x"))),
" FROM tab_foo AS a INNER JOIN unknown_table ON (a.omega>unknown_table.column_x)");
compare(__LINE__, from(sqlpp::verbatim_table("unknown_table")
.join(aFoo)
.on(aFoo.omega > sqlpp::verbatim<sqlpp::floating_point>("unknown_table.column_x"))),
" FROM unknown_table INNER JOIN tab_foo AS a ON (a.omega>unknown_table.column_x)");
compare(__LINE__, from(sqlpp::verbatim_table("unknown_table")
.as(sqlpp::alias::a)
.join(sqlpp::verbatim_table("another_table"))
.on(sqlpp::verbatim<sqlpp::boolean>("a.column_x>another_table.x"))),
" FROM unknown_table AS a INNER JOIN another_table ON a.column_x>another_table.x");
// Dynamic joins
const auto df = dynamic_from(db, foo);
compare(__LINE__, df, " FROM tab_foo");
{
auto dfa = df;
dfa.from.add(dynamic_cross_join(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;
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)");
}
{
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;
dfa.from.add(dynamic_inner_join(bar).on(bar.alpha > foo.omega));
dfa.from.add(dynamic_outer_join(aFoo).on(without_table_check(bar.alpha > aFoo.omega)));
compare(__LINE__, dfa, " FROM tab_foo INNER JOIN tab_bar ON (tab_bar.alpha>tab_foo.omega) OUTER JOIN tab_foo AS a "
"ON (tab_bar.alpha>a.omega)");
}
// Dynamic joins involving verbatim table
{
auto dfa = df;
dfa.from.add(
dynamic_inner_join(sqlpp::verbatim_table("unknown_table"))
.on(without_table_check(bar.alpha > sqlpp::verbatim<sqlpp::floating_point>("unknown_table.column_x"))));
compare(__LINE__, dfa, " FROM tab_foo INNER JOIN unknown_table ON (tab_bar.alpha>unknown_table.column_x)");
}
return 0;
}

64
test_serializer/In.cpp Normal file
View File

@ -0,0 +1,64 @@
/*
* 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 "compare.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
#include <iostream>
namespace
{
auto getFalse() -> std::string
{
MockDb::_serializer_context_t printer = {};
return serialize(sqlpp::value(false), printer).str();
}
}
int In(int, char* [])
{
const auto foo = test::TabFoo{};
const auto bar = test::TabBar{};
// Individual values
compare(__LINE__, foo.omega.in(17), "tab_foo.omega IN(17)");
compare(__LINE__, foo.omega.in(17, bar.alpha), "tab_foo.omega IN(17,tab_bar.alpha)");
compare(__LINE__, foo.omega.in(17, bar.alpha, sqlpp::value(19)), "tab_foo.omega IN(17,tab_bar.alpha,19)");
// Lists
compare(__LINE__, foo.omega.in(sqlpp::value_list(std::vector<float>{1.7f, 2.5f, 17.f, 0.f})),
"tab_foo.omega IN(1.7,2.5,17,0)");
// Sub select
compare(__LINE__, foo.omega.in(select(bar.alpha).from(bar).unconditionally()),
"tab_foo.omega IN(SELECT tab_bar.alpha FROM tab_bar)");
// Empty lists (not normally covered by SQL)
compare(__LINE__, foo.omega.in(), getFalse());
compare(__LINE__, foo.omega.in(sqlpp::value_list(std::vector<int>{})), getFalse());
return 0;
}

67
test_serializer/Where.cpp Normal file
View File

@ -0,0 +1,67 @@
/*
* 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 "compare.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
#include <iostream>
namespace
{
auto getTrue() -> std::string
{
MockDb::_serializer_context_t printer = {};
return serialize(sqlpp::value(true), printer).str();
}
auto getFalse() -> std::string
{
MockDb::_serializer_context_t printer = {};
return serialize(sqlpp::value(false), printer).str();
}
}
int Where(int, char* [])
{
const auto foo = test::TabFoo{};
const auto bar = test::TabBar{};
// Unconditionally
compare(__LINE__, select(foo.omega).from(foo).unconditionally(), "SELECT tab_foo.omega FROM tab_foo");
compare(__LINE__, remove_from(foo).unconditionally(), "DELETE FROM tab_foo");
compare(__LINE__, update(foo).set(foo.omega = 42).unconditionally(), "UPDATE tab_foo SET omega=42");
compare(__LINE__, where(sqlpp::value(true)), " WHERE " + getTrue());
// Never
compare(__LINE__, where(sqlpp::value(false)), " WHERE " + getFalse());
// Sometimes
compare(__LINE__, where(bar.gamma), " WHERE tab_bar.gamma");
compare(__LINE__, where(bar.gamma == false), " WHERE (tab_bar.gamma=" + getFalse() + ")");
compare(__LINE__, where(bar.beta == "SQL"), " WHERE (tab_bar.beta='SQL')");
return 0;
}

50
test_serializer/compare.h Normal file
View 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

View File

@ -142,6 +142,28 @@ namespace test
};
using _traits = sqlpp::make_traits<sqlpp::time_point, sqlpp::tag::can_be_null>;
};
struct OtherString
{
struct _alias_t
{
static constexpr const char _literal[] = "other_string";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template <typename T>
struct _member_t
{
T otherString;
T& operator()()
{
return otherString;
}
const T& operator()() const
{
return otherString;
}
};
};
using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
};
struct OtherInt
{
struct _alias_t
@ -261,6 +283,7 @@ namespace test
TabAllTypes_::SomeBool,
TabAllTypes_::SomeDayPoint,
TabAllTypes_::SomeTimePoint,
TabAllTypes_::OtherString,
TabAllTypes_::OtherInt,
TabAllTypes_::OtherFloat,
TabAllTypes_::OtherBool,

View File

@ -23,15 +23,22 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function(test_compile name)
set(target sqlpp11_${name})
set(target sqlpp11_assert_${name})
add_executable(${target} ${name}.cpp)
target_link_libraries(${target} PRIVATE sqlpp11 sqlpp11_testing)
endfunction()
test_compile(aggregates)
test_compile(case)
test_compile(from)
test_compile(join)
test_compile(where)
test_compile(having)
test_compile(insert)
test_compile(in)
test_compile(date)
test_compile(date_time)
test_compile(text)
test_compile(no_self_compare)
test_compile(unwrapped_bool)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2015, Roland Bock
* Copyright (c) 2015-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -75,51 +75,53 @@ namespace
// If there is no group_by, we can select whatever we want
void no_group_by()
{
run_check(select(all_of(t)).from(t).where(true));
run_check(select(t.alpha).from(t).where(true));
run_check(select(count(t.alpha)).from(t).where(true));
run_check(select(all_of(t)).from(t).unconditionally());
run_check(select(t.alpha).from(t).unconditionally());
run_check(select(count(t.alpha)).from(t).unconditionally());
}
// If there is a dynamic group_by, we can still select whatever we want
// because there is no way of knowing which expressions might have been added dynamically
void dynamic_group_by()
{
run_check(select(all_of(t)).from(t).where(true));
run_check(select(t.alpha).from(t).where(true));
run_check(select(count(t.alpha)).from(t).where(true));
run_check(select(all_of(t)).from(t).unconditionally());
run_check(select(t.alpha).from(t).unconditionally());
run_check(select(count(t.alpha)).from(t).unconditionally());
}
// If there is a static group_by, selected columns must be made of group_by expressions, or aggregate expression (e.g.
// count(t.id)) or values to be valid
void static_group_by_ok()
{
run_check(select(t.alpha).from(t).where(true).group_by(t.alpha));
run_check(select((t.alpha + 42).as(whatever)).from(t).where(true).group_by(t.alpha));
run_check(select((t.alpha + 42).as(whatever)).from(t).where(true).group_by(t.alpha, t.alpha + t.delta * 17));
run_check(
select((t.alpha + t.delta * 17).as(whatever)).from(t).where(true).group_by(t.alpha, t.alpha + t.delta * 17));
run_check(select((t.beta + "fortytwo").as(whatever)).from(t).where(true).group_by(t.beta));
run_check(select(t.alpha).from(t).unconditionally().group_by(t.alpha));
run_check(select((t.alpha + 42).as(whatever)).from(t).unconditionally().group_by(t.alpha));
run_check(select((t.alpha + 42).as(whatever)).from(t).unconditionally().group_by(t.alpha, t.alpha + t.delta * 17));
run_check(select((t.alpha + t.delta * 17).as(whatever))
.from(t)
.unconditionally()
.group_by(t.alpha, t.alpha + t.delta * 17));
run_check(select((t.beta + "fortytwo").as(whatever)).from(t).unconditionally().group_by(t.beta));
run_check(select(avg(t.alpha)).from(t).where(true).group_by(t.beta));
run_check(select(count(t.alpha)).from(t).where(true).group_by(t.beta));
run_check(select(max(t.alpha)).from(t).where(true).group_by(t.beta));
run_check(select(min(t.alpha)).from(t).where(true).group_by(t.beta));
run_check(select(sum(t.alpha)).from(t).where(true).group_by(t.beta));
run_check(select(avg(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select(count(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select(max(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select(min(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select(sum(t.alpha)).from(t).unconditionally().group_by(t.beta));
run_check(select((t.alpha + count(t.delta)).as(whatever)).from(t).where(true).group_by(t.alpha));
run_check(select((t.alpha + count(t.delta)).as(whatever)).from(t).unconditionally().group_by(t.alpha));
run_check(select(sqlpp::value(1).as(whatever)).from(t).where(true).group_by(t.alpha));
run_check(select(sqlpp::value("whatever").as(whatever)).from(t).where(true).group_by(t.alpha));
run_check(select(sqlpp::value(1).as(whatever)).from(t).unconditionally().group_by(t.alpha));
run_check(select(sqlpp::value("whatever").as(whatever)).from(t).unconditionally().group_by(t.alpha));
}
// Failures with static group_by and selected non-aggregates or incorrect aggregates
void static_group_by_nok()
{
run_check<sqlpp::assert_aggregates_t>(select(t.beta).from(t).where(true).group_by(t.alpha));
run_check<sqlpp::assert_aggregates_t>(
select((t.alpha + t.delta).as(whatever)).from(t).where(true).group_by(t.alpha));
run_check<sqlpp::assert_aggregates_t>(
select((t.alpha + t.delta).as(whatever)).from(t).where(true).group_by(t.alpha, t.alpha + t.delta * 17));
run_check<sqlpp::assert_no_unknown_aggregates_t>(select(t.beta).from(t).unconditionally().group_by(t.alpha));
run_check<sqlpp::assert_no_unknown_aggregates_t>(
select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha));
run_check<sqlpp::assert_no_unknown_aggregates_t>(
select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha, t.alpha + t.delta * 17));
}
}

View File

@ -31,7 +31,6 @@
namespace
{
constexpr auto t = test::TabBar{};
constexpr auto f = test::TabFoo{};
template <typename T>
void print_type_on_error(std::true_type)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2015, Roland Bock
* Copyright (c) 2015-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -46,7 +46,7 @@ namespace
template <typename Assert, typename Operand>
void static_check_comparison(const Operand& operand)
{
using CheckResult = sqlpp::check_rhs_comparison_operand_t<decltype(t.someDayPoint), Operand>;
using CheckResult = sqlpp::check_comparison_t<decltype(t.someDayPoint), Operand>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
static_assert(ExpectedCheckResult::value, "Unexpected check result");
print_type_on_error<CheckResult>(ExpectedCheckResult{});
@ -56,9 +56,9 @@ namespace
decltype(t.someDayPoint != operand), decltype(t.someDayPoint >= operand), decltype(t.someDayPoint > operand),
decltype(t.someDayPoint.in(operand)), decltype(t.someDayPoint.in(operand, operand)),
decltype(t.someDayPoint.not_in(operand)), decltype(t.someDayPoint.not_in(operand, operand))>;
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_statement>>::value>;
using ExpectedReturnType = sqlpp::logic::all_t<
Assert::value xor
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_expression<sqlpp::boolean>>>::value>;
static_assert(ExpectedReturnType::value, "Unexpected return type");
print_type_on_error<ReturnType>(ExpectedReturnType{});
}
@ -66,20 +66,21 @@ namespace
void allowed_comparands()
{
static_check_comparison<sqlpp::consistent_t>(std::chrono::system_clock::now());
static_check_comparison<sqlpp::consistent_t>(t.someDayPoint);
static_check_comparison<sqlpp::consistent_t>(t.otherDayPoint);
static_check_comparison<sqlpp::consistent_t>(t.someTimePoint);
static_check_comparison<sqlpp::consistent_t>(t.otherTimePoint);
}
void disallowed_comparands()
{
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(17);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>('a');
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(std::string("a"));
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someBool);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someFloat);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someInt);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someString);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(17);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>('a');
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(std::string("a"));
static_check_comparison<sqlpp::assert_comparison_rhs_is_expression_t>(t);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someBool);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someFloat);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someInt);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someString);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2015, Roland Bock
* Copyright (c) 2015-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -46,7 +46,7 @@ namespace
template <typename Assert, typename Operand>
void static_check_comparison(const Operand& operand)
{
using CheckResult = sqlpp::check_rhs_comparison_operand_t<decltype(t.someTimePoint), Operand>;
using CheckResult = sqlpp::check_comparison_t<decltype(t.someTimePoint), Operand>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
static_assert(ExpectedCheckResult::value, "Unexpected check result");
print_type_on_error<CheckResult>(ExpectedCheckResult{});
@ -56,9 +56,9 @@ namespace
decltype(t.someTimePoint != operand), decltype(t.someTimePoint >= operand), decltype(t.someTimePoint > operand),
decltype(t.someTimePoint.in(operand)), decltype(t.someTimePoint.in(operand, operand)),
decltype(t.someTimePoint.not_in(operand)), decltype(t.someTimePoint.not_in(operand, operand))>;
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_statement>>::value>;
using ExpectedReturnType = sqlpp::logic::all_t<
Assert::value xor
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_expression<sqlpp::boolean>>>::value>;
static_assert(ExpectedReturnType::value, "Unexpected return type");
print_type_on_error<ReturnType>(ExpectedReturnType{});
}
@ -67,19 +67,20 @@ namespace
{
static_check_comparison<sqlpp::consistent_t>(std::chrono::system_clock::now());
static_check_comparison<sqlpp::consistent_t>(t.someDayPoint);
static_check_comparison<sqlpp::consistent_t>(t.someTimePoint);
static_check_comparison<sqlpp::consistent_t>(t.otherDayPoint);
static_check_comparison<sqlpp::consistent_t>(t.otherTimePoint);
}
void disallowed_comparands()
{
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(17);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>('a');
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(std::string("a"));
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someBool);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someFloat);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someInt);
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someString);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(17);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>('a');
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(std::string("a"));
static_check_comparison<sqlpp::assert_comparison_rhs_is_expression_t>(t);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someBool);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someFloat);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someInt);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someString);
}
}

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2015-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 <iostream>
#include "MockDb.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
constexpr auto t = test::TabBar{};
constexpr auto f = test::TabFoo{};
template <typename T>
void print_type_on_error(std::true_type)
{
}
template <typename T>
void print_type_on_error(std::false_type)
{
T::_print_me_;
}
template <typename Assert, typename Expression>
void from_static_check(const Expression& expression)
{
using CheckResult = sqlpp::check_from_static_t<Expression>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ReturnType = decltype(select(t.alpha).from(expression));
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Expression>
void from_dynamic_check(const Expression& expression)
{
static auto db = MockDb{};
using CheckResult = sqlpp::check_from_dynamic_t<decltype(db), Expression>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ReturnType = decltype(dynamic_select(db, t.alpha).dynamic_from(expression));
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
void static_from()
{
// OK
from_static_check<sqlpp::consistent_t>(t);
from_static_check<sqlpp::consistent_t>(t.cross_join(f));
from_static_check<sqlpp::consistent_t>(t.join(f).on(t.alpha > f.omega));
// Try a bunch of non-tables
from_static_check<sqlpp::assert_from_table_t>(7);
from_static_check<sqlpp::assert_from_table_t>(t.alpha);
from_static_check<sqlpp::assert_from_table_t>(t.beta);
from_static_check<sqlpp::assert_from_table_t>(t.gamma);
from_static_check<sqlpp::assert_from_table_t>(t.delta);
// Try cross joins (missing condition)
from_static_check<sqlpp::assert_from_not_pre_join_t>(t.join(f));
}
void dynamic_from()
{
// OK
from_dynamic_check<sqlpp::consistent_t>(t);
from_dynamic_check<sqlpp::consistent_t>(t.cross_join(f));
from_dynamic_check<sqlpp::consistent_t>(t.join(f).on(t.alpha > f.omega));
// Try a bunch of non-tables
from_dynamic_check<sqlpp::assert_from_table_t>(7);
from_dynamic_check<sqlpp::assert_from_table_t>(t.alpha);
from_dynamic_check<sqlpp::assert_from_table_t>(t.beta);
from_dynamic_check<sqlpp::assert_from_table_t>(t.gamma);
from_dynamic_check<sqlpp::assert_from_table_t>(t.delta);
// Try cross joins (missing condition)
from_dynamic_check<sqlpp::assert_from_not_pre_join_t>(t.join(f));
}
template <typename Assert, typename FromImpl, typename Expression>
void dynamic_from_add_check(FromImpl from, const Expression& expression)
{
using CheckResult = sqlpp::check_from_add_t<FromImpl, Expression>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ReturnType = decltype(from.add(expression));
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
void dynamic_from_add()
{
static auto db = MockDb{};
auto fromT = dynamic_select(db, t.alpha).dynamic_from(t).from;
auto staticFrom = dynamic_select(db, t.alpha).from(t).from;
const auto fa = f.as(sqlpp::alias::a);
// OK
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_join(f).on(t.alpha > f.omega));
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_inner_join(f).on(t.alpha > f.omega));
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_left_outer_join(f).on(t.alpha > f.omega));
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_right_outer_join(f).on(t.alpha > f.omega));
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_outer_join(f).on(t.alpha > f.omega));
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_cross_join(f));
// Try a bunch of non dynamic joins
dynamic_from_add_check<sqlpp::assert_from_add_dynamic>(staticFrom, 7);
// Try a bunch of non dynamic joins
dynamic_from_add_check<sqlpp::assert_from_add_dynamic_join>(fromT, 7);
dynamic_from_add_check<sqlpp::assert_from_add_dynamic_join>(fromT, t.gamma);
dynamic_from_add_check<sqlpp::assert_from_add_dynamic_join>(fromT, join(f, f.as(sqlpp::alias::a)));
// Try incomplete dynamic join
dynamic_from_add_check<sqlpp::assert_from_add_not_dynamic_pre_join>(fromT, dynamic_join(f));
// Try joining the same table name
dynamic_from_add_check<sqlpp::assert_from_add_unique_names>(fromT, dynamic_cross_join(t));
dynamic_from_add_check<sqlpp::assert_from_add_unique_names>(fromT, dynamic_cross_join(f.as(t)));
// Try joining with a condition that requires other tables
dynamic_from_add_check<sqlpp::assert_from_add_no_required_tables>(fromT, dynamic_join(f).on(t.alpha > fa.omega));
// If you really think you know what you are doing, use without_table_check
dynamic_from_add_check<sqlpp::consistent_t>(fromT, dynamic_join(f).on(t.alpha > without_table_check(fa.omega)));
}
}
int main(int, char* [])
{
static_from();
dynamic_from();
dynamic_from_add();
}

View File

@ -0,0 +1,194 @@
/*
* 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 <iostream>
#include "MockDb.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
constexpr auto t = test::TabBar{};
constexpr auto f = test::TabFoo{};
template <typename T>
auto print_type_on_error(std::true_type) -> void
{
}
template <typename T>
auto print_type_on_error(std::false_type) -> void
{
T::_print_me_;
}
template <typename Assert, typename Expression>
auto having_static_check(const Expression& expression) -> void
{
using CheckResult = sqlpp::check_having_static_t<Expression>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ReturnType = decltype(select(all_of(t)).from(t).unconditionally().group_by(t.alpha).having(expression));
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Expression>
auto having_dynamic_check(const Expression& expression) -> void
{
static auto db = MockDb{};
using CheckResult = sqlpp::check_having_dynamic_t<decltype(db), Expression>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ReturnType =
decltype(dynamic_select(db, all_of(t)).from(t).unconditionally().group_by(t.alpha).dynamic_having(expression));
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
auto static_having() -> void
{
// OK
having_static_check<sqlpp::consistent_t>(t.gamma);
having_static_check<sqlpp::consistent_t>(t.gamma == true);
// OK using aggregate functions in having
having_static_check<sqlpp::consistent_t>(count(t.alpha) > 0);
having_static_check<sqlpp::consistent_t>(t.gamma and count(t.alpha) > 0);
having_static_check<sqlpp::consistent_t>(case_when(count(t.alpha) > 0).then(t.gamma).else_(not t.gamma));
// Try assignment as condition
having_static_check<sqlpp::assert_having_boolean_expression_t>(t.gamma = true);
// Try non-boolean expression
having_static_check<sqlpp::assert_having_boolean_expression_t>(t.alpha);
// Try builtin bool
having_static_check<sqlpp::assert_having_not_cpp_bool_t>(true);
having_static_check<sqlpp::assert_having_not_cpp_bool_t>(17 > 3);
// Try some other types as expressions
having_static_check<sqlpp::assert_having_boolean_expression_t>("true");
having_static_check<sqlpp::assert_having_boolean_expression_t>(17);
having_static_check<sqlpp::assert_having_boolean_expression_t>('c');
having_static_check<sqlpp::assert_having_boolean_expression_t>(nullptr);
having_static_check<sqlpp::assert_having_boolean_expression_t>(t.alpha.as(t.beta));
}
auto dynamic_having() -> void
{
// OK
having_dynamic_check<sqlpp::consistent_t>(t.gamma);
having_dynamic_check<sqlpp::consistent_t>(t.gamma == true);
// OK using aggregate functions in having
having_dynamic_check<sqlpp::consistent_t>(count(t.alpha) > 0);
having_dynamic_check<sqlpp::consistent_t>(t.gamma and count(t.alpha) > 0);
having_dynamic_check<sqlpp::consistent_t>(case_when(count(t.alpha) > 0).then(t.gamma).else_(not t.gamma));
// Try assignment as condition
having_dynamic_check<sqlpp::assert_having_boolean_expression_t>(t.gamma = true);
// Try non-boolean expression
having_dynamic_check<sqlpp::assert_having_boolean_expression_t>(t.alpha);
// Try builtin bool
having_dynamic_check<sqlpp::assert_having_not_cpp_bool_t>(true);
having_dynamic_check<sqlpp::assert_having_not_cpp_bool_t>(17 > 3);
// Try some other types as expressions
having_dynamic_check<sqlpp::assert_having_boolean_expression_t>("true");
having_dynamic_check<sqlpp::assert_having_boolean_expression_t>(17);
having_dynamic_check<sqlpp::assert_having_boolean_expression_t>('c');
having_dynamic_check<sqlpp::assert_having_boolean_expression_t>(nullptr);
having_dynamic_check<sqlpp::assert_having_boolean_expression_t>(t.alpha.as(t.beta));
// Try dynamic_having on a non-dynamic select
using CheckResult = sqlpp::check_having_dynamic_t<void, sqlpp::boolean_operand>;
using ExpectedCheckResult = std::is_same<CheckResult, sqlpp::assert_having_dynamic_statement_dynamic_t>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ReturnType = decltype(select(all_of(t)).from(t).dynamic_having());
using ExpectedReturnType = std::is_same<ReturnType, sqlpp::bad_statement>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Statement, typename HavingCondition>
auto static_consistency_check(const Statement statement, const HavingCondition condtion) -> void
{
using CheckResult = sqlpp::consistency_check_t<decltype(statement.having(condtion))>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
}
auto consistency_check() -> void
{
const auto select_without_group_by = select(all_of(t)).from(t).unconditionally();
// OK
static_consistency_check<sqlpp::consistent_t>(select_without_group_by, avg(t.alpha) > 17);
// Try non aggregate
static_consistency_check<sqlpp::assert_having_no_non_aggregates_t>(select_without_group_by, t.alpha > 17);
static_consistency_check<sqlpp::assert_having_no_non_aggregates_t>(select_without_group_by,
count(t.alpha) > 3 and t.alpha > 17);
// Try foreign table
static_consistency_check<sqlpp::assert_having_no_unknown_tables_t>(select_without_group_by, f.omega > 17);
const auto select_with_group_by = select(t.alpha).from(t).unconditionally().group_by(t.alpha);
// OK
static_consistency_check<sqlpp::consistent_t>(select_with_group_by, avg(t.alpha) > 17);
static_consistency_check<sqlpp::consistent_t>(select_with_group_by, t.alpha > 17);
static_consistency_check<sqlpp::consistent_t>(select_with_group_by, count(t.alpha) > 3 and t.alpha > 17);
// Try non aggregate
static_consistency_check<sqlpp::assert_having_no_non_aggregates_t>(select_with_group_by, t.beta > "17");
static_consistency_check<sqlpp::assert_having_no_non_aggregates_t>(select_with_group_by,
count(t.beta) > 3 and t.beta > "17");
// Try foreign table
static_consistency_check<sqlpp::assert_having_no_unknown_tables_t>(select_with_group_by, f.omega > 17);
}
}
int main(int, char* [])
{
static_having();
dynamic_having();
consistency_check();
}

View File

@ -0,0 +1,88 @@
/*
* 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 <iostream>
#include <set>
#include <MockDb.h>
#include "AssertTables.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
constexpr auto t = test::TabAllTypes{};
template <typename T>
void print_type_on_error(std::true_type)
{
}
template <typename T>
void print_type_on_error(std::false_type)
{
T::_print_me_;
}
template <typename Assert, typename Expr, typename... Operands>
void static_check_in(const Expr& expr, const Operands&... operands)
{
using CheckResult = sqlpp::check_in_t<Expr, Operands...>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
static_assert(ExpectedCheckResult::value, "Unexpected check result");
print_type_on_error<CheckResult>(ExpectedCheckResult{});
using ReturnType =
sqlpp::detail::make_type_set_t<decltype(expr.in(operands...)), decltype(expr.not_in(operands...))>;
using ExpectedReturnType = sqlpp::logic::all_t<
Assert::value xor
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_expression<sqlpp::boolean>>>::value>;
static_assert(ExpectedReturnType::value, "Unexpected return type");
print_type_on_error<ReturnType>(ExpectedReturnType{});
}
void checks()
{
// OK
static_check_in<sqlpp::consistent_t>(t.someString);
static_check_in<sqlpp::consistent_t>(t.someString, "");
static_check_in<sqlpp::consistent_t>(t.someString, "", "");
static_check_in<sqlpp::consistent_t>(t.someString, select(sqlpp::value("").as(sqlpp::alias::x)));
static_check_in<sqlpp::consistent_t>(t.someString, sqlpp::value_list(std::vector<std::string>{}));
static_check_in<sqlpp::consistent_t>(t.someString, sqlpp::value_list(std::set<std::string>{}));
// Try non-expressions
static_check_in<sqlpp::assert_comparison_rhs_is_expression_t>(t.someString, t);
static_check_in<sqlpp::assert_comparison_rhs_is_expression_t>(t.someString, t, t);
static_check_in<sqlpp::assert_comparison_rhs_is_expression_t>(t.someString, "", t, t, "");
// Try multi-expressions
static_check_in<sqlpp::assert_comparison_rhs_is_expression_t>(t.someString,
any(select(sqlpp::value("").as(sqlpp::alias::x))));
}
}
int main(int, char* [])
{
checks();
}

View File

@ -0,0 +1,285 @@
/*
* 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 <iostream>
#include "MockDb.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
constexpr auto t = test::TabBar{};
constexpr auto f = test::TabFoo{};
template <typename T>
void print_type_on_error(std::true_type)
{
}
template <typename T>
void print_type_on_error(std::false_type)
{
T::_print_me_;
}
template <typename Assert, typename Lhs, typename Rhs>
void join_static_check(const Lhs& lhs, const Rhs& rhs)
{
using CheckResult = sqlpp::check_pre_join_t<Lhs, Rhs>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using JoinType = decltype(sqlpp::join(lhs, rhs));
using InnerJoinType = decltype(sqlpp::inner_join(lhs, rhs));
using LeftOuterJoinType = decltype(sqlpp::left_outer_join(lhs, rhs));
using RightOuterJoinType = decltype(sqlpp::right_outer_join(lhs, rhs));
using OuterJoinType = decltype(sqlpp::outer_join(lhs, rhs));
using CrossJoinType = decltype(sqlpp::cross_join(lhs, rhs));
using ExpectedReturnType = sqlpp::logic::all_t<
(Assert::value and sqlpp::is_pre_join_t<JoinType>::value and sqlpp::is_pre_join_t<InnerJoinType>::value and
sqlpp::is_pre_join_t<LeftOuterJoinType>::value and sqlpp::is_pre_join_t<RightOuterJoinType>::value and
sqlpp::is_pre_join_t<OuterJoinType>::value and sqlpp::is_join_t<CrossJoinType>::value) xor
(std::is_same<JoinType, sqlpp::bad_statement>::value and
std::is_same<InnerJoinType, sqlpp::bad_statement>::value and
std::is_same<LeftOuterJoinType, sqlpp::bad_statement>::value and
std::is_same<RightOuterJoinType, sqlpp::bad_statement>::value and
std::is_same<OuterJoinType, sqlpp::bad_statement>::value and
std::is_same<CrossJoinType, sqlpp::bad_statement>::value)>;
print_type_on_error<JoinType>(ExpectedReturnType{});
print_type_on_error<InnerJoinType>(ExpectedReturnType{});
print_type_on_error<LeftOuterJoinType>(ExpectedReturnType{});
print_type_on_error<RightOuterJoinType>(ExpectedReturnType{});
print_type_on_error<OuterJoinType>(ExpectedReturnType{});
print_type_on_error<CrossJoinType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Lhs, typename Rhs>
void on_static_check(const Lhs& lhs, const Rhs& rhs)
{
using CheckResult = sqlpp::check_join_on_t<Lhs, Rhs>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ResultType = decltype(lhs.on(rhs));
using ExpectedReturnType = sqlpp::logic::all_t<(Assert::value and sqlpp::is_join_t<ResultType>::value) xor
std::is_same<ResultType, sqlpp::bad_statement>::value>;
print_type_on_error<ResultType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
void static_join()
{
// Prepare a few table aliases for tests
const auto ta = t.as(sqlpp::alias::a);
const auto tb = t.as(sqlpp::alias::b);
const auto fa = f.as(sqlpp::alias::a);
const auto fb = f.as(sqlpp::alias::b);
// OK: Join two different tables
join_static_check<sqlpp::consistent_t>(t, f);
join_static_check<sqlpp::consistent_t>(t, fa);
join_static_check<sqlpp::consistent_t>(ta, fb);
// OK: Self join
join_static_check<sqlpp::consistent_t>(ta, tb);
join_static_check<sqlpp::consistent_t>(t, tb);
join_static_check<sqlpp::consistent_t>(ta, t);
// Prepare a join for tests:
const auto j = cross_join(ta, tb);
// OK: Add a third table
join_static_check<sqlpp::consistent_t>(j, f);
join_static_check<sqlpp::consistent_t>(j, t.as(sqlpp::alias::c));
join_static_check<sqlpp::consistent_t>(j, t);
// Try a bunch of non-tables
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, 7);
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, t.alpha);
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, t.beta);
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, t.gamma);
join_static_check<sqlpp::assert_pre_join_rhs_table_t>(t, t.delta);
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(7, t);
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(t.alpha, t);
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(t.beta, t);
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(t.gamma, t);
join_static_check<sqlpp::assert_pre_join_lhs_table_t>(t.delta, t);
// Try to join with join (rhs)
join_static_check<sqlpp::assert_pre_join_rhs_no_join_t>(t, j);
join_static_check<sqlpp::assert_pre_join_rhs_no_join_t>(f, j);
join_static_check<sqlpp::assert_pre_join_rhs_no_join_t>(t.as(sqlpp::alias::left), j);
// Try to join identical table names
join_static_check<sqlpp::assert_pre_join_unique_names_t>(t, t);
join_static_check<sqlpp::assert_pre_join_unique_names_t>(f, f);
join_static_check<sqlpp::assert_pre_join_unique_names_t>(t.as(f), f);
join_static_check<sqlpp::assert_pre_join_unique_names_t>(t, f.as(t));
join_static_check<sqlpp::assert_pre_join_unique_names_t>(ta, fa);
join_static_check<sqlpp::assert_pre_join_unique_names_t>(j, fa);
join_static_check<sqlpp::assert_pre_join_unique_names_t>(j, fb);
join_static_check<sqlpp::assert_pre_join_unique_names_t>(j, ta);
join_static_check<sqlpp::assert_pre_join_unique_names_t>(j, tb);
// Prepare a pre_joins for tests:
const auto t_f = join(t, f);
const auto f_t = join(f, t);
const auto t_t = join(ta, tb);
const auto f_f = join(fa, fb);
// OK join.on()
on_static_check<sqlpp::consistent_t>(t_f, t.alpha > f.omega);
on_static_check<sqlpp::consistent_t>(f_t, t.alpha < f.omega);
on_static_check<sqlpp::consistent_t>(f_f, fa.omega == fb.omega);
on_static_check<sqlpp::consistent_t>(t_t, ta.alpha == tb.alpha);
on_static_check<sqlpp::consistent_t>(t_f, t.gamma);
// Try join.on(non-expression)
on_static_check<sqlpp::assert_on_is_expression_t>(t_f, true);
on_static_check<sqlpp::assert_on_is_expression_t>(t_f, 7);
on_static_check<sqlpp::assert_on_is_expression_t>(t_f, t);
// Try join.on(non-boolean)
on_static_check<sqlpp::assert_on_is_boolean_expression_t>(t_f, t.alpha);
on_static_check<sqlpp::assert_on_is_boolean_expression_t>(t_f, t.beta);
on_static_check<sqlpp::assert_on_is_boolean_expression_t>(t_f, f.omega);
// Try join.on(foreign-table)
on_static_check<sqlpp::assert_join_on_no_foreign_table_dependencies_t>(t_f, ta.alpha != 0);
on_static_check<sqlpp::assert_join_on_no_foreign_table_dependencies_t>(t_t, t.gamma);
on_static_check<sqlpp::assert_join_on_no_foreign_table_dependencies_t>(f_f, f.omega > fa.omega);
}
template <typename Assert, typename Table>
void join_dynamic_check(const Table& table)
{
using CheckResult = sqlpp::check_dynamic_pre_join_t<Table>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using JoinType = decltype(sqlpp::dynamic_join(table));
using InnerJoinType = decltype(sqlpp::dynamic_inner_join(table));
using LeftOuterJoinType = decltype(sqlpp::dynamic_left_outer_join(table));
using RightOuterJoinType = decltype(sqlpp::dynamic_right_outer_join(table));
using OuterJoinType = decltype(sqlpp::dynamic_outer_join(table));
using CrossJoinType = decltype(sqlpp::dynamic_cross_join(table));
using ExpectedReturnType = sqlpp::logic::all_t<(Assert::value and sqlpp::is_dynamic_pre_join_t<JoinType>::value and
sqlpp::is_dynamic_pre_join_t<InnerJoinType>::value and
sqlpp::is_dynamic_pre_join_t<LeftOuterJoinType>::value and
sqlpp::is_dynamic_pre_join_t<RightOuterJoinType>::value and
sqlpp::is_dynamic_pre_join_t<OuterJoinType>::value and
sqlpp::is_dynamic_join_t<CrossJoinType>::value) xor
(std::is_same<JoinType, sqlpp::bad_statement>::value and
std::is_same<InnerJoinType, sqlpp::bad_statement>::value and
std::is_same<LeftOuterJoinType, sqlpp::bad_statement>::value and
std::is_same<RightOuterJoinType, sqlpp::bad_statement>::value and
std::is_same<OuterJoinType, sqlpp::bad_statement>::value and
std::is_same<CrossJoinType, sqlpp::bad_statement>::value)>;
print_type_on_error<JoinType>(ExpectedReturnType{});
print_type_on_error<InnerJoinType>(ExpectedReturnType{});
print_type_on_error<LeftOuterJoinType>(ExpectedReturnType{});
print_type_on_error<RightOuterJoinType>(ExpectedReturnType{});
print_type_on_error<OuterJoinType>(ExpectedReturnType{});
print_type_on_error<CrossJoinType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Lhs, typename Rhs>
void on_dynamic_check(const Lhs& lhs, const Rhs& rhs)
{
using CheckResult = sqlpp::check_dynamic_join_on_t<Lhs, Rhs>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ResultType = decltype(lhs.on(rhs));
using ExpectedReturnType = sqlpp::logic::all_t<(Assert::value and sqlpp::is_dynamic_join_t<ResultType>::value) xor
std::is_same<ResultType, sqlpp::bad_statement>::value>;
print_type_on_error<ResultType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
void dynamic_join()
{
// Prepare a few table aliases for tests
const auto ta = t.as(sqlpp::alias::a);
const auto fa = f.as(sqlpp::alias::a);
// OK
join_dynamic_check<sqlpp::consistent_t>(t);
join_dynamic_check<sqlpp::consistent_t>(f);
join_dynamic_check<sqlpp::consistent_t>(ta);
join_dynamic_check<sqlpp::consistent_t>(fa);
join_dynamic_check<sqlpp::consistent_t>(sqlpp::verbatim_table("tab_sample"));
join_dynamic_check<sqlpp::consistent_t>(sqlpp::verbatim_table("tab_sample").as(sqlpp::alias::a));
// Try a bunch of non-tables
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(7);
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.alpha);
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.beta);
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.gamma);
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.delta);
// Try (pre) joins
join_dynamic_check<sqlpp::assert_dynamic_pre_join_table_t>(t.join(f));
join_dynamic_check<sqlpp::assert_dynamic_pre_join_no_join_t>(t.cross_join(f));
// Prepare a dynamic_pre_joins for tests:
const auto tj = dynamic_join(t);
const auto fj = dynamic_join(f);
const auto vj = dynamic_join(sqlpp::verbatim_table("tab_sample"));
// OK dynamic_join.on()
on_dynamic_check<sqlpp::consistent_t>(tj, t.alpha > f.omega);
on_dynamic_check<sqlpp::consistent_t>(fj, t.alpha < f.omega);
// Try dynamic_join.on(non-expression)
on_dynamic_check<sqlpp::assert_on_is_expression_t>(tj, true);
on_dynamic_check<sqlpp::assert_on_is_expression_t>(tj, 7);
on_dynamic_check<sqlpp::assert_on_is_expression_t>(tj, t);
// Try dynamic_join.on(non-boolean)
on_dynamic_check<sqlpp::assert_on_is_boolean_expression_t>(tj, t.alpha);
on_dynamic_check<sqlpp::assert_on_is_boolean_expression_t>(tj, t.beta);
on_dynamic_check<sqlpp::assert_on_is_boolean_expression_t>(tj, f.omega);
// OK dynamic_join.on(foreign-table)
on_dynamic_check<sqlpp::consistent_t>(tj, ta.alpha != 0);
on_dynamic_check<sqlpp::consistent_t>(tj, t.gamma);
on_dynamic_check<sqlpp::consistent_t>(tj, f.omega > fa.omega);
on_dynamic_check<sqlpp::consistent_t>(vj, t.alpha < f.omega);
}
}
int main(int, char* [])
{
static_join();
dynamic_join();
}

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2015-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 <iostream>
#include <MockDb.h>
#include "AssertTables.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
constexpr auto t = test::TabAllTypes{};
template <typename T>
void print_type_on_error(std::true_type)
{
}
template <typename T>
void print_type_on_error(std::false_type)
{
T::_print_me_;
}
template <typename Assert, typename Operand>
void static_check_self_compare(const Operand& operand)
{
using CheckResult = sqlpp::check_comparison_t<Operand, Operand>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
static_assert(ExpectedCheckResult::value, "Unexpected check result");
print_type_on_error<CheckResult>(ExpectedCheckResult{});
using ReturnType = sqlpp::detail::make_type_set_t<decltype(operand < operand), decltype(operand <= operand),
decltype(operand == operand), decltype(operand != operand),
decltype(operand >= operand), decltype(operand > operand)>;
using ExpectedReturnType = sqlpp::logic::all_t<
Assert::value xor
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_expression<sqlpp::boolean>>>::value>;
static_assert(ExpectedReturnType::value, "Unexpected return type");
print_type_on_error<ReturnType>(ExpectedReturnType{});
}
void disallowed_self_comparison()
{
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.someString);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.someInt);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.someFloat);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.someBool);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.someDayPoint);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.someTimePoint);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.otherString);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.otherInt);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.otherFloat);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.otherBool);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.otherDayPoint);
static_check_self_compare<sqlpp::assert_comparison_lhs_rhs_differ_t>(t.otherTimePoint);
}
}
int main(int, char* [])
{
// t.someString == t.someString;
disallowed_self_comparison();
}

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2015-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 <iostream>
#include <MockDb.h>
#include "AssertTables.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
constexpr auto t = test::TabAllTypes{};
template <typename T>
void print_type_on_error(std::true_type)
{
}
template <typename T>
void print_type_on_error(std::false_type)
{
T::_print_me_;
}
template <typename Assert, typename Operand>
void static_check_comparison(const Operand& operand)
{
using CheckResult = sqlpp::check_comparison_t<decltype(t.someString), Operand>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
static_assert(ExpectedCheckResult::value, "Unexpected check result");
print_type_on_error<CheckResult>(ExpectedCheckResult{});
using ReturnType = sqlpp::detail::make_type_set_t<
decltype(t.someString < operand), decltype(t.someString <= operand), decltype(t.someString == operand),
decltype(t.someString != operand), decltype(t.someString >= operand), decltype(t.someString > operand),
decltype(t.someString.in(operand)), decltype(t.someString.in(operand, operand)),
decltype(t.someString.not_in(operand)), decltype(t.someString.not_in(operand, operand))>;
using ExpectedReturnType = sqlpp::logic::all_t<
Assert::value xor
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_expression<sqlpp::boolean>>>::value>;
static_assert(ExpectedReturnType::value, "Unexpected return type");
print_type_on_error<ReturnType>(ExpectedReturnType{});
}
void allowed_comparands()
{
static_check_comparison<sqlpp::consistent_t>("");
// static_check_comparison<sqlpp::consistent_t>('d'); // not today
static_check_comparison<sqlpp::consistent_t>(std::string(""));
static_check_comparison<sqlpp::consistent_t>(t.otherString);
}
void disallowed_comparands()
{
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(17);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(17.4);
static_check_comparison<sqlpp::assert_comparison_rhs_is_expression_t>(t);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someBool);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someFloat);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someInt);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someDayPoint);
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someTimePoint);
}
template <typename Expected, typename Expression>
void static_check_type()
{
static_assert(std::is_same<Expected, Expression>::value, "Unexpected check result");
}
auto check_expressions() -> void
{
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(t.someString + 1)>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(t.someString - 1)>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(t.someString - "")>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(t.someString * 1)>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(t.someString * "")>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(t.someString / 1)>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(t.someString / "")>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(t.someString % 1)>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(t.someString % "")>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(-t.someString)>();
static_check_type<sqlpp::bad_expression<sqlpp::text>, decltype(+t.someString)>();
}
}
int main(int, char* [])
{
allowed_comparands();
disallowed_comparands();
check_expressions();
}

View File

@ -0,0 +1,115 @@
/*
* Copyright (c) 2015-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 <iostream>
#include "MockDb.h"
#include "Sample.h"
#include <sqlpp11/sqlpp11.h>
namespace
{
constexpr auto t = test::TabBar{};
template <typename T>
struct wrap
{
};
template <typename T>
void print_type_on_error(std::true_type)
{
}
template <typename T>
void print_type_on_error(std::false_type)
{
wrap<T>::_print_me_;
}
template <typename Assert, typename Lhs, typename Rhs>
void and_check(const Lhs& lhs, const Rhs& rhs)
{
using ReturnType = decltype(lhs and rhs);
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_expression<sqlpp::boolean>>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Lhs, typename Rhs>
void or_check(const Lhs& lhs, const Rhs& rhs)
{
using ReturnType = decltype(lhs or rhs);
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_expression<sqlpp::boolean>>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Lhs>
void not_check(const Lhs& lhs)
{
using ReturnType = decltype(not lhs);
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_expression<sqlpp::boolean>>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename Condition>
void where_check(const Condition& condition)
{
using ReturnType = decltype(sqlpp::where(condition));
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
void boolean()
{
and_check<sqlpp::consistent_t>(t.gamma, t.gamma);
and_check<sqlpp::assert_valid_operands>(t.gamma, true);
// and_check<sqlpp::assert_valid_operands>(true, t.gamma); // Cannot currently do that
or_check<sqlpp::consistent_t>(t.gamma, t.gamma);
or_check<sqlpp::assert_valid_operands>(t.gamma, true);
// or_check<sqlpp::assert_valid_operands>(true, t.gamma); // Cannot currently do that
not_check<sqlpp::consistent_t>(t.gamma);
}
void where()
{
where_check<sqlpp::consistent_t>(t.gamma);
where_check<sqlpp::bad_statement>(true);
}
}
int main(int, char* [])
{
boolean();
where();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015-2015, Roland Bock
* Copyright (c) 2015-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -31,7 +31,6 @@
namespace
{
constexpr auto t = test::TabBar{};
constexpr auto f = test::TabFoo{};
template <typename T>
void print_type_on_error(std::true_type)
@ -44,31 +43,31 @@ namespace
T::_print_me_;
}
template <typename Assert, typename... Expressions>
void where_static_check(const Expressions&... expressions)
template <typename Assert, typename Expression>
void where_static_check(const Expression& expression)
{
using CheckResult = sqlpp::check_where_static_t<Expressions...>;
using CheckResult = sqlpp::check_where_static_t<Expression>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ReturnType = decltype(remove_from(t).where(expressions...));
using ReturnType = decltype(remove_from(t).where(expression));
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
static_assert(ExpectedReturnType::value, "Unexpected return type");
}
template <typename Assert, typename... Expressions>
void where_dynamic_check(const Expressions&... expressions)
template <typename Assert, typename Expression>
void where_dynamic_check(const Expression& expression)
{
static auto db = MockDb{};
using CheckResult = sqlpp::check_where_dynamic_t<decltype(db), Expressions...>;
using CheckResult = sqlpp::check_where_dynamic_t<decltype(db), Expression>;
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");
using ReturnType = decltype(dynamic_remove_from(db, t).dynamic_where(expressions...));
using ReturnType = decltype(dynamic_remove_from(db, t).dynamic_where(expression));
using ExpectedReturnType =
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
print_type_on_error<ReturnType>(ExpectedReturnType{});
@ -81,21 +80,22 @@ namespace
where_static_check<sqlpp::consistent_t>(t.gamma);
where_static_check<sqlpp::consistent_t>(t.gamma == true);
// Try no expression
where_static_check<sqlpp::assert_where_static_count_args_t>();
// Try assignment as condition
where_static_check<sqlpp::assert_where_expressions_t>(t.gamma = true);
where_static_check<sqlpp::assert_where_boolean_expression_t>(t.gamma = true);
// Try non-boolean expression
where_static_check<sqlpp::assert_where_boolean_t>(t.alpha);
where_static_check<sqlpp::assert_where_boolean_expression_t>(t.alpha);
// Try builtin bool
where_static_check<sqlpp::assert_where_not_cpp_bool_t>(true);
where_static_check<sqlpp::assert_where_not_cpp_bool_t>(17 > 3);
// Try some other types as expressions
where_static_check<sqlpp::assert_where_expressions_t>("true");
where_static_check<sqlpp::assert_where_expressions_t>(17);
where_static_check<sqlpp::assert_where_expressions_t>('c');
where_static_check<sqlpp::assert_where_expressions_t>(nullptr);
where_static_check<sqlpp::assert_where_expressions_t>(t.alpha.as(t.beta));
where_static_check<sqlpp::assert_where_boolean_expression_t>("true");
where_static_check<sqlpp::assert_where_boolean_expression_t>(17);
where_static_check<sqlpp::assert_where_boolean_expression_t>('c');
where_static_check<sqlpp::assert_where_boolean_expression_t>(nullptr);
where_static_check<sqlpp::assert_where_boolean_expression_t>(t.alpha.as(t.beta));
// Try using aggregate functions in where
where_static_check<sqlpp::assert_where_no_aggregate_functions_t>(count(t.alpha) > 0);
@ -107,22 +107,25 @@ namespace
void dynamic_where()
{
// OK
where_dynamic_check<sqlpp::consistent_t>();
where_dynamic_check<sqlpp::consistent_t>(t.gamma);
where_dynamic_check<sqlpp::consistent_t>(t.gamma == true);
// Try assignment as condition
where_dynamic_check<sqlpp::assert_where_expressions_t>(t.gamma = true);
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>(t.gamma = true);
// Try non-boolean expression
where_dynamic_check<sqlpp::assert_where_boolean_t>(t.alpha);
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>(t.alpha);
// Try builtin bool
where_dynamic_check<sqlpp::assert_where_not_cpp_bool_t>(true);
where_dynamic_check<sqlpp::assert_where_not_cpp_bool_t>(17 > 3);
// Try some other types as expressions
where_dynamic_check<sqlpp::assert_where_expressions_t>("true");
where_dynamic_check<sqlpp::assert_where_expressions_t>(17);
where_dynamic_check<sqlpp::assert_where_expressions_t>('c');
where_dynamic_check<sqlpp::assert_where_expressions_t>(nullptr);
where_dynamic_check<sqlpp::assert_where_expressions_t>(t.alpha.as(t.beta));
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>("true");
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>(17);
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>('c');
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>(nullptr);
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>(t.alpha.as(t.beta));
// Try using aggregate functions in where
where_dynamic_check<sqlpp::assert_where_no_aggregate_functions_t>(count(t.alpha) > 0);
@ -131,7 +134,7 @@ namespace
case_when(count(t.alpha) > 0).then(t.gamma).else_(not t.gamma));
// Try dynamic_where on a non-dynamic remove
using CheckResult = sqlpp::check_where_dynamic_t<void>;
using CheckResult = sqlpp::check_where_dynamic_t<void, sqlpp::boolean_operand>;
using ExpectedCheckResult = std::is_same<CheckResult, sqlpp::assert_where_dynamic_statement_dynamic_t>;
print_type_on_error<CheckResult>(ExpectedCheckResult{});
static_assert(ExpectedCheckResult::value, "Unexpected check result");

32
test_types/CMakeLists.txt Normal file
View 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)

212
test_types/result_row.cpp Normal file
View 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();
}

View File

@ -57,6 +57,10 @@ int CustomQuery(int, char* [])
std::cerr << row.alpha << std::endl;
}
// Create a custom "insert or ignore"
db(custom_query(sqlpp::insert(), sqlpp::verbatim(" OR IGNORE"), into(t),
insert_set(t.beta = "sample", t.gamma = true)));
// A custom (select ... into) with adjusted return type
// The first argument with a return type is the select, but the custom query is really an insert. Thus, we tell it so.
printer.reset();

View File

@ -30,6 +30,13 @@
SQLPP_ALIAS_PROVIDER(now)
#if _MSC_FULL_VER >= 190023918
// MSVC Update 2 provides floor, ceil, round, abs in chrono (which is C++17 only...)
using ::std::chrono::floor;
#else
using ::date::floor;
#endif
int DateTime(int, char* [])
{
MockDb db = {};
@ -40,7 +47,7 @@ int DateTime(int, char* [])
{
std::cout << row.now;
}
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{
std::cout << row.colDayPoint;
std::cout << row.colTimePoint;
@ -48,23 +55,23 @@ int DateTime(int, char* [])
printer.reset();
std::cerr << serialize(::sqlpp::value(std::chrono::system_clock::now()), printer).str() << std::endl;
db(insert_into(t).set(t.colDayPoint = ::date::floor<::sqlpp::chrono::days>(std::chrono::system_clock::now())));
db(insert_into(t).set(t.colTimePoint = ::date::floor<::sqlpp::chrono::days>(std::chrono::system_clock::now())));
db(insert_into(t).set(t.colDayPoint = floor<::sqlpp::chrono::days>(std::chrono::system_clock::now())));
db(insert_into(t).set(t.colTimePoint = floor<::sqlpp::chrono::days>(std::chrono::system_clock::now())));
db(insert_into(t).set(t.colTimePoint = std::chrono::system_clock::now()));
db(update(t)
.set(t.colDayPoint = ::date::floor<::sqlpp::chrono::days>(std::chrono::system_clock::now()))
.set(t.colDayPoint = floor<::sqlpp::chrono::days>(std::chrono::system_clock::now()))
.where(t.colDayPoint < std::chrono::system_clock::now()));
db(update(t)
.set(t.colTimePoint = ::date::floor<::sqlpp::chrono::days>(std::chrono::system_clock::now()))
.set(t.colTimePoint = floor<::sqlpp::chrono::days>(std::chrono::system_clock::now()))
.where(t.colDayPoint < std::chrono::system_clock::now()));
db(update(t)
.set(t.colTimePoint = std::chrono::system_clock::now())
.where(t.colDayPoint < std::chrono::system_clock::now()));
db(remove_from(t).where(t.colDayPoint == ::date::floor<::sqlpp::chrono::days>(std::chrono::system_clock::now())));
db(remove_from(t).where(t.colDayPoint == floor<::sqlpp::chrono::days>(std::chrono::system_clock::now())));
db(remove_from(t).where(t.colDayPoint == std::chrono::system_clock::now()));
db(remove_from(t).where(t.colTimePoint == ::date::floor<::sqlpp::chrono::days>(std::chrono::system_clock::now())));
db(remove_from(t).where(t.colTimePoint == floor<::sqlpp::chrono::days>(std::chrono::system_clock::now())));
db(remove_from(t).where(t.colTimePoint == std::chrono::system_clock::now()));
return 0;

View File

@ -197,7 +197,7 @@ int Function(int, char* [])
static_assert(not sqlpp::is_numeric_t<TT>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TT>::value, "type requirement");
if (false and db(select(exists(select(t.alpha).from(t).where(true)))).front().exists)
if (false and db(select(exists(select(t.alpha).from(t).unconditionally()))).front().exists)
{ /* do something */
}
}
@ -286,7 +286,7 @@ int Function(int, char* [])
static_assert(sqlpp::is_integral_t<TT>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<TT>::value, "type requirement");
if (false and db(select(count(t.alpha)).from(t).where(true)).front().count > 0)
if (false and db(select(count(t.alpha)).from(t).unconditionally()).front().count > 0)
{ /* do something */
}
}
@ -444,7 +444,7 @@ int Function(int, char* [])
static_assert(std::is_same<decltype(sqlpp::tvin("test")), sqlpp::tvin_arg_t<sqlpp::text_operand>>::value,
"text values are accepted and wrapped");
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{
static_assert(std::is_same<decltype(sqlpp::tvin(row.alpha)),
sqlpp::tvin_arg_t<typename std::remove_const<decltype(row.alpha)>::type>>::value,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -163,13 +163,11 @@ int Interpret(int, char* [])
serialize(s, printer).str();
}
{
auto s = dynamic_select(db)
.dynamic_flags(sqlpp::distinct)
.dynamic_columns(t.alpha)
.extra_tables(t); // Would fail to run()
// Behold, dynamically constructed queries might compile but be illegal SQL
auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha);
s.select_flags.add(sqlpp::all);
s.selected_columns.add(t.beta);
s.selected_columns.add(t.gamma);
s.selected_columns.add(without_table_check(t.beta));
s.selected_columns.add(without_table_check(t.gamma));
serialize(s, printer).str();
}
@ -178,10 +176,9 @@ int Interpret(int, char* [])
serialize(avg(sqlpp::distinct, t.alpha - 7), printer).str();
serialize(sum(sqlpp::distinct, t.alpha + 7), printer).str();
serialize(select(all_of(t)).from(t).where(true), printer).str();
serialize(select(all_of(t)).from(t).where(false), printer).str();
serialize(select(all_of(t)).from(t).unconditionally(), printer).str();
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{
serialize(row.alpha, printer);
serialize(row.beta, printer);
@ -201,8 +198,8 @@ int Interpret(int, char* [])
std::cerr << serialize(x, printer).str() << std::endl;
printer.reset();
std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in(select(f.epsilon).from(f).where(true))), printer)
.str() << std::endl;
std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in(select(f.epsilon).from(f).unconditionally())),
printer).str() << std::endl;
printer.reset();
std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in()), printer).str() << std::endl;
@ -214,7 +211,7 @@ int Interpret(int, char* [])
auto s = schema_qualified_table(schema, t).as(sqlpp::alias::x);
printer.reset();
std::cerr << serialize(select(all_of(s)).from(s).where(true), printer).str() << std::endl;
std::cerr << serialize(select(all_of(s)).from(s).unconditionally(), printer).str() << std::endl;
printer.reset();
std::cerr << serialize(sqlpp::case_when(true).then(t.alpha).else_(t.alpha + 1).as(t.beta), printer).str()

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -60,7 +60,7 @@ int Remove(int, char* [])
printer.reset();
std::cerr << serialize(r, printer).str() << std::endl;
printer.reset();
std::cerr << serialize(remove_from(t).where(true), printer).str() << std::endl;
std::cerr << serialize(remove_from(t).unconditionally(), printer).str() << std::endl;
db(r);

View File

@ -42,7 +42,7 @@ int Result(int, char* [])
static_assert(not sqlpp::null_is_trivial_value_t<decltype(t.alpha)>::value, "t.alpha does not say null_is_trivial");
// Using a non-enforcing db
for (const auto& row : db(select(all_of(t), t.beta.like("")).from(t).where(true)))
for (const auto& row : db(select(all_of(t), t.beta.like("")).from(t).unconditionally()))
{
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha interprets null_is_trivial");
@ -64,14 +64,14 @@ int Result(int, char* [])
}
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha interprets null_is_trivial");
}
// Using a non-enforcing db
for (const auto& row : edb(select(all_of(t)).from(t).where(true)))
for (const auto& row : edb(select(all_of(t)).from(t).unconditionally()))
{
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,
@ -79,7 +79,7 @@ int Result(int, char* [])
}
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);
for (const auto& row : edb(select(all_of(t)).from(t).where(true)))
for (const auto& row : edb(select(all_of(t)).from(t).unconditionally()))
{
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,

View File

@ -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
{

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -31,11 +31,12 @@
#include <sqlpp11/select.h>
#include <sqlpp11/functions.h>
#include <sqlpp11/connection.h>
#include <sqlpp11/without_table_check.h>
template <typename Db, typename Column>
int64_t getColumn(Db&& db, const Column& column)
{
auto result = db(select(column.as(sqlpp::alias::a)).from(column.table()).where(true));
auto result = db(select(column.as(sqlpp::alias::a)).from(column.table()).unconditionally());
if (not result.empty())
return result.front().a;
else
@ -59,14 +60,14 @@ int Select(int, char* [])
std::cout << row.a << std::endl;
}
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{
int64_t a = row.alpha;
const std::string b = row.beta;
std::cout << a << ", " << b << std::endl;
}
for (const auto& row : db(select(all_of(t).as(t)).from(t).where(true)))
for (const auto& row : db(select(all_of(t).as(t)).from(t).unconditionally()))
{
int64_t a = row.tabBar.alpha;
const std::string b = row.tabBar.beta;
@ -82,19 +83,19 @@ int Select(int, char* [])
}
for (const auto& row :
db(select(all_of(t), all_of(f)).from(t.join(f).on(t.alpha > f.omega and not t.gamma)).where(true)))
db(select(all_of(t), all_of(f)).from(t.join(f).on(t.alpha > f.omega and not t.gamma)).unconditionally()))
{
std::cout << row.alpha << std::endl;
}
for (const auto& row : db(select(all_of(t), all_of(f))
.from(t.join(f).on(t.alpha > f.omega).join(tab_a).on(t.alpha == tab_a.omega))
.where(true)))
.unconditionally()))
{
std::cout << row.alpha << std::endl;
}
for (const auto& row : db(select(count(t.alpha), avg(t.alpha)).from(t).where(true)))
for (const auto& row : db(select(count(t.alpha), avg(t.alpha)).from(t).unconditionally()))
{
std::cout << row.count << std::endl;
}
@ -108,7 +109,6 @@ int Select(int, char* [])
.columns(all_of(t))
.flags(sqlpp::all)
.from(t)
.extra_tables(f, t)
.where(t.alpha > 0)
.group_by(t.alpha)
.order_by(t.gamma.asc())
@ -122,7 +122,6 @@ int Select(int, char* [])
.columns(all_of(t))
.flags(sqlpp::all)
.from(t)
.extra_tables(f, t)
.where(t.alpha > 0)
.group_by(t.alpha)
.order_by(t.gamma.asc())
@ -137,16 +136,15 @@ int Select(int, char* [])
.dynamic_columns(all_of(t))
.dynamic_flags()
.dynamic_from(t)
.extra_tables(f, t)
.dynamic_where()
.dynamic_group_by(t.alpha)
.dynamic_order_by()
.dynamic_having(t.gamma)
.dynamic_having(sum(t.alpha) > 17)
.dynamic_limit()
.dynamic_offset();
s.select_flags.add(sqlpp::distinct);
s.selected_columns.add(f.omega);
s.from.add(f);
s.selected_columns.add(without_table_check(f.omega));
s.from.add(dynamic_cross_join(f));
s.where.add(t.alpha > 7);
s.having.add(t.alpha > 7);
s.limit.set(3);
@ -165,7 +163,7 @@ int Select(int, char* [])
select(sqlpp::value(7).as(t.alpha));
for (const auto& row :
db(select(sqlpp::case_when(true).then(sqlpp::null).else_(sqlpp::null).as(t.beta)).from(t).where(true)))
db(select(sqlpp::case_when(true).then(sqlpp::null).else_(sqlpp::null).as(t.beta)).from(t).unconditionally()))
{
std::cerr << row.beta << std::endl;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* Copyright (c) 2013-2016, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -31,6 +31,7 @@
#include <sqlpp11/select.h>
#include <sqlpp11/functions.h>
#include <sqlpp11/connection.h>
#include <sqlpp11/without_table_check.h>
namespace alias
{
@ -298,7 +299,7 @@ int SelectType(int, char* [])
t.alpha.as(alias::a) // index 12
)
.from(t)
.where(true)); // next index is 13
.unconditionally()); // next index is 13
using ResultRow = typename Select::_result_methods_t<Select>::template _result_row_t<MockDb>;
using IndexSequence = ResultRow::_field_index_sequence;
static_assert(std::is_same<IndexSequence, sqlpp::detail::field_index_sequence<13, 0, 1, 2, 3, 4, 8, 12>>::value,
@ -318,16 +319,16 @@ int SelectType(int, char* [])
"select with identical columns(name/value_type) need to have identical result_types");
}
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
for (const auto& row : db(select(all_of(t)).from(t).unconditionally()))
{
int64_t a = row.alpha;
std::cout << a << std::endl;
}
{
auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset();
s.from.add(t);
s.where.add_ntc(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3)));
auto s = dynamic_select(db, all_of(t)).dynamic_from(t).dynamic_where().dynamic_limit().dynamic_offset();
s.from.add(dynamic_join(f).on(f.omega > t.alpha));
s.where.add(without_table_check(f.omega > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3))));
s.limit.set(30);
s.limit.set(3);
std::cerr << "------------------------\n";
@ -339,8 +340,8 @@ int SelectType(int, char* [])
// Test that select can be called with zero columns if it is used with dynamic columns.
{
auto s = dynamic_select(db).dynamic_columns().extra_tables(t);
s.selected_columns.add(t.alpha);
auto s = dynamic_select(db).dynamic_columns();
s.selected_columns.add(without_table_check(t.alpha));
serialize(s, printer).str();
}
@ -357,7 +358,8 @@ int SelectType(int, char* [])
static_assert(sqlpp::is_numeric_t<T>::value, "T has to be numeric");
static_assert(sqlpp::is_numeric_t<decltype(t.alpha)>::value, "TabBar.alpha has to be a numeric");
((t.alpha + 7) + 4).asc();
static_assert(sqlpp::is_boolean_t<decltype(t.gamma == t.gamma)>::value, "Comparison expression have to be boolean");
static_assert(sqlpp::is_boolean_t<decltype(t.gamma != not(t.gamma))>::value,
"Comparison expression have to be boolean");
!t.gamma;
serialize(t.beta < "kaesekuchen", printer).str();
serialize(t.beta + "hallenhalma", printer).str();
@ -376,7 +378,7 @@ int SelectType(int, char* [])
auto s1 = sqlpp::select()
.flags(sqlpp::distinct, sqlpp::straight_join)
.columns(l.gamma, r.a)
.from(r, t, l)
.from(r.cross_join(t).cross_join(l))
.where(t.beta == "hello world" and select(t.gamma).from(t)) // .as(alias::right))
.group_by(l.gamma, r.a)
.having(r.a != true)

View File

@ -37,23 +37,23 @@ int Union(int, char* [])
const auto t = test::TabBar{};
const auto f = test::TabFoo{};
db(select(t.alpha).from(t).where(true).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)));
db(select(t.alpha).from(t).unconditionally().union_distinct(select(f.epsilon.as(t.alpha)).from(f).unconditionally()));
db(select(t.alpha).from(t).unconditionally().union_all(select(f.epsilon.as(t.alpha)).from(f).unconditionally()));
auto u = select(t.alpha)
.from(t)
.where(true)
.union_all(select(f.epsilon.as(t.alpha)).from(f).where(true))
.unconditionally()
.union_all(select(f.epsilon.as(t.alpha)).from(f).unconditionally())
.as(sqlpp::alias::u);
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(all_of(u)).from(u).unconditionally().union_all(select(t.delta.as(t.alpha)).from(t).unconditionally()));
db(select(u.alpha).from(u).unconditionally().union_all(select(t.delta.as(t.alpha)).from(t).unconditionally()));
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)));
.unconditionally()
.union_all(select(t.alpha).from(t).unconditionally())
.union_all(select(t.alpha).from(t).unconditionally()));
return 0;
}

View File

@ -54,7 +54,7 @@ int Update(int, char* [])
serialize(update(t), printer).str();
serialize(update(t).set(t.gamma = false), printer).str();
serialize(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).str();
serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).str();
serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta + "this is nonsense"), printer).str();
auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where();
u.assignments.add(t.beta = "cannot update gamma a second time");
u.where.add(t.gamma != false);
@ -63,11 +63,11 @@ int Update(int, char* [])
db(u);
db(update(t).set(t.delta = sqlpp::verbatim<sqlpp::integer>("17+4")).where(true));
db(update(t).set(t.delta = sqlpp::null).where(true));
db(update(t).set(t.delta = sqlpp::default_value).where(true));
db(update(t).set(t.delta = sqlpp::verbatim<sqlpp::integer>("17+4")).unconditionally());
db(update(t).set(t.delta = sqlpp::null).unconditionally());
db(update(t).set(t.delta = sqlpp::default_value).unconditionally());
db(update(t).set(t.delta += t.alpha * 2, t.beta += " and cake").where(true));
db(update(t).set(t.delta += t.alpha * 2, t.beta += " and cake").unconditionally());
return 0;
}

View File

@ -38,16 +38,16 @@ int With(int, char* [])
auto x = sqlpp::cte(sqlpp::alias::x).as(select(all_of(t)).from(t));
db(with(x)(select(x.alpha).from(x).where(true)));
db(with(x)(select(x.alpha).from(x).unconditionally()));
auto y0 = sqlpp::cte(sqlpp::alias::y).as(select(all_of(t)).from(t));
auto y = y0.union_all(select(all_of(y0)).from(y0).where(false));
auto y = y0.union_all(select(all_of(y0)).from(y0).unconditionally());
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)));
db(with(y)(select(y.alpha).from(y).unconditionally()));
return 0;
}