mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Merge remote-tracking branch 'upstream/master' into ddl2cppEmptyTableCheck
This commit is contained in:
commit
dad441f2b9
@ -23,6 +23,9 @@ install:
|
|||||||
- CMAKE_VERSION_MM=3.2
|
- CMAKE_VERSION_MM=3.2
|
||||||
- CMAKE_VERSION_FULL=$CMAKE_VERSION_MM.2
|
- CMAKE_VERSION_FULL=$CMAKE_VERSION_MM.2
|
||||||
- git clone https://github.com/HowardHinnant/date
|
- git clone https://github.com/HowardHinnant/date
|
||||||
|
- cd date
|
||||||
|
- git checkout tags/v1.0.0
|
||||||
|
- cd ..
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then
|
||||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||||
&& sudo add-apt-repository -y ppa:apokluda/boost1.53
|
&& sudo add-apt-repository -y ppa:apokluda/boost1.53
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2013-2015, Roland Bock
|
# Copyright (c) 2013-2016, Roland Bock
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -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")
|
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)
|
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()
|
endif()
|
||||||
|
|
||||||
target_include_directories(sqlpp11 INTERFACE
|
target_include_directories(sqlpp11 INTERFACE
|
||||||
$<BUILD_INTERFACE:${DATE_INCLUDE_DIR}>
|
$<BUILD_INTERFACE:${DATE_INCLUDE_DIR}>
|
||||||
$<BUILD_INTERFACE:${sqlpp11_SOURCE_DIR}/include>
|
$<BUILD_INTERFACE:${sqlpp11_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:include>
|
||||||
)
|
)
|
||||||
|
|
||||||
if (NOT MSVC)
|
if (NOT MSVC)
|
||||||
@ -64,10 +71,51 @@ target_compile_features(sqlpp11 INTERFACE
|
|||||||
)
|
)
|
||||||
endif ()
|
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(tests)
|
||||||
|
add_subdirectory(test_types)
|
||||||
|
add_subdirectory(test_serializer)
|
||||||
add_subdirectory(test_static_asserts)
|
add_subdirectory(test_static_asserts)
|
||||||
add_subdirectory(test_constraints)
|
add_subdirectory(test_constraints)
|
||||||
add_subdirectory(examples)
|
add_subdirectory(examples)
|
||||||
|
|
||||||
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/sqlpp11" DESTINATION include)
|
|
||||||
|
|
||||||
|
109
ChangeLog.md
Normal file
109
ChangeLog.md
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
Important changes in sqlpp11
|
||||||
|
============================
|
||||||
|
|
||||||
|
Breaking changes in 0.36:
|
||||||
|
-------------------------
|
||||||
|
__Abstract__:
|
||||||
|
|
||||||
|
One of the main motivations of sqlpp11 is to prevent SQL programming mistakes at compile time. The following changes prevent reported mishaps.
|
||||||
|
* `from(a,b)` not allowed anymore, please use explicit joins
|
||||||
|
* `where(true)` not allowed anymore, please use `.unconditionally()` or sqlpp::value(true)
|
||||||
|
* `some_sql_expression and true` not allowed anymore, please use `tab.col == sqlpp::value(true)` if you really want to express this.
|
||||||
|
* `having(expression)` requires `expression` to be made of aggregates, e.g. columns named in `group_by()` or aggregate functions like `count()` or constant values.
|
||||||
|
* `where()` and `having` accept only one parameter
|
||||||
|
|
||||||
|
__Explicit joins required__:
|
||||||
|
|
||||||
|
Up until sqlpp11-0.35 you could write something like
|
||||||
|
|
||||||
|
```
|
||||||
|
auto result = db(select(all_of(a), all_of(b))
|
||||||
|
.from(a,b)
|
||||||
|
.where(true));
|
||||||
|
```
|
||||||
|
|
||||||
|
Using this syntax in `from()`, it was expected to have the join condition implicitly in the `where()` call.
|
||||||
|
But there is no reliable way to tell whether or not that condition is there. Or, if there definitely is none, whether
|
||||||
|
it was omitted on purpose or by accident.
|
||||||
|
In one case, an accidentally omitted join condition in the `where()` brought a production system to a screeching halt.
|
||||||
|
|
||||||
|
In order to prevent this in the future, sqlpp11 now requires you to join table explicitly, including an explicit join condition, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
auto result = db(select(all_of(a), all_of(b))
|
||||||
|
.from(a.join(b).on(a.b == b.id))
|
||||||
|
.where(true));
|
||||||
|
```
|
||||||
|
|
||||||
|
Most joins, (`join`/`inner_join`, `left_outer_join`, `right_outer_join` and `outer_join`) require a join condition to given via `on()`.
|
||||||
|
The join condition has to be some sqlpp11 boolean expression.
|
||||||
|
|
||||||
|
In those rare cases, when you really need a cross join, you can also use `cross_join()` which has no join condition, of course.
|
||||||
|
|
||||||
|
```
|
||||||
|
auto result = db(select(all_of(a), all_of(b))
|
||||||
|
.from(a.cross_join(b))
|
||||||
|
.where(true));
|
||||||
|
```
|
||||||
|
|
||||||
|
__Use `.unconditionally()`__
|
||||||
|
|
||||||
|
If you want to select/update/remove all rows, earlier versions of sqlpp11 required the use of `where(true)`. Since version 0.36, use `unconditionally()`, for instance:
|
||||||
|
```
|
||||||
|
auto result = db(select(all_of(t)).from(t).unconditionally());
|
||||||
|
```
|
||||||
|
|
||||||
|
__Use `sqlpp::value()` to wrap bool values in boolean expressions__
|
||||||
|
|
||||||
|
Lets say you had
|
||||||
|
|
||||||
|
```
|
||||||
|
struct X
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
};
|
||||||
|
auto x = X{};
|
||||||
|
```
|
||||||
|
|
||||||
|
Then earlier versions of sqlpp11 would compile the following expression:
|
||||||
|
|
||||||
|
```
|
||||||
|
select(all_of(t)).from(t).where(x.a == x.a or t.b == t.b);
|
||||||
|
```
|
||||||
|
|
||||||
|
What you probably meant was:
|
||||||
|
|
||||||
|
```
|
||||||
|
select(all_of(t)).from(t).where(t.a == x.a and t.b == x.b);
|
||||||
|
```
|
||||||
|
|
||||||
|
In order to prevent this kind of mistake, boolean operators in sql expressions require sqlpp boolean expressions as operators.
|
||||||
|
The library also requires the types of the left/right hand side operands of a comparison to be different, so that `t.a < t.a` does not compile any more.
|
||||||
|
|
||||||
|
In the rare case you really have a bool value that you want to use a boolean sql expression, you have to wrap it in sqlpp::value(x), e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
select(all_of(t)).from(t).where(sqlpp::value(x.a == 17) and t.b == x.b);
|
||||||
|
```
|
||||||
|
|
||||||
|
__`having()` requires aggregate expressions__
|
||||||
|
|
||||||
|
In older versions, the following code was allowed:
|
||||||
|
|
||||||
|
```
|
||||||
|
select(all_of(t)).from(t).where(t.a > 7).having(t.b != "");
|
||||||
|
```
|
||||||
|
|
||||||
|
As of sqlpp11-0.36, the having argument must be made of aggregate columns or functions, e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
select(all_of(t)).from(t).unconditionally().group_by(t.b).having(t.b != "", avg(t.c) < 42);
|
||||||
|
```
|
||||||
|
|
||||||
|
__`where()` and `having` accept only one expression__
|
||||||
|
|
||||||
|
In older versions, `where()` and `having()` would accept more than one argument and combine those arguments with `and`.
|
||||||
|
I am not sure this was ever used. So it just made life harder for the compiler.
|
||||||
|
|
||||||
|
As of version 0.36, `where()` and `having()` accept only one parameter.
|
55
README.md
55
README.md
@ -1,31 +1,22 @@
|
|||||||
sqlpp11
|
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
|
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)
|
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)
|
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:
|
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.
|
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.
|
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:
|
Examples:
|
||||||
---------
|
---------
|
||||||
For the examples, lets assume you have a table class representing something like
|
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));
|
db(remove_from(foo).where(not foo.hasFun));
|
||||||
```
|
```
|
||||||
|
|
||||||
Your help is needed:
|
Additional information available:
|
||||||
--------------------
|
---------------------------------
|
||||||
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.
|
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:
|
Requirements:
|
||||||
@ -125,6 +132,7 @@ sqlpp11 requires a certain api in order to connect with the database, see databa
|
|||||||
* MySQL: https://github.com/rbock/sqlpp11-connector-mysql
|
* MySQL: https://github.com/rbock/sqlpp11-connector-mysql
|
||||||
* Sqlite3: https://github.com/rbock/sqlpp11-connector-sqlite3
|
* Sqlite3: https://github.com/rbock/sqlpp11-connector-sqlite3
|
||||||
* PostgreSQL: https://github.com/matthijs/sqlpp11-connector-postgresql
|
* PostgreSQL: https://github.com/matthijs/sqlpp11-connector-postgresql
|
||||||
|
* ODBC: https://github.com/Erroneous1/sqlpp11-connector-odbc (experimental)
|
||||||
|
|
||||||
To demonstrate that sqlpp11 can work with other backends as well, here is an experimental backend for structs in standard containers:
|
To demonstrate that sqlpp11 can work with other backends as well, here is an experimental backend for structs in standard containers:
|
||||||
|
|
||||||
@ -159,3 +167,4 @@ Include generated header (MyTable.h), that's all
|
|||||||
License:
|
License:
|
||||||
-------------
|
-------------
|
||||||
sqlpp11 is distributed under the [BSD 2-Clause License](https://github.com/rbock/sqlpp11/blob/master/LICENSE).
|
sqlpp11 is distributed under the [BSD 2-Clause License](https://github.com/rbock/sqlpp11/blob/master/LICENSE).
|
||||||
|
|
||||||
|
26
cmake/Sqlpp11Config.cmake
Normal file
26
cmake/Sqlpp11Config.cmake
Normal 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")
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -111,7 +111,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
"avg() cannot be used on an aggregate function");
|
"avg() cannot be used on an aggregate function");
|
||||||
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
|
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a numeric value expression as argument");
|
||||||
return {t};
|
return {t};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
"avg() cannot be used on an aggregate function");
|
"avg() cannot be used on an aggregate function");
|
||||||
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
|
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a numeric value expression as argument");
|
||||||
return {t};
|
return {t};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,8 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
struct bad_statement
|
struct bad_statement
|
||||||
{
|
{
|
||||||
|
static constexpr bool value = false;
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
bad_statement(T&&...)
|
bad_statement(T&&...)
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -28,7 +28,7 @@
|
|||||||
#define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H
|
#define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H
|
||||||
|
|
||||||
#include <sqlpp11/value_type_fwd.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/portable_static_assert.h>
|
||||||
#include <sqlpp11/consistent.h>
|
#include <sqlpp11/consistent.h>
|
||||||
#include <sqlpp11/alias.h>
|
#include <sqlpp11/alias.h>
|
||||||
@ -41,206 +41,171 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
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>
|
template <typename LhsType, typename RhsType>
|
||||||
using check_rhs_comparison_operand_t =
|
using check_comparison_impl = static_combined_check_t<
|
||||||
static_check_t<(is_expression_t<sqlpp::wrap_operand_t<RhsType>>::value // expressions are OK
|
static_check_t<logic::any_t<is_expression_t<RhsType>::value, is_multi_expression_t<RhsType>::value>::value,
|
||||||
or
|
assert_comparison_rhs_is_expression_t>,
|
||||||
is_multi_expression_t<sqlpp::wrap_operand_t<RhsType>>::value) // multi-expressions like ANY are
|
static_check_t<value_type_of<LhsType>::template _is_valid_operand<RhsType>::value,
|
||||||
// OK for comparisons, too
|
assert_comparison_rhs_is_valid_operand_t>,
|
||||||
and
|
static_check_t<not std::is_same<LhsType, RhsType>::value, assert_comparison_lhs_rhs_differ_t>>;
|
||||||
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>;
|
|
||||||
|
|
||||||
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>
|
template <typename LhsType, typename... RhsType>
|
||||||
using check_rhs_in_arguments_t =
|
using check_in_impl = static_combined_check_t<
|
||||||
static_check_t<logic::all_t<check_rhs_comparison_operand_t<LhsValueType, InTypes>::value...>::value,
|
static_check_t<logic::all_t<is_expression_t<RhsType>::value...>::value, assert_comparison_rhs_is_expression_t>,
|
||||||
assert_valid_in_arguments_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 <typename LhsType, typename... RhsType>
|
||||||
{
|
using check_in_t = check_in_impl<LhsType, typename wrap_operand<RhsType>::type...>;
|
||||||
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;
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template <bool Enable, template <typename Lhs, typename Rhs> class Expr, typename Lhs, typename Rhs>
|
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>
|
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>
|
template <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;
|
using comparison_expression_t =
|
||||||
|
typename detail::comparison_expression_impl<check_comparison_t<Lhs, Rhs>::value, Expr, Lhs, Rhs>::type;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template <bool Enable, template <typename Lhs, typename... Rhs> class Expr, typename Lhs, typename... Rhs>
|
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>
|
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...>;
|
using type = Expr<Lhs, Rhs...>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
template <typename Check, template <typename Lhs, typename... Rhs> class Expr, typename Lhs, typename... 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
|
// basic operators
|
||||||
template <typename Expr, typename ValueType>
|
template <typename Expr>
|
||||||
struct basic_expression_operators
|
struct basic_expression_operators
|
||||||
{
|
{
|
||||||
template <template <typename Lhs, typename Rhs> class NewExpr, typename T>
|
template <template <typename Lhs, typename Rhs> class NewExpr, typename T>
|
||||||
using _new_binary_expression_t =
|
struct _new_binary_expression
|
||||||
new_binary_expression_t<check_rhs_comparison_operand_t<ValueType, wrap_operand_t<T>>,
|
{
|
||||||
NewExpr,
|
using type = comparison_expression_t<NewExpr, Expr, T>;
|
||||||
Expr,
|
};
|
||||||
wrap_operand_t<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>
|
template <template <typename Lhs, typename... Rhs> class NewExpr, typename... T>
|
||||||
struct _new_nary_expression
|
struct _new_nary_expression
|
||||||
{
|
{
|
||||||
using type =
|
using _check = check_in_t<Expr, T...>;
|
||||||
new_nary_expression_t<logic::all_t<check_rhs_comparison_operand_t<ValueType, wrap_operand_t<T>>::value...>,
|
using type = in_expression_t<_check, NewExpr, Expr, wrap_operand_t<T>...>;
|
||||||
NewExpr,
|
|
||||||
Expr,
|
|
||||||
wrap_operand_t<T>...>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename 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>;
|
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<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>::_();
|
|
||||||
|
|
||||||
return {*static_cast<const Expr*>(this), rhs{t}};
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename 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>;
|
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}};
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename 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>;
|
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}};
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename 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>;
|
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}};
|
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)};
|
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)};
|
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)};
|
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)};
|
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>
|
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}...};
|
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>
|
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}...};
|
return {*static_cast<const Expr*>(this), typename wrap_operand<T>::type{t}...};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#ifndef SQLPP_CHRONO_H
|
#ifndef SQLPP_CHRONO_H
|
||||||
#define SQLPP_CHRONO_H
|
#define SQLPP_CHRONO_H
|
||||||
|
|
||||||
#include <chrono>
|
#include <date.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -37,6 +37,13 @@ namespace sqlpp
|
|||||||
|
|
||||||
using day_point = std::chrono::time_point<std::chrono::system_clock, days>;
|
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>;
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,26 +35,26 @@
|
|||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename Expression>
|
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>
|
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 check = consistent_t;
|
||||||
using type = logical_and_t<wrap_operand_t<L>, wrap_operand_t<R>>;
|
using type = logical_and_t<wrap_operand_t<L>, wrap_operand_t<R>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename L, typename 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 check = consistent_t;
|
||||||
using type = logical_or_t<wrap_operand_t<L>, wrap_operand_t<R>>;
|
using type = logical_or_t<wrap_operand_t<L>, wrap_operand_t<R>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Defer>
|
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 check = consistent_t;
|
||||||
using type = logical_not_t<wrap_operand_t<T>>;
|
using type = logical_not_t<wrap_operand_t<T>>;
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename Expression>
|
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>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
bool _is_trivial() const
|
bool _is_trivial() const
|
||||||
{
|
{
|
||||||
return _t == _value_t{};
|
return std::chrono::operator==(_t, _value_t{});
|
||||||
}
|
}
|
||||||
|
|
||||||
_value_t _t;
|
_value_t _t;
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename Expr>
|
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>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#ifndef SQLPP_FLOATING_POINT_RESULT_FIELD_H
|
#ifndef SQLPP_FLOATING_POINT_RESULT_FIELD_H
|
||||||
#define 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/exception.h>
|
||||||
#include <sqlpp11/result_field.h>
|
#include <sqlpp11/result_field.h>
|
||||||
#include <sqlpp11/result_field_base.h>
|
#include <sqlpp11/result_field_base.h>
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename Expression>
|
template <typename Expression>
|
||||||
struct expression_operators<Expression, integral> : public basic_expression_operators<Expression, integral>
|
struct expression_operators<Expression, integral> : public basic_expression_operators<Expression>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename Expression>
|
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>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Expression>
|
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>
|
template <typename T>
|
||||||
using _is_valid_operand = is_valid_operand<text, T>;
|
using _is_valid_operand = is_valid_operand<text, T>;
|
||||||
|
@ -36,7 +36,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
// time_point expression operators
|
// time_point expression operators
|
||||||
template <typename Expression>
|
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>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
#ifndef SQLPP_TIME_POINT_OPERAND_H
|
#ifndef SQLPP_TIME_POINT_OPERAND_H
|
||||||
#define SQLPP_TIME_POINT_OPERAND_H
|
#define SQLPP_TIME_POINT_OPERAND_H
|
||||||
|
|
||||||
#include <date.h>
|
|
||||||
#include <sqlpp11/chrono.h>
|
#include <sqlpp11/chrono.h>
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/alias_operators.h>
|
#include <sqlpp11/alias_operators.h>
|
||||||
@ -62,7 +61,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
bool _is_trivial() const
|
bool _is_trivial() const
|
||||||
{
|
{
|
||||||
return _t == _value_t{};
|
return std::chrono::operator==(_t, _value_t{});
|
||||||
}
|
}
|
||||||
|
|
||||||
_value_t _t;
|
_value_t _t;
|
||||||
@ -76,7 +75,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
static Context& _(const Operand& t, Context& context)
|
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 time = ::date::make_time(t._t - dp);
|
||||||
const auto ymd = ::date::year_month_day{dp};
|
const auto ymd = ::date::year_month_day{dp};
|
||||||
context << "TIMESTAMP '" << ymd << ' ' << time << "'";
|
context << "TIMESTAMP '" << ymd << ' ' << time << "'";
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#ifndef SQLPP_TIME_POINT_RESULT_FIELD_H
|
#ifndef SQLPP_TIME_POINT_RESULT_FIELD_H
|
||||||
#define 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/basic_expression_operators.h>
|
||||||
#include <sqlpp11/result_field.h>
|
#include <sqlpp11/result_field.h>
|
||||||
#include <sqlpp11/result_field_base.h>
|
#include <sqlpp11/result_field_base.h>
|
||||||
@ -63,7 +64,7 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
else
|
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 time = ::date::make_time(e.value() - dp);
|
||||||
const auto ymd = ::date::year_month_day{dp};
|
const auto ymd = ::date::year_month_day{dp};
|
||||||
os << ymd << 'T' << time;
|
os << ymd << 'T' << time;
|
||||||
|
@ -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
|
|
66
include/sqlpp11/dynamic_join.h
Normal file
66
include/sqlpp11/dynamic_join.h
Normal 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
|
170
include/sqlpp11/dynamic_pre_join.h
Normal file
170
include/sqlpp11/dynamic_pre_join.h
Normal 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
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <sqlpp11/no_name.h>
|
||||||
#include <sqlpp11/named_interpretable.h>
|
#include <sqlpp11/named_interpretable.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
@ -51,24 +52,59 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
return _dynamic_columns.empty();
|
return _dynamic_columns.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto size() -> size_t
|
||||||
|
{
|
||||||
|
return _dynamic_columns.size();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct dynamic_select_column_list<void>
|
struct dynamic_select_column_list<void>
|
||||||
{
|
{
|
||||||
struct _names_t
|
using _names_t = no_name_t;
|
||||||
{
|
|
||||||
static constexpr size_t size()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
_names_t _dynamic_expression_names;
|
_names_t _dynamic_expression_names;
|
||||||
|
|
||||||
static constexpr bool empty()
|
static constexpr bool empty()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr auto size() -> size_t
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 _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>;
|
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 _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>;
|
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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ namespace sqlpp
|
|||||||
struct return_type_plus
|
struct return_type_plus
|
||||||
{
|
{
|
||||||
using check = assert_valid_operands;
|
using check = assert_valid_operands;
|
||||||
using type = bad_expression<boolean>;
|
using type = bad_expression<value_type_of<L>>;
|
||||||
};
|
};
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using return_type_plus_t = typename return_type_plus<L, R>::type;
|
using return_type_plus_t = typename return_type_plus<L, R>::type;
|
||||||
@ -89,7 +89,7 @@ namespace sqlpp
|
|||||||
struct return_type_minus
|
struct return_type_minus
|
||||||
{
|
{
|
||||||
using check = assert_valid_operands;
|
using check = assert_valid_operands;
|
||||||
using type = bad_expression<boolean>;
|
using type = bad_expression<value_type_of<L>>;
|
||||||
};
|
};
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using return_type_minus_t = typename return_type_minus<L, R>::type;
|
using return_type_minus_t = typename return_type_minus<L, R>::type;
|
||||||
@ -98,7 +98,7 @@ namespace sqlpp
|
|||||||
struct return_type_multiplies
|
struct return_type_multiplies
|
||||||
{
|
{
|
||||||
using check = assert_valid_operands;
|
using check = assert_valid_operands;
|
||||||
using type = bad_expression<boolean>;
|
using type = bad_expression<value_type_of<L>>;
|
||||||
};
|
};
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using return_type_multiplies_t = typename return_type_multiplies<L, R>::type;
|
using return_type_multiplies_t = typename return_type_multiplies<L, R>::type;
|
||||||
@ -107,7 +107,7 @@ namespace sqlpp
|
|||||||
struct return_type_divides
|
struct return_type_divides
|
||||||
{
|
{
|
||||||
using check = assert_valid_operands;
|
using check = assert_valid_operands;
|
||||||
using type = bad_expression<boolean>;
|
using type = bad_expression<value_type_of<L>>;
|
||||||
};
|
};
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using return_type_divides_t = typename return_type_divides<L, R>::type;
|
using return_type_divides_t = typename return_type_divides<L, R>::type;
|
||||||
@ -116,7 +116,7 @@ namespace sqlpp
|
|||||||
struct return_type_modulus
|
struct return_type_modulus
|
||||||
{
|
{
|
||||||
using check = assert_valid_operands;
|
using check = assert_valid_operands;
|
||||||
using type = bad_expression<boolean>;
|
using type = bad_expression<value_type_of<L>>;
|
||||||
};
|
};
|
||||||
template <typename L, typename R>
|
template <typename L, typename R>
|
||||||
using return_type_modulus_t = typename return_type_modulus<L, R>::type;
|
using return_type_modulus_t = typename return_type_modulus<L, R>::type;
|
||||||
@ -125,7 +125,7 @@ namespace sqlpp
|
|||||||
struct return_type_unary_plus
|
struct return_type_unary_plus
|
||||||
{
|
{
|
||||||
using check = assert_valid_operands;
|
using check = assert_valid_operands;
|
||||||
using type = bad_expression<boolean>;
|
using type = bad_expression<value_type_of<T>>;
|
||||||
};
|
};
|
||||||
template <typename T, typename Defer>
|
template <typename T, typename Defer>
|
||||||
using return_type_unary_plus_t = typename return_type_unary_plus<T, Defer>::type;
|
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
|
struct return_type_unary_minus
|
||||||
{
|
{
|
||||||
using check = assert_valid_operands;
|
using check = assert_valid_operands;
|
||||||
using type = bad_expression<boolean>;
|
using type = bad_expression<value_type_of<T>>;
|
||||||
};
|
};
|
||||||
template <typename T, typename Defer>
|
template <typename T, typename Defer>
|
||||||
using return_type_unary_minus_t = typename return_type_unary_minus<T, Defer>::type;
|
using return_type_unary_minus_t = typename return_type_unary_minus<T, Defer>::type;
|
||||||
|
@ -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
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -35,14 +35,15 @@
|
|||||||
#include <sqlpp11/logic.h>
|
#include <sqlpp11/logic.h>
|
||||||
#include <sqlpp11/detail/sum.h>
|
#include <sqlpp11/detail/sum.h>
|
||||||
#include <sqlpp11/policy_update.h>
|
#include <sqlpp11/policy_update.h>
|
||||||
|
#include <sqlpp11/dynamic_join.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// FROM DATA
|
// FROM DATA
|
||||||
template <typename Database, typename... Tables>
|
template <typename Database, typename Table>
|
||||||
struct from_data_t
|
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& operator=(from_data_t&&) = default;
|
||||||
~from_data_t() = default;
|
~from_data_t() = default;
|
||||||
|
|
||||||
std::tuple<Tables...> _tables;
|
Table _table;
|
||||||
interpretable_list_t<Database> _dynamic_tables;
|
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
|
// FROM
|
||||||
template <typename Database, typename... Tables>
|
template <typename Database, typename Table>
|
||||||
struct from_t
|
struct from_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_from>;
|
using _traits = make_traits<no_value_t, tag::is_from>;
|
||||||
using _nodes = detail::type_vector<Tables...>;
|
using _nodes = detail::type_vector<Table>;
|
||||||
using _is_dynamic = is_database<Database>;
|
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = from_data_t<Database, Tables...>;
|
using _data_t = from_data_t<Database, Table>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
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
|
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
|
||||||
_impl_t() = default;
|
_impl_t() = default;
|
||||||
_impl_t(const _data_t& data) : _data(data)
|
_impl_t(const _data_t& data) : _data(data)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Table>
|
template <typename DynamicJoin>
|
||||||
void add(Table table)
|
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()");
|
using Check = check_from_add_t<_impl_t, DynamicJoin>;
|
||||||
static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
|
Check::_();
|
||||||
using _known_tables =
|
return _add_impl(dynamicJoin, Check{});
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename Table>
|
template <typename DynamicJoin>
|
||||||
void _add_impl(Table table, const std::true_type&)
|
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>
|
template <typename DynamicJoin>
|
||||||
void _add_impl(Table table, const std::false_type&);
|
auto _add_impl(DynamicJoin dynamicJoin, const std::false_type&) -> bad_statement;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
@ -115,7 +142,7 @@ namespace sqlpp
|
|||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
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
|
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
|
||||||
template <typename... Args>
|
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
|
struct no_from_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
@ -197,86 +257,72 @@ namespace sqlpp
|
|||||||
|
|
||||||
using _database_t = typename Policies::_database_t;
|
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>
|
template <typename Check, typename T>
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_from_t, T>;
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_from_t, T>;
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = consistent_t;
|
||||||
|
|
||||||
template <typename... Tables>
|
template <typename Table>
|
||||||
auto from(Tables... tables) const -> _new_statement_t<_check<Tables...>, from_t<void, from_table_t<Tables>...>>
|
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()");
|
using Check = check_from_static_t<Table>;
|
||||||
static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
|
Check{}._();
|
||||||
return _from_impl<void>(_check<Tables...>{}, tables...);
|
return _from_impl<void>(Check{}, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Tables>
|
template <typename Table>
|
||||||
auto dynamic_from(Tables... tables) const
|
auto dynamic_from(Table table) const
|
||||||
-> _new_statement_t<_check<Tables...>, from_t<_database_t, from_table_t<Tables>...>>
|
-> _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,
|
using Check = check_from_dynamic_t<_database_t, Table>;
|
||||||
"dynamic_from must not be called in a static statement");
|
Check{}._();
|
||||||
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
|
return _from_impl<_database_t>(Check{}, table);
|
||||||
return _from_impl<_database_t>(_check<Tables...>{}, tables...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename Database, typename... Tables>
|
template <typename Database, typename Table>
|
||||||
auto _from_impl(const std::false_type&, Tables... tables) const -> bad_statement;
|
auto _from_impl(const std::false_type&, Table table) const -> bad_statement;
|
||||||
|
|
||||||
template <typename Database, typename... Tables>
|
template <typename Database, typename Table>
|
||||||
auto _from_impl(const std::true_type&, Tables... tables) const
|
auto _from_impl(const std::true_type&, Table table) const
|
||||||
-> _new_statement_t<std::true_type, from_t<Database, from_table_t<Tables>...>>
|
-> _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),
|
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
|
// Interpreters
|
||||||
template <typename Context, typename Database, typename... Tables>
|
template <typename Context, typename Database, typename Table>
|
||||||
struct serializer_t<Context, from_data_t<Database, Tables...>>
|
struct serializer_t<Context, from_data_t<Database, Table>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Tables...>;
|
using _serialize_check = serialize_check_of<Context, Table>;
|
||||||
using T = from_data_t<Database, Tables...>;
|
using T = from_data_t<Database, Table>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if (sizeof...(Tables) == 0 and t._dynamic_tables.empty())
|
|
||||||
return context;
|
|
||||||
context << " FROM ";
|
context << " FROM ";
|
||||||
interpret_tuple(t._tables, ',', context);
|
serialize(t._table, context);
|
||||||
if (sizeof...(Tables) and not t._dynamic_tables.empty())
|
if (not t._dynamic_tables.empty())
|
||||||
context << ',';
|
{
|
||||||
interpret_list(t._dynamic_tables, ',', context);
|
interpret_list(t._dynamic_tables, "", context);
|
||||||
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... T>
|
template <typename T>
|
||||||
auto from(T&&... t) -> decltype(statement_t<void, no_from_t>().from(std::forward<T>(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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -42,19 +42,12 @@
|
|||||||
#include <sqlpp11/value_type.h>
|
#include <sqlpp11/value_type.h>
|
||||||
#include <sqlpp11/verbatim.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim
|
#include <sqlpp11/verbatim.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim
|
||||||
#include <sqlpp11/verbatim_table.h>
|
#include <sqlpp11/verbatim_table.h>
|
||||||
|
#include <sqlpp11/value.h>
|
||||||
#include <sqlpp11/value_or_null.h>
|
#include <sqlpp11/value_or_null.h>
|
||||||
#include <sqlpp11/eval.h>
|
#include <sqlpp11/eval.h>
|
||||||
|
|
||||||
namespace sqlpp
|
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>
|
template <typename Expression, typename Db>
|
||||||
auto flatten(const Expression& exp, Db& db) -> verbatim_t<value_type_of<Expression>>
|
auto flatten(const Expression& exp, Db& db) -> verbatim_t<value_type_of<Expression>>
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -85,17 +85,11 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expression>
|
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)
|
void add(Expression expression)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "add() must not be called for static group_by");
|
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(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()");
|
"expression uses tables unknown to this statement in group_by::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, Expression>;
|
||||||
_serialize_check::_();
|
_serialize_check::_();
|
||||||
@ -277,6 +271,19 @@ namespace sqlpp
|
|||||||
return context;
|
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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -28,6 +28,7 @@
|
|||||||
#define SQLPP_HAVING_H
|
#define SQLPP_HAVING_H
|
||||||
|
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/value.h>
|
||||||
#include <sqlpp11/expression.h>
|
#include <sqlpp11/expression.h>
|
||||||
#include <sqlpp11/interpret_tuple.h>
|
#include <sqlpp11/interpret_tuple.h>
|
||||||
#include <sqlpp11/interpretable_list.h>
|
#include <sqlpp11/interpretable_list.h>
|
||||||
@ -37,10 +38,10 @@
|
|||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// HAVING DATA
|
// HAVING DATA
|
||||||
template <typename Database, typename... Expressions>
|
template <typename Database, typename Expression>
|
||||||
struct having_data_t
|
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& operator=(having_data_t&&) = default;
|
||||||
~having_data_t() = default;
|
~having_data_t() = default;
|
||||||
|
|
||||||
std::tuple<Expressions...> _expressions;
|
Expression _expression;
|
||||||
interpretable_list_t<Database> _dynamic_expressions;
|
interpretable_list_t<Database> _dynamic_expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(
|
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");
|
"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
|
// HAVING
|
||||||
template <typename Database, typename... Expressions>
|
template <typename Database, typename Expression>
|
||||||
struct having_t
|
struct having_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_having>;
|
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>;
|
using _is_dynamic = is_database<Database>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = having_data_t<Database, Expressions...>;
|
using _data_t = having_data_t<Database, Expression>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
@ -80,36 +84,30 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expression>
|
template <typename Expr>
|
||||||
void add_ntc(Expression expression)
|
void add(Expr expression)
|
||||||
{
|
|
||||||
add<Expression, std::false_type>(expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Expression, typename TableCheckRequired = std::true_type>
|
|
||||||
void add(Expression expression)
|
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having");
|
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(is_expression_t<Expr>::value, "invalid expression argument in having::add()");
|
||||||
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value,
|
static_assert(Policies::template _no_unknown_tables<Expr>::value,
|
||||||
"expression uses tables unknown to this statement in having::add()");
|
"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::_();
|
_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
|
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename Expression>
|
template <typename Expr>
|
||||||
void _add_impl(Expression expression, const std::true_type&)
|
void _add_impl(Expr expression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return _data._dynamic_expressions.emplace_back(expression);
|
return _data._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expression>
|
template <typename Expr>
|
||||||
void _add_impl(Expression expression, const std::false_type&);
|
void _add_impl(Expr expression, const std::false_type&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
@ -119,7 +117,7 @@ namespace sqlpp
|
|||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
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
|
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
@ -144,12 +142,46 @@ namespace sqlpp
|
|||||||
return t.having;
|
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,
|
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
|
// NO HAVING YET
|
||||||
struct no_having_t
|
struct no_having_t
|
||||||
{
|
{
|
||||||
@ -216,59 +248,76 @@ namespace sqlpp
|
|||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = consistent_t;
|
||||||
|
|
||||||
template <typename... Expressions>
|
template <typename Expression>
|
||||||
auto having(Expressions... expressions) const
|
auto having(Expression expression) const
|
||||||
-> _new_statement_t<_check<Expressions...>, having_t<void, Expressions...>>
|
-> _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()");
|
using Check = check_having_static_t<Expression>;
|
||||||
static_assert(sizeof...(Expressions), "at least one expression argument required in having()");
|
Check{}._();
|
||||||
|
|
||||||
return _having_impl<void>(_check<Expressions...>{}, expressions...);
|
return _having_impl<void>(Check{}, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Expressions>
|
template <typename Expression>
|
||||||
auto dynamic_having(Expressions... expressions) const
|
auto dynamic_having(Expression expression) const
|
||||||
-> _new_statement_t<_check<Expressions...>, having_t<_database_t, Expressions...>>
|
-> _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()");
|
using Check = check_having_dynamic_t<_database_t, Expression>;
|
||||||
static_assert(not std::is_same<_database_t, void>::value,
|
Check{}._();
|
||||||
"dynamic_having must not be called in a static statement");
|
|
||||||
return _having_impl<_database_t>(_check<Expressions...>{}, expressions...);
|
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:
|
private:
|
||||||
template <typename Database, typename... Expressions>
|
template <typename Database, typename Expression>
|
||||||
auto _having_impl(const std::false_type&, Expressions... expressions) const -> bad_statement;
|
auto _having_impl(const std::false_type&, Expression expression) const -> bad_statement;
|
||||||
|
|
||||||
template <typename Database, typename... Expressions>
|
template <typename Database, typename Expression>
|
||||||
auto _having_impl(const std::true_type&, Expressions... expressions) const
|
auto _having_impl(const std::true_type&, Expression expression) const
|
||||||
-> _new_statement_t<std::true_type, having_t<Database, Expressions...>>
|
-> _new_statement_t<std::true_type, having_t<Database, Expression>>
|
||||||
{
|
{
|
||||||
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
||||||
having_data_t<Database, Expressions...>{expressions...}};
|
having_data_t<Database, Expression>{expression}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Interpreters
|
// Interpreters
|
||||||
template <typename Context, typename Database, typename... Expressions>
|
template <typename Context, typename Database, typename Expression>
|
||||||
struct serializer_t<Context, having_data_t<Database, Expressions...>>
|
struct serializer_t<Context, having_data_t<Database, Expression>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
using _serialize_check = serialize_check_of<Context, Expression>;
|
||||||
using T = having_data_t<Database, Expressions...>;
|
using T = having_data_t<Database, Expression>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
|
||||||
return context;
|
|
||||||
context << " HAVING ";
|
context << " HAVING ";
|
||||||
interpret_tuple(t._expressions, " AND ", context);
|
serialize(t._expression, context);
|
||||||
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
if (not t._dynamic_expressions.empty())
|
||||||
context << " AND ";
|
context << " AND ";
|
||||||
interpret_list(t._dynamic_expressions, " AND ", context);
|
interpret_list(t._dynamic_expressions, " AND ", context);
|
||||||
return 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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -39,6 +39,7 @@
|
|||||||
#include <sqlpp11/simple_column.h>
|
#include <sqlpp11/simple_column.h>
|
||||||
#include <sqlpp11/no_data.h>
|
#include <sqlpp11/no_data.h>
|
||||||
#include <sqlpp11/policy_update.h>
|
#include <sqlpp11/policy_update.h>
|
||||||
|
#include <sqlpp11/statement.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -252,12 +253,6 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Assignment>
|
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)
|
void add(Assignment assignment)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "add must not be called for static from()");
|
static_assert(_is_dynamic::value, "add must not be called for static from()");
|
||||||
@ -266,7 +261,7 @@ namespace sqlpp
|
|||||||
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value,
|
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value,
|
||||||
"Must not assign value to column twice");
|
"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 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");
|
"add() contains a column from a foreign table");
|
||||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Assignment>;
|
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Assignment>;
|
||||||
_serialize_check::_();
|
_serialize_check::_();
|
||||||
@ -641,6 +636,20 @@ namespace sqlpp
|
|||||||
return context;
|
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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -27,125 +27,70 @@
|
|||||||
#ifndef SQLPP_JOIN_H
|
#ifndef SQLPP_JOIN_H
|
||||||
#define 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/on.h>
|
||||||
#include <sqlpp11/noop.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct inner_join_t
|
template <typename PreJoin, typename On>
|
||||||
{
|
|
||||||
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>
|
|
||||||
struct join_t
|
struct join_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
|
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
|
||||||
using _nodes = detail::type_vector<Lhs, Rhs>;
|
using _nodes = detail::type_vector<PreJoin, On>;
|
||||||
using _can_be_null = std::false_type;
|
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");
|
template <typename T>
|
||||||
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
|
auto join(T t) const -> decltype(::sqlpp::join(*this, t))
|
||||||
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...>>
|
|
||||||
{
|
{
|
||||||
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
|
return ::sqlpp::join(*this, t);
|
||||||
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...}, {}}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename 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 ::sqlpp::inner_join(*this, t);
|
||||||
return {*this, t, {}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename 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 ::sqlpp::left_outer_join(*this, t);
|
||||||
return {*this, t, {}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename 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 ::sqlpp::right_outer_join(*this, t);
|
||||||
return {*this, t, {}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename 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 ::sqlpp::outer_join(*this, t);
|
||||||
return {*this, t, {}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename 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 ::sqlpp::cross_join(*this, t);
|
||||||
return {*this, t, {}};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Lhs _lhs;
|
PreJoin _pre_join;
|
||||||
Rhs _rhs;
|
|
||||||
On _on;
|
On _on;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context, typename JoinType, typename Lhs, typename Rhs, typename On>
|
template <typename Context, typename PreJoin, typename On>
|
||||||
struct serializer_t<Context, join_t<JoinType, Lhs, Rhs, On>>
|
struct serializer_t<Context, join_t<PreJoin, On>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Lhs, Rhs, On>;
|
using _serialize_check = serialize_check_of<Context, PreJoin, On>;
|
||||||
using T = join_t<JoinType, Lhs, Rhs, On>;
|
using T = join_t<PreJoin, On>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
static_assert(not is_noop<On>::value, "joined tables require on()");
|
serialize(t._pre_join, context);
|
||||||
serialize(t._lhs, context);
|
|
||||||
context << JoinType::_name;
|
|
||||||
context << " JOIN ";
|
|
||||||
serialize(t._rhs, context);
|
|
||||||
serialize(t._on, context);
|
serialize(t._on, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
73
include/sqlpp11/join_types.h
Normal file
73
include/sqlpp11/join_types.h
Normal 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
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -312,6 +312,18 @@ namespace sqlpp
|
|||||||
return context;
|
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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -328,6 +328,18 @@ namespace sqlpp
|
|||||||
return context;
|
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
|
#endif
|
||||||
|
@ -28,65 +28,63 @@
|
|||||||
#define SQLPP_ON_H
|
#define SQLPP_ON_H
|
||||||
|
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
#include <sqlpp11/interpret_tuple.h>
|
|
||||||
#include <sqlpp11/interpretable_list.h>
|
#include <sqlpp11/interpretable_list.h>
|
||||||
|
#include <sqlpp11/unconditional.h>
|
||||||
#include <sqlpp11/logic.h>
|
#include <sqlpp11/logic.h>
|
||||||
|
|
||||||
namespace sqlpp
|
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
|
struct on_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_on>;
|
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>;
|
Expression _expression;
|
||||||
|
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context, typename Database, typename... Expressions>
|
template <>
|
||||||
struct serializer_t<Context, on_t<Database, Expressions...>>
|
struct on_t<unconditional_t>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
using _traits = make_traits<no_value_t, tag::is_on>;
|
||||||
using T = on_t<Database, Expressions...>;
|
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)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
|
||||||
return context;
|
|
||||||
context << " ON ";
|
context << " ON ";
|
||||||
interpret_tuple(t._expressions, " AND ", context);
|
serialize(t._expression, context);
|
||||||
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
|
||||||
context << " AND ";
|
|
||||||
interpret_list(t._dynamic_expressions, " AND ", context);
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -38,13 +38,16 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, template <typename> class Pred>
|
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;
|
using type = void;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, template <typename> class Pred>
|
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 L,
|
||||||
template <typename> class LPred,
|
template <typename> class LPred,
|
||||||
@ -56,17 +59,17 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename L, template <typename> class LPred, typename R, template <typename> class RPred>
|
template <typename L, template <typename> class LPred, typename R, template <typename> class RPred>
|
||||||
struct binary_operand_check<L,
|
struct binary_operand_check<L, LPred, R, RPred, detail::enable_if_t<LPred<L>::value and RPred<R>::value>>
|
||||||
LPred,
|
|
||||||
R,
|
|
||||||
RPred,
|
|
||||||
detail::enable_if_t<LPred<wrap_operand_t<L>>::value and RPred<wrap_operand_t<R>>::value>>
|
|
||||||
{
|
{
|
||||||
using type = void;
|
using type = void;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename L, template <typename> class LPred, typename R, template <typename> class RPred>
|
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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -82,17 +82,11 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expression>
|
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)
|
void add(Expression expression)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "add() must not be called for static order_by");
|
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(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()");
|
"expression uses tables unknown to this statement in order_by::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, Expression>;
|
||||||
_serialize_check::_();
|
_serialize_check::_();
|
||||||
@ -274,6 +268,19 @@ namespace sqlpp
|
|||||||
return context;
|
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
|
#endif
|
||||||
|
@ -27,7 +27,9 @@
|
|||||||
#ifndef _sqlpp__ppgen__colops__auto_increment_h
|
#ifndef _sqlpp__ppgen__colops__auto_increment_h
|
||||||
#define _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_GET_TRAITS_LAZY_SQLPP_AUTO_INCREMENT \
|
||||||
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_AUTO_INCREMENT(...) ::sqlpp::tag::must_not_update
|
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
|
#endif // _sqlpp__ppgen__colops__auto_increment_h
|
||||||
|
@ -27,8 +27,9 @@
|
|||||||
#ifndef _sqlpp__ppgen__colops__primary_key_h
|
#ifndef _sqlpp__ppgen__colops__primary_key_h
|
||||||
#define _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(...) \
|
#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
|
#endif // _sqlpp__ppgen__colops__primary_key_h
|
||||||
|
210
include/sqlpp11/pre_join.h
Normal file
210
include/sqlpp11/pre_join.h
Normal 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
|
@ -34,7 +34,6 @@
|
|||||||
#include <sqlpp11/prepared_remove.h>
|
#include <sqlpp11/prepared_remove.h>
|
||||||
#include <sqlpp11/noop.h>
|
#include <sqlpp11/noop.h>
|
||||||
#include <sqlpp11/from.h>
|
#include <sqlpp11/from.h>
|
||||||
#include <sqlpp11/extra_tables.h>
|
|
||||||
#include <sqlpp11/using.h>
|
#include <sqlpp11/using.h>
|
||||||
#include <sqlpp11/where.h>
|
#include <sqlpp11/where.h>
|
||||||
|
|
||||||
@ -103,7 +102,7 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Database>
|
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>
|
inline auto remove() -> blank_remove_t<void>
|
||||||
{
|
{
|
||||||
|
@ -35,7 +35,6 @@
|
|||||||
#include <sqlpp11/select_flag_list.h>
|
#include <sqlpp11/select_flag_list.h>
|
||||||
#include <sqlpp11/select_column_list.h>
|
#include <sqlpp11/select_column_list.h>
|
||||||
#include <sqlpp11/from.h>
|
#include <sqlpp11/from.h>
|
||||||
#include <sqlpp11/extra_tables.h>
|
|
||||||
#include <sqlpp11/where.h>
|
#include <sqlpp11/where.h>
|
||||||
#include <sqlpp11/group_by.h>
|
#include <sqlpp11/group_by.h>
|
||||||
#include <sqlpp11/having.h>
|
#include <sqlpp11/having.h>
|
||||||
@ -77,7 +76,6 @@ namespace sqlpp
|
|||||||
no_select_flag_list_t,
|
no_select_flag_list_t,
|
||||||
no_select_column_list_t,
|
no_select_column_list_t,
|
||||||
no_from_t,
|
no_from_t,
|
||||||
no_extra_tables_t,
|
|
||||||
no_where_t<true>,
|
no_where_t<true>,
|
||||||
no_group_by_t,
|
no_group_by_t,
|
||||||
no_having_t,
|
no_having_t,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -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
|
// SELECTED COLUMNS DATA
|
||||||
template <typename Database, typename... Columns>
|
template <typename Database, typename... Columns>
|
||||||
struct select_column_list_data_t
|
struct select_column_list_data_t
|
||||||
@ -122,7 +91,7 @@ namespace sqlpp
|
|||||||
SQLPP_PORTABLE_STATIC_ASSERT(
|
SQLPP_PORTABLE_STATIC_ASSERT(
|
||||||
assert_no_unknown_tables_in_selected_columns_t,
|
assert_no_unknown_tables_in_selected_columns_t,
|
||||||
"at least one selected column requires a table which is otherwise not known in the statement");
|
"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");
|
"not all columns are made of aggregates, despite group_by or similar");
|
||||||
|
|
||||||
// SELECTED COLUMNS
|
// SELECTED COLUMNS
|
||||||
@ -154,19 +123,13 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename NamedExpression>
|
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)
|
void add(NamedExpression namedExpression)
|
||||||
{
|
{
|
||||||
using named_expression = auto_alias_t<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_dynamic::value, "selected_columns::add() can only be called for dynamic_column");
|
||||||
static_assert(is_selectable_t<named_expression>::value,
|
static_assert(is_selectable_t<named_expression>::value,
|
||||||
"invalid named expression argument in selected_columns::add()");
|
"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()");
|
"named expression uses tables unknown to this statement in selected_columns::add()");
|
||||||
using column_names = detail::make_type_set_t<typename Columns::_alias_t...>;
|
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,
|
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;
|
return t.selected_columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _column_check =
|
using _table_check = typename std::conditional<Policies::template _no_unknown_tables<select_column_list_t>::value,
|
||||||
typename std::conditional<Policies::template _no_unknown_tables<select_column_list_t>::value,
|
|
||||||
consistent_t,
|
consistent_t,
|
||||||
assert_no_unknown_tables_in_selected_columns_t>::type;
|
assert_no_unknown_tables_in_selected_columns_t>::type;
|
||||||
|
|
||||||
using _aggregate_check = typename std::conditional<Policies::template _no_unknown_aggregates<Columns...>::value,
|
using _aggregate_check = typename std::conditional<Policies::template _no_unknown_aggregates<Columns...>::value,
|
||||||
consistent_t,
|
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
|
// Result methods
|
||||||
@ -302,7 +264,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
size_t get_no_of_result_columns() const
|
size_t get_no_of_result_columns() const
|
||||||
{
|
{
|
||||||
return sizeof...(Columns) + get_dynamic_names().size();
|
return sizeof...(Columns) + _get_statement().get_selected_columns()._data._dynamic_columns.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
@ -484,6 +446,13 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
return statement_t<void, no_select_column_list_t>().columns(std::forward<T>(t)...);
|
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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -78,17 +78,11 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Flag>
|
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)
|
void add(Flag flag)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "select_flags::add() must not be called for static select flags");
|
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(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()");
|
"flag uses tables unknown to this statement in select_flags::add()");
|
||||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Flag>;
|
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Flag>;
|
||||||
_serialize_check::_();
|
_serialize_check::_();
|
||||||
@ -264,6 +258,19 @@ namespace sqlpp
|
|||||||
return context;
|
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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -36,6 +36,8 @@
|
|||||||
#include <sqlpp11/functions.h>
|
#include <sqlpp11/functions.h>
|
||||||
#include <sqlpp11/transaction.h>
|
#include <sqlpp11/transaction.h>
|
||||||
#include <sqlpp11/boolean_expression.h>
|
#include <sqlpp11/boolean_expression.h>
|
||||||
|
#include <sqlpp11/without_table_check.h>
|
||||||
#include <sqlpp11/schema_qualified_table.h>
|
#include <sqlpp11/schema_qualified_table.h>
|
||||||
|
#include <sqlpp11/custom_query.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -76,13 +76,10 @@ namespace sqlpp
|
|||||||
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
|
||||||
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
|
||||||
using _all_provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Policies>...>;
|
using _all_provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Policies>...>;
|
||||||
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 _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>
|
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
|
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2086629
|
||||||
// template <typename... Expressions>
|
// template <typename... Expressions>
|
||||||
@ -96,15 +93,15 @@ namespace sqlpp
|
|||||||
logic::all_t<detail::is_aggregate_expression_impl<_all_provided_aggregates,
|
logic::all_t<detail::is_aggregate_expression_impl<_all_provided_aggregates,
|
||||||
Expressions>::type::value...>::value>;
|
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>
|
template <template <typename> class Predicate>
|
||||||
using any_t = logic::any_t<Predicate<Policies>::value...>;
|
using any_t = logic::any_t<Predicate<Policies>::value...>;
|
||||||
|
|
||||||
// The tables not covered by the from.
|
// The tables not covered by the from.
|
||||||
using _required_tables =
|
using _required_tables = detail::make_difference_set_t<_all_required_tables, _all_provided_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_*()
|
|
||||||
>;
|
|
||||||
|
|
||||||
// The common table expressions not covered by the with.
|
// The common table expressions not covered by the with.
|
||||||
using _required_ctes = detail::make_difference_set_t<_all_required_ctes, _all_provided_ctes>;
|
using _required_ctes = detail::make_difference_set_t<_all_required_ctes, _all_provided_ctes>;
|
||||||
|
@ -62,33 +62,33 @@ namespace sqlpp
|
|||||||
using _alias_t = table_alias_t<AliasProvider, Table, ColumnSpec...>;
|
using _alias_t = table_alias_t<AliasProvider, Table, ColumnSpec...>;
|
||||||
|
|
||||||
template <typename T>
|
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>
|
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>
|
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>
|
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>
|
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>
|
template <typename AliasProvider>
|
||||||
@ -97,6 +97,12 @@ namespace sqlpp
|
|||||||
return {*static_cast<const Table*>(this)};
|
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
|
const Table& ref() const
|
||||||
{
|
{
|
||||||
return *static_cast<const Table*>(this);
|
return *static_cast<const Table*>(this);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -30,6 +30,7 @@
|
|||||||
#include <sqlpp11/column_fwd.h>
|
#include <sqlpp11/column_fwd.h>
|
||||||
#include <sqlpp11/interpret.h>
|
#include <sqlpp11/interpret.h>
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/join.h>
|
||||||
#include <sqlpp11/alias.h>
|
#include <sqlpp11/alias.h>
|
||||||
#include <sqlpp11/detail/type_set.h>
|
#include <sqlpp11/detail/type_set.h>
|
||||||
|
|
||||||
@ -41,7 +42,6 @@ namespace sqlpp
|
|||||||
template <typename AliasProvider, typename Table, typename... ColumnSpec>
|
template <typename AliasProvider, typename Table, typename... ColumnSpec>
|
||||||
struct table_alias_t : public ColumnSpec::_alias_t::template _member_t<column_t<AliasProvider, 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>,
|
using _traits = make_traits<value_type_of<Table>,
|
||||||
tag::is_table,
|
tag::is_table,
|
||||||
tag::is_alias,
|
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;
|
Table _table;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -56,6 +56,12 @@ namespace sqlpp
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
using value_type_of = typename detail::value_type_of_impl<T>::type;
|
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
|
// data types
|
||||||
struct boolean;
|
struct boolean;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -163,7 +169,10 @@ namespace sqlpp
|
|||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_return_value)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_table)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_table)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_raw_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_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_pseudo_table)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_column)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_column)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_select)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_select)
|
||||||
@ -172,7 +181,6 @@ namespace sqlpp
|
|||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_from)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_from)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_single_table)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_single_table)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_into)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_into)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_extra_tables)
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_on)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_on)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_where)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_where)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_group_by)
|
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(required_tables)
|
||||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_tables)
|
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_tables)
|
||||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_outer_tables)
|
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_outer_tables)
|
||||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(extra_tables)
|
|
||||||
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_aggregates)
|
SQLPP_RECURSIVE_TRAIT_SET_GENERATOR(provided_aggregates)
|
||||||
|
|
||||||
#define SQLPP_RECURSIVE_TRAIT_GENERATOR(trait) \
|
#define SQLPP_RECURSIVE_TRAIT_GENERATOR(trait) \
|
||||||
@ -373,6 +380,7 @@ namespace sqlpp
|
|||||||
using serialize_check_of =
|
using serialize_check_of =
|
||||||
detail::get_first_if<is_inconsistent_t, consistent_t, typename serializer_t<Context, T>::_serialize_check...>;
|
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,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_run_statement_or_prepared_t,
|
||||||
"connection cannot run something that is neither statement nor prepared statement");
|
"connection cannot run something that is neither statement nor prepared statement");
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_prepare_statement_t,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_prepare_statement_t,
|
||||||
@ -381,12 +389,11 @@ namespace sqlpp
|
|||||||
template <typename T, typename Enable = void>
|
template <typename T, typename Enable = void>
|
||||||
struct consistency_check
|
struct consistency_check
|
||||||
{
|
{
|
||||||
using type = assert_run_statement_or_prepared_t;
|
using type = assert_sqlpp_type_t;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct consistency_check<T,
|
struct consistency_check<T, detail::void_t<typename T::_consistency_check>>
|
||||||
typename std::enable_if<is_statement_t<T>::value or is_prepared_statement_t<T>::value>::type>
|
|
||||||
{
|
{
|
||||||
using type = typename T::_consistency_check;
|
using type = typename T::_consistency_check;
|
||||||
};
|
};
|
||||||
@ -495,6 +502,24 @@ namespace sqlpp
|
|||||||
|
|
||||||
template <typename Statement, template <typename> class Predicate>
|
template <typename Statement, template <typename> class Predicate>
|
||||||
using has_policy_t = typename has_policy_impl<Statement, Predicate>::type;
|
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
|
#endif
|
||||||
|
@ -24,32 +24,13 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SQLPP_OPERATORS_H
|
#ifndef SQLPP_UNCONDITIONAL_H
|
||||||
#define SQLPP_OPERATORS_H
|
#define SQLPP_UNCONDITIONAL_H
|
||||||
|
|
||||||
#include <sqlpp11/wrap_operand.h>
|
|
||||||
#include <sqlpp11/expression_return_types.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template <typename L, typename R>
|
struct unconditional_t
|
||||||
auto operator and(const L& l, const R& r) -> return_type_and_t<L, R>
|
|
||||||
{
|
{
|
||||||
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
|
#endif
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -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
|
#endif
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -78,12 +78,6 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Assignment>
|
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)
|
void add(Assignment assignment)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "add must not be called for static from()");
|
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,
|
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value,
|
||||||
"Must not assign value to column twice");
|
"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(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()");
|
"assignment uses tables unknown to this statement in add()");
|
||||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Assignment>;
|
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Assignment>;
|
||||||
_serialize_check::_();
|
_serialize_check::_();
|
||||||
|
43
include/sqlpp11/value.h
Normal file
43
include/sqlpp11/value.h
Normal 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
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -27,6 +27,7 @@
|
|||||||
#ifndef SQLPP_VERBATIM_TABLE_H
|
#ifndef SQLPP_VERBATIM_TABLE_H
|
||||||
#define SQLPP_VERBATIM_TABLE_H
|
#define SQLPP_VERBATIM_TABLE_H
|
||||||
|
|
||||||
|
#include <sqlpp11/table.h>
|
||||||
#include <sqlpp11/data_types/no_value.h>
|
#include <sqlpp11/data_types/no_value.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -29,19 +29,21 @@
|
|||||||
|
|
||||||
#include <sqlpp11/statement_fwd.h>
|
#include <sqlpp11/statement_fwd.h>
|
||||||
#include <sqlpp11/type_traits.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
#include <sqlpp11/value.h>
|
||||||
#include <sqlpp11/parameter_list.h>
|
#include <sqlpp11/parameter_list.h>
|
||||||
#include <sqlpp11/expression.h>
|
#include <sqlpp11/expression.h>
|
||||||
#include <sqlpp11/interpret_tuple.h>
|
#include <sqlpp11/interpret_tuple.h>
|
||||||
#include <sqlpp11/interpretable_list.h>
|
#include <sqlpp11/interpretable_list.h>
|
||||||
|
#include <sqlpp11/unconditional.h>
|
||||||
#include <sqlpp11/logic.h>
|
#include <sqlpp11/logic.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// WHERE DATA
|
// WHERE DATA
|
||||||
template <typename Database, typename... Expressions>
|
template <typename Database, typename Expression>
|
||||||
struct where_data_t
|
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& operator=(where_data_t&&) = default;
|
||||||
~where_data_t() = default;
|
~where_data_t() = default;
|
||||||
|
|
||||||
std::tuple<Expressions...> _expressions;
|
Expression _expression;
|
||||||
interpretable_list_t<Database> _dynamic_expressions;
|
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");
|
"at least one expression in where() requires a table which is otherwise not known in the statement");
|
||||||
|
|
||||||
// WHERE(EXPR)
|
// WHERE(EXPR)
|
||||||
template <typename Database, typename... Expressions>
|
template <typename Database, typename Expression>
|
||||||
struct where_t
|
struct where_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_where>;
|
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>;
|
using _is_dynamic = is_database<Database>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = where_data_t<Database, Expressions...>;
|
using _data_t = where_data_t<Database, Expression>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
@ -81,38 +83,33 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expression>
|
template <typename Expr>
|
||||||
void add_ntc(Expression expression)
|
void add(Expr expression)
|
||||||
{
|
|
||||||
add<Expression, std::false_type>(expression);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Expression, typename TableCheckRequired = std::true_type>
|
|
||||||
void add(Expression expression)
|
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "where::add() can only be called for dynamic_where");
|
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(is_expression_t<Expr>::value, "invalid expression argument in where::add()");
|
||||||
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value,
|
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()");
|
"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");
|
"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::_();
|
_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
|
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <typename Expression>
|
template <typename Expr>
|
||||||
void _add_impl(Expression expression, const std::true_type&)
|
void _add_impl(Expr expression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return _data._dynamic_expressions.emplace_back(expression);
|
return _data._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Expression>
|
template <typename Expr>
|
||||||
void _add_impl(Expression expression, const std::false_type&);
|
void _add_impl(Expr expression, const std::false_type&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
@ -122,7 +119,7 @@ namespace sqlpp
|
|||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
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
|
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
@ -154,20 +151,19 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct where_data_t<void, bool>
|
struct where_data_t<void, unconditional_t>
|
||||||
{
|
{
|
||||||
bool _condition;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// WHERE(BOOL)
|
// WHERE() UNCONDITIONALLY
|
||||||
template <>
|
template <>
|
||||||
struct where_t<void, bool>
|
struct where_t<void, unconditional_t>
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_where>;
|
using _traits = make_traits<no_value_t, tag::is_where>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = where_data_t<void, bool>;
|
using _data_t = where_data_t<void, unconditional_t>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
@ -186,7 +182,7 @@ namespace sqlpp
|
|||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
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
|
// workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269
|
||||||
template <typename... Args>
|
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,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_not_cpp_bool_t,
|
||||||
"at least one argument is not a boolean expression in where()");
|
"where() argument has to be an sqlpp boolean expression. Please use "
|
||||||
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_boolean_t, "at least one argument is not a boolean expression in where()");
|
".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,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_no_aggregate_functions_t,
|
||||||
"at least one aggregate function used in where()");
|
"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,
|
SQLPP_PORTABLE_STATIC_ASSERT(assert_where_dynamic_statement_dynamic_t,
|
||||||
"dynamic_where() must not be called in a static statement");
|
"dynamic_where() must not be called in a static statement");
|
||||||
|
|
||||||
@ -230,33 +227,33 @@ namespace sqlpp
|
|||||||
// https://connect.microsoft.com/VisualStudio/feedback/details/2173198
|
// https://connect.microsoft.com/VisualStudio/feedback/details/2173198
|
||||||
// template <typename... Expressions>
|
// template <typename... Expressions>
|
||||||
// using check_where_t = static_combined_check_t<
|
// 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_not_cpp_bool_t<Expressions>::value...>::value,
|
||||||
// static_check_t<logic::all_t<is_boolean_t<Expressions>::value...>::value, assert_where_boolean_t>,
|
// 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,
|
// static_check_t<logic::all_t<(not contains_aggregate_function_t<Expressions>::value)...>::value,
|
||||||
// assert_where_no_aggregate_functions_t>>;
|
// assert_where_no_aggregate_functions_t>>;
|
||||||
template <typename... Expressions>
|
template <typename Expression>
|
||||||
struct check_where
|
struct check_where
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<logic::all_t<detail::is_expression_impl<Expressions>::type::value...>::value,
|
static_check_t<is_not_cpp_bool_t<Expression>::value, assert_where_not_cpp_bool_t>,
|
||||||
assert_where_expressions_t>,
|
static_check_t<is_expression_t<Expression>::value, assert_where_boolean_expression_t>,
|
||||||
static_check_t<logic::all_t<is_boolean_t<Expressions>::value...>::value, assert_where_boolean_t>,
|
static_check_t<is_boolean_t<Expression>::value, assert_where_boolean_expression_t>,
|
||||||
static_check_t<logic::all_t<(not detail::contains_aggregate_function_impl<Expressions>::type::value)...>::value,
|
static_check_t<not contains_aggregate_function_t<Expression>::value, assert_where_no_aggregate_functions_t>>;
|
||||||
assert_where_no_aggregate_functions_t>>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... Expressions>
|
template <typename Expression>
|
||||||
using check_where_t = typename check_where<Expressions...>::type;
|
using check_where_t = typename check_where<Expression>::type;
|
||||||
|
|
||||||
template <typename... Expressions>
|
template <typename Expression>
|
||||||
using check_where_static_t =
|
using check_where_static_t = check_where_t<Expression>;
|
||||||
static_combined_check_t<check_where_t<Expressions...>,
|
|
||||||
static_check_t<sizeof...(Expressions) != 0, assert_where_static_count_args_t>>;
|
|
||||||
|
|
||||||
template <typename Database, typename... Expressions>
|
template <typename Database, typename Expression>
|
||||||
using check_where_dynamic_t = static_combined_check_t<
|
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>,
|
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
|
// NO WHERE YET
|
||||||
template <bool WhereRequired>
|
template <bool WhereRequired>
|
||||||
@ -312,14 +309,6 @@ namespace sqlpp
|
|||||||
|
|
||||||
using _database_t = typename Policies::_database_t;
|
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>
|
template <typename Check, typename T>
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_where_t, T>;
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_where_t, T>;
|
||||||
|
|
||||||
@ -328,59 +317,63 @@ namespace sqlpp
|
|||||||
assert_where_t,
|
assert_where_t,
|
||||||
consistent_t>::type;
|
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>
|
template <typename Expression>
|
||||||
auto where(Expressions... expressions) const
|
auto where(Expression expression) const
|
||||||
-> _new_statement_t<check_where_static_t<Expressions...>, where_t<void, Expressions...>>
|
-> _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{}._();
|
Check{}._();
|
||||||
|
|
||||||
return _where_impl<void>(Check{}, expressions...);
|
return _where_impl<void>(Check{}, expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... Expressions>
|
template <typename Expression>
|
||||||
auto dynamic_where(Expressions... expressions) const
|
auto dynamic_where(Expression expression) const
|
||||||
-> _new_statement_t<check_where_dynamic_t<_database_t, Expressions...>, where_t<_database_t, Expressions...>>
|
-> _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{}._();
|
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:
|
private:
|
||||||
template <typename Database, typename... Expressions>
|
template <typename Database, typename Expression>
|
||||||
auto _where_impl(const std::false_type&, Expressions... expressions) const -> bad_statement;
|
auto _where_impl(const std::false_type&, Expression expression) const -> bad_statement;
|
||||||
|
|
||||||
template <typename Database, typename... Expressions>
|
template <typename Database, typename Expression>
|
||||||
auto _where_impl(const std::true_type&, Expressions... expressions) const
|
auto _where_impl(const std::true_type&, Expression expression) const
|
||||||
-> _new_statement_t<std::true_type, where_t<Database, Expressions...>>
|
-> _new_statement_t<std::true_type, where_t<Database, Expression>>
|
||||||
{
|
{
|
||||||
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
||||||
where_data_t<Database, Expressions...>{expressions...}};
|
where_data_t<Database, Expression>{expression}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// Interpreters
|
// Interpreters
|
||||||
template <typename Context, typename Database, typename... Expressions>
|
template <typename Context, typename Database, typename Expression>
|
||||||
struct serializer_t<Context, where_data_t<Database, Expressions...>>
|
struct serializer_t<Context, where_data_t<Database, Expression>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
using _serialize_check = serialize_check_of<Context, Expression>;
|
||||||
using T = where_data_t<Database, Expressions...>;
|
using T = where_data_t<Database, Expression>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
|
||||||
return context;
|
|
||||||
context << " WHERE ";
|
context << " WHERE ";
|
||||||
interpret_tuple(t._expressions, " AND ", context);
|
serialize(t._expression, context);
|
||||||
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
if (not t._dynamic_expressions.empty())
|
||||||
context << " AND ";
|
context << " AND ";
|
||||||
interpret_list(t._dynamic_expressions, " AND ", context);
|
interpret_list(t._dynamic_expressions, " AND ", context);
|
||||||
return context;
|
return context;
|
||||||
@ -388,23 +381,33 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Context>
|
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 _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;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename... T>
|
template <typename T>
|
||||||
auto where(T&&... t) -> decltype(statement_t<void, no_where_t<false>>().where(std::forward<T>(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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
67
include/sqlpp11/without_table_check.h
Normal file
67
include/sqlpp11/without_table_check.h
Normal 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
|
@ -36,7 +36,7 @@ int main()
|
|||||||
static_assert(sqlpp::can_be_null_t<decltype(t.alpha)>::value, "t.alpha can be null");
|
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");
|
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(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,
|
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,
|
||||||
|
41
test_serializer/CMakeLists.txt
Normal file
41
test_serializer/CMakeLists.txt
Normal 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()
|
||||||
|
|
63
test_serializer/CustomQuery.cpp
Normal file
63
test_serializer/CustomQuery.cpp
Normal 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
130
test_serializer/From.cpp
Normal 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
64
test_serializer/In.cpp
Normal 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
67
test_serializer/Where.cpp
Normal 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
50
test_serializer/compare.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2015, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_TEST_SERIALIZER_H
|
||||||
|
#define SQLPP_TEST_SERIALIZER_H
|
||||||
|
|
||||||
|
#include "MockDb.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <typename Expression>
|
||||||
|
void compare(int lineNo, const Expression& expr, const std::string& expected)
|
||||||
|
{
|
||||||
|
MockDb::_serializer_context_t printer = {};
|
||||||
|
|
||||||
|
const auto result = serialize(expr, printer).str();
|
||||||
|
|
||||||
|
if (result != expected)
|
||||||
|
{
|
||||||
|
std::cerr << __FILE__ << " " << lineNo << '\n' << "Expected: -->|" << expected << "|<--\n"
|
||||||
|
<< "Received: -->|" << result << "|<--\n";
|
||||||
|
throw std::runtime_error("unexpected serialization result");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -142,6 +142,28 @@ namespace test
|
|||||||
};
|
};
|
||||||
using _traits = sqlpp::make_traits<sqlpp::time_point, sqlpp::tag::can_be_null>;
|
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 OtherInt
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
@ -261,6 +283,7 @@ namespace test
|
|||||||
TabAllTypes_::SomeBool,
|
TabAllTypes_::SomeBool,
|
||||||
TabAllTypes_::SomeDayPoint,
|
TabAllTypes_::SomeDayPoint,
|
||||||
TabAllTypes_::SomeTimePoint,
|
TabAllTypes_::SomeTimePoint,
|
||||||
|
TabAllTypes_::OtherString,
|
||||||
TabAllTypes_::OtherInt,
|
TabAllTypes_::OtherInt,
|
||||||
TabAllTypes_::OtherFloat,
|
TabAllTypes_::OtherFloat,
|
||||||
TabAllTypes_::OtherBool,
|
TabAllTypes_::OtherBool,
|
||||||
|
@ -23,15 +23,22 @@
|
|||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
function(test_compile name)
|
function(test_compile name)
|
||||||
set(target sqlpp11_${name})
|
set(target sqlpp11_assert_${name})
|
||||||
add_executable(${target} ${name}.cpp)
|
add_executable(${target} ${name}.cpp)
|
||||||
target_link_libraries(${target} PRIVATE sqlpp11 sqlpp11_testing)
|
target_link_libraries(${target} PRIVATE sqlpp11 sqlpp11_testing)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
test_compile(aggregates)
|
test_compile(aggregates)
|
||||||
test_compile(case)
|
test_compile(case)
|
||||||
|
test_compile(from)
|
||||||
|
test_compile(join)
|
||||||
test_compile(where)
|
test_compile(where)
|
||||||
|
test_compile(having)
|
||||||
test_compile(insert)
|
test_compile(insert)
|
||||||
|
test_compile(in)
|
||||||
test_compile(date)
|
test_compile(date)
|
||||||
test_compile(date_time)
|
test_compile(date_time)
|
||||||
|
test_compile(text)
|
||||||
|
test_compile(no_self_compare)
|
||||||
|
test_compile(unwrapped_bool)
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2015, Roland Bock
|
* Copyright (c) 2015-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -75,51 +75,53 @@ namespace
|
|||||||
// If there is no group_by, we can select whatever we want
|
// If there is no group_by, we can select whatever we want
|
||||||
void no_group_by()
|
void no_group_by()
|
||||||
{
|
{
|
||||||
run_check(select(all_of(t)).from(t).where(true));
|
run_check(select(all_of(t)).from(t).unconditionally());
|
||||||
run_check(select(t.alpha).from(t).where(true));
|
run_check(select(t.alpha).from(t).unconditionally());
|
||||||
run_check(select(count(t.alpha)).from(t).where(true));
|
run_check(select(count(t.alpha)).from(t).unconditionally());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is a dynamic group_by, we can still select whatever we want
|
// 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
|
// because there is no way of knowing which expressions might have been added dynamically
|
||||||
void dynamic_group_by()
|
void dynamic_group_by()
|
||||||
{
|
{
|
||||||
run_check(select(all_of(t)).from(t).where(true));
|
run_check(select(all_of(t)).from(t).unconditionally());
|
||||||
run_check(select(t.alpha).from(t).where(true));
|
run_check(select(t.alpha).from(t).unconditionally());
|
||||||
run_check(select(count(t.alpha)).from(t).where(true));
|
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.
|
// 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
|
// count(t.id)) or values to be valid
|
||||||
void static_group_by_ok()
|
void static_group_by_ok()
|
||||||
{
|
{
|
||||||
run_check(select(t.alpha).from(t).where(true).group_by(t.alpha));
|
run_check(select(t.alpha).from(t).unconditionally().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).unconditionally().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 + 42).as(whatever)).from(t).unconditionally().group_by(t.alpha, t.alpha + t.delta * 17));
|
||||||
run_check(
|
run_check(select((t.alpha + t.delta * 17).as(whatever))
|
||||||
select((t.alpha + t.delta * 17).as(whatever)).from(t).where(true).group_by(t.alpha, t.alpha + t.delta * 17));
|
.from(t)
|
||||||
run_check(select((t.beta + "fortytwo").as(whatever)).from(t).where(true).group_by(t.beta));
|
.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(avg(t.alpha)).from(t).unconditionally().group_by(t.beta));
|
||||||
run_check(select(count(t.alpha)).from(t).where(true).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).where(true).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).where(true).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).where(true).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(1).as(whatever)).from(t).unconditionally().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("whatever").as(whatever)).from(t).unconditionally().group_by(t.alpha));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failures with static group_by and selected non-aggregates or incorrect aggregates
|
// Failures with static group_by and selected non-aggregates or incorrect aggregates
|
||||||
void static_group_by_nok()
|
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_no_unknown_aggregates_t>(select(t.beta).from(t).unconditionally().group_by(t.alpha));
|
||||||
run_check<sqlpp::assert_aggregates_t>(
|
run_check<sqlpp::assert_no_unknown_aggregates_t>(
|
||||||
select((t.alpha + t.delta).as(whatever)).from(t).where(true).group_by(t.alpha));
|
select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha));
|
||||||
run_check<sqlpp::assert_aggregates_t>(
|
run_check<sqlpp::assert_no_unknown_aggregates_t>(
|
||||||
select((t.alpha + t.delta).as(whatever)).from(t).where(true).group_by(t.alpha, t.alpha + t.delta * 17));
|
select((t.alpha + t.delta).as(whatever)).from(t).unconditionally().group_by(t.alpha, t.alpha + t.delta * 17));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr auto t = test::TabBar{};
|
constexpr auto t = test::TabBar{};
|
||||||
constexpr auto f = test::TabFoo{};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void print_type_on_error(std::true_type)
|
void print_type_on_error(std::true_type)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2015, Roland Bock
|
* Copyright (c) 2015-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -46,7 +46,7 @@ namespace
|
|||||||
template <typename Assert, typename Operand>
|
template <typename Assert, typename Operand>
|
||||||
void static_check_comparison(const Operand& 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>;
|
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
|
||||||
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
||||||
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
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 != operand), decltype(t.someDayPoint >= operand), decltype(t.someDayPoint > operand),
|
||||||
decltype(t.someDayPoint.in(operand)), decltype(t.someDayPoint.in(operand, 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))>;
|
decltype(t.someDayPoint.not_in(operand)), decltype(t.someDayPoint.not_in(operand, operand))>;
|
||||||
using ExpectedReturnType =
|
using ExpectedReturnType = sqlpp::logic::all_t<
|
||||||
sqlpp::logic::all_t<Assert::value xor
|
Assert::value xor
|
||||||
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_statement>>::value>;
|
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_expression<sqlpp::boolean>>>::value>;
|
||||||
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
||||||
print_type_on_error<ReturnType>(ExpectedReturnType{});
|
print_type_on_error<ReturnType>(ExpectedReturnType{});
|
||||||
}
|
}
|
||||||
@ -66,20 +66,21 @@ namespace
|
|||||||
void allowed_comparands()
|
void allowed_comparands()
|
||||||
{
|
{
|
||||||
static_check_comparison<sqlpp::consistent_t>(std::chrono::system_clock::now());
|
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.someTimePoint);
|
||||||
|
static_check_comparison<sqlpp::consistent_t>(t.otherTimePoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disallowed_comparands()
|
void disallowed_comparands()
|
||||||
{
|
{
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(17);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(17);
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>('a');
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>('a');
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(std::string("a"));
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(std::string("a"));
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_expression_t>(t);
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someBool);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someBool);
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someFloat);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someFloat);
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someInt);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_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>(t.someString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2015, Roland Bock
|
* Copyright (c) 2015-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -46,7 +46,7 @@ namespace
|
|||||||
template <typename Assert, typename Operand>
|
template <typename Assert, typename Operand>
|
||||||
void static_check_comparison(const Operand& 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>;
|
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
|
||||||
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
||||||
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
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 != operand), decltype(t.someTimePoint >= operand), decltype(t.someTimePoint > operand),
|
||||||
decltype(t.someTimePoint.in(operand)), decltype(t.someTimePoint.in(operand, 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))>;
|
decltype(t.someTimePoint.not_in(operand)), decltype(t.someTimePoint.not_in(operand, operand))>;
|
||||||
using ExpectedReturnType =
|
using ExpectedReturnType = sqlpp::logic::all_t<
|
||||||
sqlpp::logic::all_t<Assert::value xor
|
Assert::value xor
|
||||||
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_statement>>::value>;
|
std::is_same<ReturnType, sqlpp::detail::type_set<sqlpp::bad_expression<sqlpp::boolean>>>::value>;
|
||||||
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
||||||
print_type_on_error<ReturnType>(ExpectedReturnType{});
|
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>(std::chrono::system_clock::now());
|
||||||
static_check_comparison<sqlpp::consistent_t>(t.someDayPoint);
|
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()
|
void disallowed_comparands()
|
||||||
{
|
{
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(17);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(17);
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>('a');
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>('a');
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(std::string("a"));
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(std::string("a"));
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_expression_t>(t);
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someBool);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someBool);
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someFloat);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_operand_t>(t.someFloat);
|
||||||
static_check_comparison<sqlpp::assert_valid_rhs_comparison_operand_t>(t.someInt);
|
static_check_comparison<sqlpp::assert_comparison_rhs_is_valid_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>(t.someString);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
172
test_static_asserts/from.cpp
Normal file
172
test_static_asserts/from.cpp
Normal 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();
|
||||||
|
}
|
194
test_static_asserts/having.cpp
Normal file
194
test_static_asserts/having.cpp
Normal 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();
|
||||||
|
}
|
88
test_static_asserts/in.cpp
Normal file
88
test_static_asserts/in.cpp
Normal 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();
|
||||||
|
}
|
285
test_static_asserts/join.cpp
Normal file
285
test_static_asserts/join.cpp
Normal 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();
|
||||||
|
}
|
85
test_static_asserts/no_self_compare.cpp
Normal file
85
test_static_asserts/no_self_compare.cpp
Normal 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();
|
||||||
|
}
|
113
test_static_asserts/text.cpp
Normal file
113
test_static_asserts/text.cpp
Normal 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();
|
||||||
|
}
|
115
test_static_asserts/unwrapped_bool.cpp
Normal file
115
test_static_asserts/unwrapped_bool.cpp
Normal 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();
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015-2015, Roland Bock
|
* Copyright (c) 2015-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -31,7 +31,6 @@
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr auto t = test::TabBar{};
|
constexpr auto t = test::TabBar{};
|
||||||
constexpr auto f = test::TabFoo{};
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void print_type_on_error(std::true_type)
|
void print_type_on_error(std::true_type)
|
||||||
@ -44,31 +43,31 @@ namespace
|
|||||||
T::_print_me_;
|
T::_print_me_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Assert, typename... Expressions>
|
template <typename Assert, typename Expression>
|
||||||
void where_static_check(const Expressions&... expressions)
|
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>;
|
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
|
||||||
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
||||||
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
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 =
|
using ExpectedReturnType =
|
||||||
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
|
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
|
||||||
print_type_on_error<ReturnType>(ExpectedReturnType{});
|
print_type_on_error<ReturnType>(ExpectedReturnType{});
|
||||||
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
static_assert(ExpectedReturnType::value, "Unexpected return type");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Assert, typename... Expressions>
|
template <typename Assert, typename Expression>
|
||||||
void where_dynamic_check(const Expressions&... expressions)
|
void where_dynamic_check(const Expression& expression)
|
||||||
{
|
{
|
||||||
static auto db = MockDb{};
|
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>;
|
using ExpectedCheckResult = std::is_same<CheckResult, Assert>;
|
||||||
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
||||||
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
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 =
|
using ExpectedReturnType =
|
||||||
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
|
sqlpp::logic::all_t<Assert::value xor std::is_same<ReturnType, sqlpp::bad_statement>::value>;
|
||||||
print_type_on_error<ReturnType>(ExpectedReturnType{});
|
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);
|
||||||
where_static_check<sqlpp::consistent_t>(t.gamma == true);
|
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
|
// 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
|
// 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
|
// Try some other types as expressions
|
||||||
where_static_check<sqlpp::assert_where_expressions_t>("true");
|
where_static_check<sqlpp::assert_where_boolean_expression_t>("true");
|
||||||
where_static_check<sqlpp::assert_where_expressions_t>(17);
|
where_static_check<sqlpp::assert_where_boolean_expression_t>(17);
|
||||||
where_static_check<sqlpp::assert_where_expressions_t>('c');
|
where_static_check<sqlpp::assert_where_boolean_expression_t>('c');
|
||||||
where_static_check<sqlpp::assert_where_expressions_t>(nullptr);
|
where_static_check<sqlpp::assert_where_boolean_expression_t>(nullptr);
|
||||||
where_static_check<sqlpp::assert_where_expressions_t>(t.alpha.as(t.beta));
|
where_static_check<sqlpp::assert_where_boolean_expression_t>(t.alpha.as(t.beta));
|
||||||
|
|
||||||
// Try using aggregate functions in where
|
// Try using aggregate functions in where
|
||||||
where_static_check<sqlpp::assert_where_no_aggregate_functions_t>(count(t.alpha) > 0);
|
where_static_check<sqlpp::assert_where_no_aggregate_functions_t>(count(t.alpha) > 0);
|
||||||
@ -107,22 +107,25 @@ namespace
|
|||||||
void dynamic_where()
|
void dynamic_where()
|
||||||
{
|
{
|
||||||
// OK
|
// OK
|
||||||
where_dynamic_check<sqlpp::consistent_t>();
|
|
||||||
where_dynamic_check<sqlpp::consistent_t>(t.gamma);
|
where_dynamic_check<sqlpp::consistent_t>(t.gamma);
|
||||||
where_dynamic_check<sqlpp::consistent_t>(t.gamma == true);
|
where_dynamic_check<sqlpp::consistent_t>(t.gamma == true);
|
||||||
|
|
||||||
// Try assignment as condition
|
// 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
|
// 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
|
// Try some other types as expressions
|
||||||
where_dynamic_check<sqlpp::assert_where_expressions_t>("true");
|
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>("true");
|
||||||
where_dynamic_check<sqlpp::assert_where_expressions_t>(17);
|
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>(17);
|
||||||
where_dynamic_check<sqlpp::assert_where_expressions_t>('c');
|
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>('c');
|
||||||
where_dynamic_check<sqlpp::assert_where_expressions_t>(nullptr);
|
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>(nullptr);
|
||||||
where_dynamic_check<sqlpp::assert_where_expressions_t>(t.alpha.as(t.beta));
|
where_dynamic_check<sqlpp::assert_where_boolean_expression_t>(t.alpha.as(t.beta));
|
||||||
|
|
||||||
// Try using aggregate functions in where
|
// Try using aggregate functions in where
|
||||||
where_dynamic_check<sqlpp::assert_where_no_aggregate_functions_t>(count(t.alpha) > 0);
|
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));
|
case_when(count(t.alpha) > 0).then(t.gamma).else_(not t.gamma));
|
||||||
|
|
||||||
// Try dynamic_where on a non-dynamic remove
|
// 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>;
|
using ExpectedCheckResult = std::is_same<CheckResult, sqlpp::assert_where_dynamic_statement_dynamic_t>;
|
||||||
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
print_type_on_error<CheckResult>(ExpectedCheckResult{});
|
||||||
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
static_assert(ExpectedCheckResult::value, "Unexpected check result");
|
||||||
|
32
test_types/CMakeLists.txt
Normal file
32
test_types/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
# Copyright (c) 2016-2016, Roland Bock
|
||||||
|
# All rights reserved.
|
||||||
|
#
|
||||||
|
# Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
# are permitted provided that the following conditions are met:
|
||||||
|
#
|
||||||
|
# Redistributions of source code must retain the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
# list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
# other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
function(test_compile name)
|
||||||
|
set(target sqlpp11_${name})
|
||||||
|
add_executable(${target} ${name}.cpp)
|
||||||
|
target_link_libraries(${target} PRIVATE sqlpp11 sqlpp11_testing)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
test_compile(result_row)
|
||||||
|
|
212
test_types/result_row.cpp
Normal file
212
test_types/result_row.cpp
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2016, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||||
|
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||||
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MockDb.h"
|
||||||
|
#include "Sample.h"
|
||||||
|
#include <sqlpp11/sqlpp11.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr auto bar = test::TabBar{};
|
||||||
|
constexpr auto foo = test::TabFoo{};
|
||||||
|
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(bar.alpha)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(foo.omega)>::value, "");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(foo.delta)>::value, "");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(bar.gamma)>::value, "");
|
||||||
|
const auto seven = sqlpp::value(7).as(sqlpp::alias::s);
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(seven)>::value, "");
|
||||||
|
|
||||||
|
auto db = MockDb{};
|
||||||
|
|
||||||
|
void single_table()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// result fields are as nullable as the expressions they represent
|
||||||
|
const auto& x = db(select(bar.alpha, bar.gamma, seven).from(bar).unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void join()
|
||||||
|
{
|
||||||
|
// Join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of (inner) join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of (inner) join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of (inner) join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of (inner) join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inner join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.inner_join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of inner join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of inner join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.inner_join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of inner join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of inner join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Left outer join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.left_outer_join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of left outer join cannot be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of left outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.left_outer_join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of left outer join cannot be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of left outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right outer join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.right_outer_join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of right outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value,
|
||||||
|
"right side of right outer join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.right_outer_join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of right outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value,
|
||||||
|
"right side of right outer join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outer join
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(foo.outer_join(bar).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of outer join can be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x = db(select(bar.alpha, foo.delta, bar.gamma, seven)
|
||||||
|
.from(bar.outer_join(foo).on(foo.omega > bar.alpha))
|
||||||
|
.unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of outer join can be null");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of outer join can be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cross join
|
||||||
|
{
|
||||||
|
const auto& x =
|
||||||
|
db(select(bar.alpha, foo.delta, bar.gamma, seven).from(foo.cross_join(bar)).unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "left side of cross join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "right side of cross join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto& x =
|
||||||
|
db(select(bar.alpha, foo.delta, bar.gamma, seven).from(bar.cross_join(foo)).unconditionally()).front();
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.alpha)>::value, "nullable value can always be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.gamma)>::value, "left side of cross join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.delta)>::value, "right side of cross join cannot be null");
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.s)>::value, "constant non-null value can not be null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void aggregates()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
// aggregates of nullable values
|
||||||
|
const auto a = bar.alpha;
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(bar.alpha)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(a)>::value, "");
|
||||||
|
const auto& x = db(select(count(a), avg(a), max(a), min(a), sum(a)).from(bar).unconditionally()).front();
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.count)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.avg)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.sum)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.max)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.min)>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// aggregates of nullable values
|
||||||
|
const auto o = foo.omega;
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(foo.omega)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(o)>::value, "");
|
||||||
|
const auto& x = db(select(count(o), avg(o), max(o), min(o), sum(o)).from(foo).unconditionally()).front();
|
||||||
|
static_assert(not sqlpp::can_be_null_t<decltype(x.count)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.avg)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.sum)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.max)>::value, "");
|
||||||
|
static_assert(sqlpp::can_be_null_t<decltype(x.min)>::value, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int, char* [])
|
||||||
|
{
|
||||||
|
single_table();
|
||||||
|
join();
|
||||||
|
aggregates();
|
||||||
|
}
|
@ -57,6 +57,10 @@ int CustomQuery(int, char* [])
|
|||||||
std::cerr << row.alpha << std::endl;
|
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
|
// 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.
|
// 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();
|
printer.reset();
|
||||||
|
@ -30,6 +30,13 @@
|
|||||||
|
|
||||||
SQLPP_ALIAS_PROVIDER(now)
|
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* [])
|
int DateTime(int, char* [])
|
||||||
{
|
{
|
||||||
MockDb db = {};
|
MockDb db = {};
|
||||||
@ -40,7 +47,7 @@ int DateTime(int, char* [])
|
|||||||
{
|
{
|
||||||
std::cout << row.now;
|
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.colDayPoint;
|
||||||
std::cout << row.colTimePoint;
|
std::cout << row.colTimePoint;
|
||||||
@ -48,23 +55,23 @@ int DateTime(int, char* [])
|
|||||||
printer.reset();
|
printer.reset();
|
||||||
std::cerr << serialize(::sqlpp::value(std::chrono::system_clock::now()), printer).str() << std::endl;
|
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.colDayPoint = 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.colTimePoint = floor<::sqlpp::chrono::days>(std::chrono::system_clock::now())));
|
||||||
db(insert_into(t).set(t.colTimePoint = std::chrono::system_clock::now()));
|
db(insert_into(t).set(t.colTimePoint = std::chrono::system_clock::now()));
|
||||||
|
|
||||||
db(update(t)
|
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()));
|
.where(t.colDayPoint < std::chrono::system_clock::now()));
|
||||||
db(update(t)
|
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()));
|
.where(t.colDayPoint < std::chrono::system_clock::now()));
|
||||||
db(update(t)
|
db(update(t)
|
||||||
.set(t.colTimePoint = std::chrono::system_clock::now())
|
.set(t.colTimePoint = std::chrono::system_clock::now())
|
||||||
.where(t.colDayPoint < 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.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()));
|
db(remove_from(t).where(t.colTimePoint == std::chrono::system_clock::now()));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -197,7 +197,7 @@ int Function(int, char* [])
|
|||||||
static_assert(not sqlpp::is_numeric_t<TT>::value, "type requirement");
|
static_assert(not sqlpp::is_numeric_t<TT>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_text_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 */
|
{ /* do something */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -286,7 +286,7 @@ int Function(int, char* [])
|
|||||||
static_assert(sqlpp::is_integral_t<TT>::value, "type requirement");
|
static_assert(sqlpp::is_integral_t<TT>::value, "type requirement");
|
||||||
static_assert(not sqlpp::is_floating_point_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 */
|
{ /* 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,
|
static_assert(std::is_same<decltype(sqlpp::tvin("test")), sqlpp::tvin_arg_t<sqlpp::text_operand>>::value,
|
||||||
"text values are accepted and wrapped");
|
"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)),
|
static_assert(std::is_same<decltype(sqlpp::tvin(row.alpha)),
|
||||||
sqlpp::tvin_arg_t<typename std::remove_const<decltype(row.alpha)>::type>>::value,
|
sqlpp::tvin_arg_t<typename std::remove_const<decltype(row.alpha)>::type>>::value,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -163,13 +163,11 @@ int Interpret(int, char* [])
|
|||||||
serialize(s, printer).str();
|
serialize(s, printer).str();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
auto s = dynamic_select(db)
|
// Behold, dynamically constructed queries might compile but be illegal SQL
|
||||||
.dynamic_flags(sqlpp::distinct)
|
auto s = dynamic_select(db).dynamic_flags(sqlpp::distinct).dynamic_columns(t.alpha);
|
||||||
.dynamic_columns(t.alpha)
|
|
||||||
.extra_tables(t); // Would fail to run()
|
|
||||||
s.select_flags.add(sqlpp::all);
|
s.select_flags.add(sqlpp::all);
|
||||||
s.selected_columns.add(t.beta);
|
s.selected_columns.add(without_table_check(t.beta));
|
||||||
s.selected_columns.add(t.gamma);
|
s.selected_columns.add(without_table_check(t.gamma));
|
||||||
serialize(s, printer).str();
|
serialize(s, printer).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,10 +176,9 @@ int Interpret(int, char* [])
|
|||||||
serialize(avg(sqlpp::distinct, t.alpha - 7), printer).str();
|
serialize(avg(sqlpp::distinct, t.alpha - 7), printer).str();
|
||||||
serialize(sum(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).unconditionally(), printer).str();
|
||||||
serialize(select(all_of(t)).from(t).where(false), 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.alpha, printer);
|
||||||
serialize(row.beta, printer);
|
serialize(row.beta, printer);
|
||||||
@ -201,8 +198,8 @@ int Interpret(int, char* [])
|
|||||||
std::cerr << serialize(x, printer).str() << std::endl;
|
std::cerr << serialize(x, printer).str() << std::endl;
|
||||||
|
|
||||||
printer.reset();
|
printer.reset();
|
||||||
std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in(select(f.epsilon).from(f).where(true))), printer)
|
std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in(select(f.epsilon).from(f).unconditionally())),
|
||||||
.str() << std::endl;
|
printer).str() << std::endl;
|
||||||
|
|
||||||
printer.reset();
|
printer.reset();
|
||||||
std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in()), printer).str() << std::endl;
|
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);
|
auto s = schema_qualified_table(schema, t).as(sqlpp::alias::x);
|
||||||
|
|
||||||
printer.reset();
|
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();
|
printer.reset();
|
||||||
std::cerr << serialize(sqlpp::case_when(true).then(t.alpha).else_(t.alpha + 1).as(t.beta), printer).str()
|
std::cerr << serialize(sqlpp::case_when(true).then(t.alpha).else_(t.alpha + 1).as(t.beta), printer).str()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -60,7 +60,7 @@ int Remove(int, char* [])
|
|||||||
printer.reset();
|
printer.reset();
|
||||||
std::cerr << serialize(r, printer).str() << std::endl;
|
std::cerr << serialize(r, printer).str() << std::endl;
|
||||||
printer.reset();
|
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);
|
db(r);
|
||||||
|
|
||||||
|
@ -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");
|
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
|
// 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::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");
|
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);
|
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::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");
|
static_assert(sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha interprets null_is_trivial");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using a non-enforcing db
|
// 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(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,
|
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);
|
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(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,
|
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value,
|
||||||
|
@ -29,7 +29,7 @@ namespace test
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
|
using _traits = sqlpp::make_traits<sqlpp::varchar>;
|
||||||
};
|
};
|
||||||
struct Epsilon
|
struct Epsilon
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -31,11 +31,12 @@
|
|||||||
#include <sqlpp11/select.h>
|
#include <sqlpp11/select.h>
|
||||||
#include <sqlpp11/functions.h>
|
#include <sqlpp11/functions.h>
|
||||||
#include <sqlpp11/connection.h>
|
#include <sqlpp11/connection.h>
|
||||||
|
#include <sqlpp11/without_table_check.h>
|
||||||
|
|
||||||
template <typename Db, typename Column>
|
template <typename Db, typename Column>
|
||||||
int64_t getColumn(Db&& db, const Column& 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())
|
if (not result.empty())
|
||||||
return result.front().a;
|
return result.front().a;
|
||||||
else
|
else
|
||||||
@ -59,14 +60,14 @@ int Select(int, char* [])
|
|||||||
std::cout << row.a << std::endl;
|
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;
|
int64_t a = row.alpha;
|
||||||
const std::string b = row.beta;
|
const std::string b = row.beta;
|
||||||
std::cout << a << ", " << b << std::endl;
|
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;
|
int64_t a = row.tabBar.alpha;
|
||||||
const std::string b = row.tabBar.beta;
|
const std::string b = row.tabBar.beta;
|
||||||
@ -82,19 +83,19 @@ int Select(int, char* [])
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& row :
|
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;
|
std::cout << row.alpha << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& row : db(select(all_of(t), all_of(f))
|
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))
|
.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;
|
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;
|
std::cout << row.count << std::endl;
|
||||||
}
|
}
|
||||||
@ -108,7 +109,6 @@ int Select(int, char* [])
|
|||||||
.columns(all_of(t))
|
.columns(all_of(t))
|
||||||
.flags(sqlpp::all)
|
.flags(sqlpp::all)
|
||||||
.from(t)
|
.from(t)
|
||||||
.extra_tables(f, t)
|
|
||||||
.where(t.alpha > 0)
|
.where(t.alpha > 0)
|
||||||
.group_by(t.alpha)
|
.group_by(t.alpha)
|
||||||
.order_by(t.gamma.asc())
|
.order_by(t.gamma.asc())
|
||||||
@ -122,7 +122,6 @@ int Select(int, char* [])
|
|||||||
.columns(all_of(t))
|
.columns(all_of(t))
|
||||||
.flags(sqlpp::all)
|
.flags(sqlpp::all)
|
||||||
.from(t)
|
.from(t)
|
||||||
.extra_tables(f, t)
|
|
||||||
.where(t.alpha > 0)
|
.where(t.alpha > 0)
|
||||||
.group_by(t.alpha)
|
.group_by(t.alpha)
|
||||||
.order_by(t.gamma.asc())
|
.order_by(t.gamma.asc())
|
||||||
@ -137,16 +136,15 @@ int Select(int, char* [])
|
|||||||
.dynamic_columns(all_of(t))
|
.dynamic_columns(all_of(t))
|
||||||
.dynamic_flags()
|
.dynamic_flags()
|
||||||
.dynamic_from(t)
|
.dynamic_from(t)
|
||||||
.extra_tables(f, t)
|
|
||||||
.dynamic_where()
|
.dynamic_where()
|
||||||
.dynamic_group_by(t.alpha)
|
.dynamic_group_by(t.alpha)
|
||||||
.dynamic_order_by()
|
.dynamic_order_by()
|
||||||
.dynamic_having(t.gamma)
|
.dynamic_having(sum(t.alpha) > 17)
|
||||||
.dynamic_limit()
|
.dynamic_limit()
|
||||||
.dynamic_offset();
|
.dynamic_offset();
|
||||||
s.select_flags.add(sqlpp::distinct);
|
s.select_flags.add(sqlpp::distinct);
|
||||||
s.selected_columns.add(f.omega);
|
s.selected_columns.add(without_table_check(f.omega));
|
||||||
s.from.add(f);
|
s.from.add(dynamic_cross_join(f));
|
||||||
s.where.add(t.alpha > 7);
|
s.where.add(t.alpha > 7);
|
||||||
s.having.add(t.alpha > 7);
|
s.having.add(t.alpha > 7);
|
||||||
s.limit.set(3);
|
s.limit.set(3);
|
||||||
@ -165,7 +163,7 @@ int Select(int, char* [])
|
|||||||
select(sqlpp::value(7).as(t.alpha));
|
select(sqlpp::value(7).as(t.alpha));
|
||||||
|
|
||||||
for (const auto& row :
|
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;
|
std::cerr << row.beta << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, Roland Bock
|
* Copyright (c) 2013-2016, Roland Bock
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
@ -31,6 +31,7 @@
|
|||||||
#include <sqlpp11/select.h>
|
#include <sqlpp11/select.h>
|
||||||
#include <sqlpp11/functions.h>
|
#include <sqlpp11/functions.h>
|
||||||
#include <sqlpp11/connection.h>
|
#include <sqlpp11/connection.h>
|
||||||
|
#include <sqlpp11/without_table_check.h>
|
||||||
|
|
||||||
namespace alias
|
namespace alias
|
||||||
{
|
{
|
||||||
@ -298,7 +299,7 @@ int SelectType(int, char* [])
|
|||||||
t.alpha.as(alias::a) // index 12
|
t.alpha.as(alias::a) // index 12
|
||||||
)
|
)
|
||||||
.from(t)
|
.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 ResultRow = typename Select::_result_methods_t<Select>::template _result_row_t<MockDb>;
|
||||||
using IndexSequence = ResultRow::_field_index_sequence;
|
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,
|
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");
|
"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;
|
int64_t a = row.alpha;
|
||||||
std::cout << a << std::endl;
|
std::cout << a << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
auto s = dynamic_select(db, all_of(t)).dynamic_from().dynamic_where().dynamic_limit().dynamic_offset();
|
auto s = dynamic_select(db, all_of(t)).dynamic_from(t).dynamic_where().dynamic_limit().dynamic_offset();
|
||||||
s.from.add(t);
|
s.from.add(dynamic_join(f).on(f.omega > t.alpha));
|
||||||
s.where.add_ntc(t.alpha > 7 and t.alpha == any(select(t.alpha).from(t).where(t.alpha < 3)));
|
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(30);
|
||||||
s.limit.set(3);
|
s.limit.set(3);
|
||||||
std::cerr << "------------------------\n";
|
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.
|
// 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);
|
auto s = dynamic_select(db).dynamic_columns();
|
||||||
s.selected_columns.add(t.alpha);
|
s.selected_columns.add(without_table_check(t.alpha));
|
||||||
serialize(s, printer).str();
|
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<T>::value, "T has to be numeric");
|
||||||
static_assert(sqlpp::is_numeric_t<decltype(t.alpha)>::value, "TabBar.alpha has to be a numeric");
|
static_assert(sqlpp::is_numeric_t<decltype(t.alpha)>::value, "TabBar.alpha has to be a numeric");
|
||||||
((t.alpha + 7) + 4).asc();
|
((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;
|
!t.gamma;
|
||||||
serialize(t.beta < "kaesekuchen", printer).str();
|
serialize(t.beta < "kaesekuchen", printer).str();
|
||||||
serialize(t.beta + "hallenhalma", printer).str();
|
serialize(t.beta + "hallenhalma", printer).str();
|
||||||
@ -376,7 +378,7 @@ int SelectType(int, char* [])
|
|||||||
auto s1 = sqlpp::select()
|
auto s1 = sqlpp::select()
|
||||||
.flags(sqlpp::distinct, sqlpp::straight_join)
|
.flags(sqlpp::distinct, sqlpp::straight_join)
|
||||||
.columns(l.gamma, r.a)
|
.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))
|
.where(t.beta == "hello world" and select(t.gamma).from(t)) // .as(alias::right))
|
||||||
.group_by(l.gamma, r.a)
|
.group_by(l.gamma, r.a)
|
||||||
.having(r.a != true)
|
.having(r.a != true)
|
||||||
|
@ -37,23 +37,23 @@ int Union(int, char* [])
|
|||||||
const auto t = test::TabBar{};
|
const auto t = test::TabBar{};
|
||||||
const auto f = test::TabFoo{};
|
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).unconditionally().union_distinct(select(f.epsilon.as(t.alpha)).from(f).unconditionally()));
|
||||||
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_all(select(f.epsilon.as(t.alpha)).from(f).unconditionally()));
|
||||||
|
|
||||||
auto u = select(t.alpha)
|
auto u = select(t.alpha)
|
||||||
.from(t)
|
.from(t)
|
||||||
.where(true)
|
.unconditionally()
|
||||||
.union_all(select(f.epsilon.as(t.alpha)).from(f).where(true))
|
.union_all(select(f.epsilon.as(t.alpha)).from(f).unconditionally())
|
||||||
.as(sqlpp::alias::u);
|
.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(all_of(u)).from(u).unconditionally().union_all(select(t.delta.as(t.alpha)).from(t).unconditionally()));
|
||||||
db(select(u.alpha).from(u).where(true).union_all(select(t.delta.as(t.alpha)).from(t).where(true)));
|
db(select(u.alpha).from(u).unconditionally().union_all(select(t.delta.as(t.alpha)).from(t).unconditionally()));
|
||||||
|
|
||||||
db(select(t.alpha)
|
db(select(t.alpha)
|
||||||
.from(t)
|
.from(t)
|
||||||
.where(true)
|
.unconditionally()
|
||||||
.union_all(select(t.alpha).from(t).where(true))
|
.union_all(select(t.alpha).from(t).unconditionally())
|
||||||
.union_all(select(t.alpha).from(t).where(true)));
|
.union_all(select(t.alpha).from(t).unconditionally()));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ int Update(int, char* [])
|
|||||||
serialize(update(t), printer).str();
|
serialize(update(t), printer).str();
|
||||||
serialize(update(t).set(t.gamma = false), 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.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();
|
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.assignments.add(t.beta = "cannot update gamma a second time");
|
||||||
u.where.add(t.gamma != false);
|
u.where.add(t.gamma != false);
|
||||||
@ -63,11 +63,11 @@ int Update(int, char* [])
|
|||||||
|
|
||||||
db(u);
|
db(u);
|
||||||
|
|
||||||
db(update(t).set(t.delta = sqlpp::verbatim<sqlpp::integer>("17+4")).where(true));
|
db(update(t).set(t.delta = sqlpp::verbatim<sqlpp::integer>("17+4")).unconditionally());
|
||||||
db(update(t).set(t.delta = sqlpp::null).where(true));
|
db(update(t).set(t.delta = sqlpp::null).unconditionally());
|
||||||
db(update(t).set(t.delta = sqlpp::default_value).where(true));
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -38,16 +38,16 @@ int With(int, char* [])
|
|||||||
|
|
||||||
auto x = sqlpp::cte(sqlpp::alias::x).as(select(all_of(t)).from(t));
|
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 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;
|
std::cout << serialize(y, printer).str() << std::endl;
|
||||||
printer.reset();
|
printer.reset();
|
||||||
std::cout << serialize(from_table(y), printer).str() << std::endl;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user