0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 12:51:13 +08:00

Merge pull request #1 from rbock/master

Update repo for rbock
This commit is contained in:
Johan 2015-01-18 16:02:06 +01:00
commit 0a66dad4ca
104 changed files with 2156 additions and 991 deletions

32
.travis.yml Normal file
View File

@ -0,0 +1,32 @@
language: cpp
os:
- linux
compiler:
# - clang # disabled clang due to missing libc++
- gcc
notifications:
email:
on_success: change
on_failure: always
before_install:
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- sudo apt-get update
- if [ "$CXX" = "g++" ]; then sudo apt-get install g++-4.8; fi
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
install:
- "mkdir -p $TRAVIS_BUILD_DIR/build/scripts"
- "cd $TRAVIS_BUILD_DIR/build/scripts"
- "cmake $TRAVIS_BUILD_DIR"
script:
- "cd $TRAVIS_BUILD_DIR/build/scripts"
- "make -j3"
# test compile-time constraints
- "make test_sqlpp_constraints"

View File

@ -23,6 +23,10 @@
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
# Cygwin does not define WIN32 and warn if not use with this flag
set(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required
project (sqlpp11) project (sqlpp11)
enable_testing() enable_testing()
@ -34,10 +38,11 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
endif () endif ()
set(include_dir "${PROJECT_SOURCE_DIR}/include") set(include_dir "${PROJECT_SOURCE_DIR}/include")
file(GLOB_RECURSE sqlpp_headers ${include_dir}/*.h) file(GLOB_RECURSE sqlpp_headers "${include_dir}/*.h")
include_directories(${include_dir}) include_directories("${include_dir}")
add_subdirectory(tests) add_subdirectory(tests)
add_subdirectory(test_constraints) add_subdirectory(test_constraints)
add_subdirectory(examples)
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/sqlpp11" DESTINATION include) install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/sqlpp11" DESTINATION include)

View File

@ -7,8 +7,12 @@ This library evolved through several stages and would probably not exist without
* Peter Knoblach: Initial ideas * Peter Knoblach: Initial ideas
* Ulrich Küttler: Feedback and extensions * Ulrich Küttler: Feedback and extensions
* Metafeed GmbH: Production code using a forerunner version * Metafeed GmbH: Production code using a forerunner version
* PPRO Financial Ltd: Production code using sqlpp11 and a forerunner version * PPRO Financial Ltd: Production code using sqlpp11 and a forerunner version
* The boost community: Invaluable suggestions and critiques
* Meeting C++ Munich: Hosted the first talk about sqlpp11
If you miss your name of this list, please let me know. If you miss your name of this list, please let me know.

View File

@ -5,9 +5,11 @@ A type safe embedded domain specific language for SQL queries and results in C++
Extensive documentation is found in the wiki, https://github.com/rbock/sqlpp11/wiki Extensive documentation is found in the wiki, https://github.com/rbock/sqlpp11/wiki
Upcoming talks at Upcoming talks/workshops) at
* CppCon (Bellevue, Washington, USA): http://cppcon.org * CppCon (Bellevue, Washington, USA): http://cppcon.org
* 2014-09-11: http://sched.co/1r4lue3 * 2014-09-08: http://sched.co/1qhngYK (Workshop Part 1)
* 2014-09-11: http://sched.co/1r4lue3 (Talk)
* 2014-09-12: http://sched.co/Wi8aWM (Workshop Part 2)
* MeetingC++ (Berlin, Germany): http://meetingcpp.com/index.php/mcpp2014.html * MeetingC++ (Berlin, Germany): http://meetingcpp.com/index.php/mcpp2014.html
* 2014-12-05:http://meetingcpp.com/index.php/tv14/items/4.html * 2014-12-05:http://meetingcpp.com/index.php/tv14/items/4.html
@ -105,6 +107,7 @@ sqlpp11 makes heavy use of C++11 and requires a recent compiler and STL. The fol
* clang-3.2 on Ubuntu-12.4 * clang-3.2 on Ubuntu-12.4
* clang-3.4 on Ubuntu-12.4 * clang-3.4 on Ubuntu-12.4
* g++-4.8 on Ubuntu-12.4 * g++-4.8 on Ubuntu-12.4
* g++-4.8 on cygwin 64bit
* g++-4.9 on Debian Unstable * g++-4.9 on Debian Unstable
__Database Connector:__ __Database Connector:__

22
examples/CMakeLists.txt Normal file
View File

@ -0,0 +1,22 @@
macro (build arg)
# Add headers to sources to enable file browsing in IDEs
include_directories("${CMAKE_SOURCE_DIR}/tests")
add_executable("Sqlpp11Example${arg}" "${arg}.cpp" ${sqlpp_headers} "${CMAKE_SOURCE_DIR}/tests/MockDb.h" "${CMAKE_CURRENT_LIST_DIR}/Sample.h")
add_test("${arg}" "${arg}")
endmacro ()
#build(sample)
build(insert)
build(update)
build(remove)
build(select)
#find_package(PythonInterp REQUIRED)
#add_custom_command(
# OUTPUT ${CMAKE_CURRENT_LIST_DIR}/Sample.h
# COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/ddl2cpp ${CMAKE_CURRENT_LIST_DIR}/sample.sql Sample test
# DEPENDS ${CMAKE_CURRENT_LIST_DIR}/sample.sql
# )

142
examples/Sample.h Normal file
View File

@ -0,0 +1,142 @@
#ifndef TEST_SAMPLE_H
#define TEST_SAMPLE_H
#include <sqlpp11/table.h>
#include <sqlpp11/column_types.h>
namespace test
{
namespace TabPerson_
{
struct Id
{
struct _name_t
{
static constexpr const char* _get_name() { return "id"; }
template<typename T>
struct _member_t
{
T id;
T& operator()() { return id; }
const T& operator()() const { return id; }
};
};
using _traits = sqlpp::make_traits<sqlpp::integer, sqlpp::tag::must_not_insert, sqlpp::tag::must_not_update, sqlpp::tag::can_be_null>;
};
struct Name
{
struct _name_t
{
static constexpr const char* _get_name() { return "name"; }
template<typename T>
struct _member_t
{
T name;
T& operator()() { return name; }
const T& operator()() const { return name; }
};
};
using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::require_insert>;
};
struct Feature
{
struct _name_t
{
static constexpr const char* _get_name() { return "feature"; }
template<typename T>
struct _member_t
{
T feature;
T& operator()() { return feature; }
const T& operator()() const { return feature; }
};
};
using _traits = sqlpp::make_traits<sqlpp::integer, sqlpp::tag::require_insert>;
};
}
struct TabPerson: sqlpp::table_t<TabPerson,
TabPerson_::Id,
TabPerson_::Name,
TabPerson_::Feature>
{
struct _name_t
{
static constexpr const char* _get_name() { return "tab_person"; }
template<typename T>
struct _member_t
{
T tabPerson;
T& operator()() { return tabPerson; }
const T& operator()() const { return tabPerson; }
};
};
};
namespace TabFeature_
{
struct Id
{
struct _name_t
{
static constexpr const char* _get_name() { return "id"; }
template<typename T>
struct _member_t
{
T id;
T& operator()() { return id; }
const T& operator()() const { return id; }
};
};
using _traits = sqlpp::make_traits<sqlpp::integer, sqlpp::tag::must_not_insert, sqlpp::tag::must_not_update, sqlpp::tag::can_be_null>;
};
struct Name
{
struct _name_t
{
static constexpr const char* _get_name() { return "name"; }
template<typename T>
struct _member_t
{
T name;
T& operator()() { return name; }
const T& operator()() const { return name; }
};
};
using _traits = sqlpp::make_traits<sqlpp::varchar, sqlpp::tag::can_be_null>;
};
struct Fatal
{
struct _name_t
{
static constexpr const char* _get_name() { return "fatal"; }
template<typename T>
struct _member_t
{
T fatal;
T& operator()() { return fatal; }
const T& operator()() const { return fatal; }
};
};
using _traits = sqlpp::make_traits<sqlpp::boolean, sqlpp::tag::require_insert>;
};
}
struct TabFeature: sqlpp::table_t<TabFeature,
TabFeature_::Id,
TabFeature_::Name,
TabFeature_::Fatal>
{
struct _name_t
{
static constexpr const char* _get_name() { return "tab_feature"; }
template<typename T>
struct _member_t
{
T tabFeature;
T& operator()() { return tabFeature; }
const T& operator()() const { return tabFeature; }
};
};
};
}
#endif

177
examples/TabSample.h Normal file
View File

@ -0,0 +1,177 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_TAB_SAMPLE_H
#define SQLPP_TAB_SAMPLE_H
#include <sqlpp11/table_base.h>
#include <sqlpp11/column_types.h>
namespace TabFoo_
{
struct Omega
{
struct _name_t
{
static constexpr const char* _get_name() { return "omega"; }
};
template<typename T>
struct _member_t
{
/*
template<typename... TT>
_name_t(TT&&... t): omega(std::forward<TT>(t)...) {}
template<typename TT>
_name_t& operator=(TT&& t) { omega = std::forward<TT>(t); return *this; }
*/
T omega;
};
using _value_type = sqlpp::bigint;
struct _column_type
{
};
};
}
struct TabFoo: sqlpp::table_base_t<
TabFoo,
TabFoo_::Omega
>
{
using _value_type = sqlpp::no_value_t;
struct _name_t
{
static constexpr const char* _get_name() { return "tab_foo"; }
};
template<typename T>
struct _member_t
{
T tabFoo;
};
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << _name_t::_get_name();
}
};
namespace TabSample_
{
struct Alpha
{
struct _name_t
{
static constexpr const char* _get_name() { return "alpha"; }
};
template<typename T>
struct _member_t
{
/*
template<typename... TT>
_name_t(TT&&... t): alpha(std::forward<TT>(t)...) {}
template<typename TT>
_name_t& operator=(TT&& t) { alpha = std::forward<TT>(t); return *this; }
*/
T alpha;
};
using _value_type = sqlpp::bigint;
struct _column_type
{
using _must_not_insert = sqlpp::tag_yes;
using _must_not_update = sqlpp::tag_yes;
using _can_be_null = sqlpp::tag_yes;
using _foreign_key = decltype(TabFoo::omega);
};
};
struct Beta
{
struct _name_t
{
static constexpr const char* _get_name() { return "beta"; }
};
template<typename T>
struct _member_t
{
T beta;
};
using _value_type = sqlpp::varchar;
struct _column_type
{
using _can_be_null = sqlpp::tag_yes;
using _must_not_update = sqlpp::tag_yes;
};
};
struct Gamma
{
struct _name_t
{
static constexpr const char* _get_name() { return "gamma"; }
};
template<typename T>
struct _member_t
{
T gamma;
};
using _value_type = sqlpp::boolean;
struct _column_type
{
using _require_insert = sqlpp::tag_yes;
};
};
}
struct TabSample: sqlpp::table_base_t<
TabSample,
TabSample_::Alpha,
TabSample_::Beta,
TabSample_::Gamma
>
{
using _value_type = sqlpp::no_value_t;
struct _name_t
{
static constexpr const char* _get_name() { return "tab_sample"; }
};
template<typename T>
struct _member_t
{
T tabSample;
};
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << _name_t::_get_name();
}
};
#endif

67
examples/insert.cpp Normal file
View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/sqlpp11.h>
MockDb db;
test::TabPerson p;
test::TabFeature f;
int main()
{
db(insert_into(f).set(f.name = "loves c++", f.fatal = false));
//db(insert_into(f).set(f.nahme = "loves c++", f.fatal = false));
//db(insert_into(f).set(f.name == "loves c++", f.fatal = false));
//db(insert_into(f).set(f.name = "loves c++", f.fatal = "false"));
//db(insert_into(p).set(f.name = "loves c++", f.fatal = false));
//db(insert_into(f).set(f.name = "loves c++", p.feature = 7));
//db(insert_into(f).set(f.id = 42, f.name = "loves c++", f.fatal = false));
//db(insert_into(f).set(f.name = "loves c++"));
db(insert_into(f).default_values());
auto i = insert_into(p).columns(p.name, p.feature);
i.values.add(p.name = "Roland", p.feature = 1);
i.values.add(p.name = "Zaphod", p.feature = sqlpp::default_value);
db(i);
auto pi = db.prepare(insert_into(p).set(p.name = parameter(f.name), p.feature = parameter(p.feature)));
pi.params.name = "likes java";
pi.params.feature = true;
db(pi);
}

40
examples/remove.cpp Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/sqlpp11.h>
MockDb db;
test::TabPerson p;
test::TabFeature q;
int main()
{
db(remove_from(p)
.using_(p, q)
.where(p.feature == q.id and q.fatal == true));
}

59
examples/sample.cpp Normal file
View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/sqlpp11.h>
MockDb db;
test::TabPerson p;
test::TabFeature f;
int main()
{
db(insert_into(f).set(f.name = "Loves C++", p.fatal = false));
db(insert_into(f).set(p.name = "Roland", p.feature = 1));
auto s = select(all_of(p))
.from(p, q)
.where(p.name == any(select(q.name)
.from(q)
.where(true)))
.group_by(q.name)
.having(p.name.like("%Bee%"))
.order_by(p.name.asc())
.limit(3).offset(7);
auto x = s.as(sqlpp::alias::x);
for (const auto& row : db(select(p.id, x.name)
.from(p.join(x).on(p.feature == x.feature))
.where(true)))
{
int id = row.id;
std::string name = row.name;
}
}

40
examples/sample.sql Normal file
View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2013, 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.
*/
CREATE TABLE tab_person
(
id int AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NOT NULL,
feature int NOT NULL
);
CREATE TABLE tab_feature
(
id int AUTO_INCREMENT PRIMARY KEY,
name varchar(255) NULL DEFAULT "",
fatal bool NOT NULL
);

135
examples/select.cpp Normal file
View File

@ -0,0 +1,135 @@
/*
* Copyright (c) 2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wunused-variable"
#endif
#if defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-variable"
#endif
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/sqlpp11.h>
SQLPP_ALIAS_PROVIDER(cheesecake);
MockDb db;
test::TabPerson p;
test::TabFeature f;
int main()
{
for (const auto& row : db(select(all_of(p)).from(p).where(p.id > 7)))
{
int64_t id = row.id;
std::string name = row.name;
int64_t feature = row.feature;
}
#if 0
for (const auto& row : db(select(p.name).from(p).where(p.name.like("Herb%"))))
{
int64_t id = row.id;
std::string name = row.name;
int64_t feature = row.feature;
}
#endif
#if 0
for (const auto& row : db(select(p.name, f.name.as(cheesecake)).from(p,f).where(p.id > 7 and p.feature == 3)))
{
//int64_t id = row.id;
//std::string a = row.a;
std::string name = row.name;
std::string feature = row.cheesecake;
}
#endif
#if 0
for (const auto& row : db(select(multi_column(all_of(p)).as(p), multi_column(f.name, f.id).as(f)).from(p,f).where(true)))
{
//int64_t id = row.id;
//std::string a = row.a;
std::string name = row.tabPerson.name;
std::string name1 = row.tabFeature.name;
//int64_t feature = row.feature;
}
#endif
#if !0
auto s = select(all_of(p))
.from(p, f)
.where(p.name == any(select(f.name)
.from(f)
.where(true)))
.group_by(f.name)
.having(p.name.like("%Bee%"))
.order_by(p.name.asc())
.limit(3).offset(7);
auto x = s.as(sqlpp::alias::x);
for (const auto& row : db(select(p.id, x.name)
.from(p.join(x).on(p.feature == x.feature))
.where(true)))
{
int id = row.id;
std::string name = row.name;
}
#endif
}

38
examples/update.cpp Normal file
View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/sqlpp11.h>
MockDb db;
test::TabPerson p;
test::TabFeature q;
int main()
{
db(update(p).set(p.feature = 7).where(p.id == 23));
}

View File

@ -35,7 +35,7 @@ namespace sqlpp
template<typename Expression, typename AliasProvider> template<typename Expression, typename AliasProvider>
struct expression_alias_t struct expression_alias_t
{ {
using _traits = make_traits<value_type_of<Expression>, tag::is_named_expression, tag::is_alias>; using _traits = make_traits<value_type_of<Expression>, tag::is_selectable, tag::is_alias>;
using _recursive_traits = make_recursive_traits<Expression>; using _recursive_traits = make_recursive_traits<Expression>;
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias"); static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");

View File

@ -41,7 +41,7 @@ namespace sqlpp
template<typename AliasProvider> template<typename AliasProvider>
detail::copy_tuple_args_t<multi_column_alias_t, AliasProvider, _column_tuple_t> as(const AliasProvider& alias) detail::copy_tuple_args_t<multi_column_alias_t, AliasProvider, _column_tuple_t> as(const AliasProvider& alias)
{ {
return ::sqlpp::multi_column(_column_tuple_t{}).as(alias); return multi_column(_column_tuple_t{}).as(alias);
} }
}; };

View File

@ -35,7 +35,7 @@ namespace sqlpp
template<typename Select> template<typename Select>
struct any_t struct any_t
{ {
using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::is_multi_expression>; using _traits = make_traits<value_type_of<Select>, tag::is_multi_expression>;
using _recursive_traits = make_recursive_traits<Select>; using _recursive_traits = make_recursive_traits<Select>;
struct _name_t struct _name_t

View File

@ -40,7 +40,7 @@ namespace sqlpp
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct assignment_t struct assignment_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_assignment>; using _traits = make_traits<no_value_t, tag::is_assignment>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _lhs_t = Lhs; using _lhs_t = Lhs;

View File

@ -32,13 +32,14 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Flag, typename Expr> template<typename Flag, typename Expr>
struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>>, struct avg_t:
public alias_operators<avg_t<Flag, Expr>> public expression_operators<avg_t<Flag, Expr>, floating_point>,
public alias_operators<avg_t<Flag, Expr>>
{ {
using _traits = make_traits<floating_point, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<floating_point, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr, aggregate_function>;
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "avg() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "avg() used with flag other than 'distinct'");
static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument"); static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument");
struct _name_t struct _name_t
@ -74,7 +75,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "AVG("; context << "AVG(";
if (std::is_same<sqlpp::distinct_t, Flag>::value) if (std::is_same<distinct_t, Flag>::value)
{ {
serialize(Flag(), context); serialize(Flag(), context);
context << ' '; context << ' ';
@ -88,13 +89,15 @@ namespace sqlpp
template<typename T> template<typename T>
auto avg(T t) -> avg_t<noop, wrap_operand_t<T>> auto avg(T t) -> avg_t<noop, wrap_operand_t<T>>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "avg() cannot be used on an aggregate function");
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument"); static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
return { t }; return { t };
} }
template<typename T> template<typename T>
auto avg(const sqlpp::distinct_t&, T t) -> avg_t<sqlpp::distinct_t, wrap_operand_t<T>> auto avg(const distinct_t&, T t) -> avg_t<distinct_t, wrap_operand_t<T>>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "avg() cannot be used on an aggregate function");
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument"); static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
return { t }; return { t };
} }

View File

@ -27,18 +27,19 @@
#ifndef SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H #ifndef SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H
#define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H #define SQLPP_DETAIL_BASIC_EXPRESSION_OPERATORS_H
#include <sqlpp11/value_type_fwd.h>
#include <sqlpp11/alias.h> #include <sqlpp11/alias.h>
#include <sqlpp11/sort_order.h> #include <sqlpp11/sort_order.h>
#include <sqlpp11/expression_fwd.h> #include <sqlpp11/expression_fwd.h>
#include <sqlpp11/in_fwd.h> #include <sqlpp11/in_fwd.h>
#include <sqlpp11/is_null_fwd.h> #include <sqlpp11/is_null_fwd.h>
#include <sqlpp11/wrap_operand.h> #include <sqlpp11/wrap_operand_fwd.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
namespace sqlpp namespace sqlpp
{ {
// basic operators // basic operators
template<typename Base, template<typename> class IsCorrectValueType> template<typename Expr, typename ValueType>
struct basic_expression_operators struct basic_expression_operators
{ {
template<typename T> template<typename T>
@ -47,107 +48,107 @@ namespace sqlpp
static constexpr bool value = static constexpr bool value =
(is_expression_t<T>::value // expressions are OK (is_expression_t<T>::value // expressions are OK
or is_multi_expression_t<T>::value) // multi-expressions like ANY are OK for comparisons, too or is_multi_expression_t<T>::value) // multi-expressions like ANY are OK for comparisons, too
and IsCorrectValueType<T>::value // the correct value type is required, of course and ValueType::template _is_valid_operand<T>::value // the correct value type is required, of course
; ;
}; };
template<typename T> template<typename T>
equal_to_t<Base, wrap_operand_t<T>> operator==(T t) const equal_to_t<Expr, wrap_operand_t<T>> operator==(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), {rhs{t}} }; return { *static_cast<const Expr*>(this), {rhs{t}} };
} }
template<typename T> template<typename T>
not_equal_to_t<Base, wrap_operand_t<T>> operator!=(T t) const not_equal_to_t<Expr, wrap_operand_t<T>> operator!=(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), {rhs{t}} }; return { *static_cast<const Expr*>(this), {rhs{t}} };
} }
template<typename T> template<typename T>
less_than_t<Base, wrap_operand_t<T>> operator<(T t) const less_than_t<Expr, wrap_operand_t<T>> operator<(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Expr*>(this), rhs{t} };
} }
template<typename T> template<typename T>
less_equal_t<Base, wrap_operand_t<T>> operator<=(T t) const less_equal_t<Expr, wrap_operand_t<T>> operator<=(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Expr*>(this), rhs{t} };
} }
template<typename T> template<typename T>
greater_than_t<Base, wrap_operand_t<T>> operator>(T t) const greater_than_t<Expr, wrap_operand_t<T>> operator>(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Expr*>(this), rhs{t} };
} }
template<typename T> template<typename T>
greater_equal_t<Base, wrap_operand_t<T>> operator>=(T t) const greater_equal_t<Expr, wrap_operand_t<T>> operator>=(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Expr*>(this), rhs{t} };
} }
is_null_t<true, Base> is_null() const is_null_t<true, Expr> is_null() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Expr*>(this) };
} }
is_null_t<false, Base> is_not_null() const is_null_t<false, Expr> is_not_null() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Expr*>(this) };
} }
sort_order_t<Base, sort_type::asc> asc() sort_order_t<Expr, sort_type::asc> asc() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Expr*>(this) };
} }
sort_order_t<Base, sort_type::desc> desc() sort_order_t<Expr, sort_type::desc> desc() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Expr*>(this) };
} }
// Hint: use value_list wrapper for containers... // Hint: use value_list wrapper for containers...
template<typename... T> template<typename... T>
in_t<true, Base, wrap_operand_t<T>...> in(T... t) const in_t<true, Expr, wrap_operand_t<T>...> in(T... t) const
{ {
static_assert(detail::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid"); static_assert(detail::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Base*>(this), wrap_operand_t<T>{t}... }; return { *static_cast<const Expr*>(this), wrap_operand_t<T>{t}... };
} }
template<typename... T> template<typename... T>
in_t<false, Base, wrap_operand_t<T>...> not_in(T... t) const in_t<false, Expr, wrap_operand_t<T>...> not_in(T... t) const
{ {
static_assert(detail::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid"); static_assert(detail::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Base*>(this), wrap_operand_t<T>{t}... }; return { *static_cast<const Expr*>(this), wrap_operand_t<T>{t}... };
} }
}; };
template<typename Base> template<typename Expr>
struct alias_operators struct alias_operators
{ {
template<typename alias_provider> template<typename alias_provider>
expression_alias_t<Base, alias_provider> as(const alias_provider&) expression_alias_t<Expr, alias_provider> as(const alias_provider&) const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Expr*>(this) };
} }
}; };

View File

@ -40,32 +40,39 @@ namespace sqlpp
// boolean value type // boolean value type
struct boolean struct boolean
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::is_boolean, ::sqlpp::tag::is_value_type>; using _traits = make_traits<boolean, tag::is_value_type>;
using _tag = ::sqlpp::tag::is_boolean; using _tag = tag::is_boolean;
using _cpp_value_type = bool; using _cpp_value_type = bool;
struct _parameter_t template<typename T>
using _is_valid_operand = is_boolean_t<T>;
};
// boolean parameter type
template<>
struct parameter_value_t<boolean>
{ {
using _value_type = boolean; // FIXME using _value_type = boolean; // FIXME
using _cpp_value_type = typename _value_type::_cpp_value_type;
_parameter_t(): parameter_value_t():
_value(false), _value(false),
_is_null(true) _is_null(true)
{} {}
_parameter_t(const _cpp_value_type& value): parameter_value_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(false) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) parameter_value_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = false; _is_null = false;
return *this; return *this;
} }
_parameter_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t) parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
{ {
if (t._is_trivial()) if (t._is_trivial())
{ {
@ -80,7 +87,7 @@ namespace sqlpp
return *this; return *this;
} }
_parameter_t& operator=(const std::nullptr_t&) parameter_value_t& operator=(const std::nullptr_t&)
{ {
_value = false; _value = false;
_is_null = true; _is_null = true;
@ -110,48 +117,44 @@ namespace sqlpp
bool _is_null; bool _is_null;
}; };
// boolean expression operators
template<typename Base>
struct expression_operators<Base, boolean>: public basic_expression_operators<Base, boolean>
{
template<typename T> template<typename T>
struct _is_valid_operand using _is_valid_operand = is_valid_operand<boolean, T>;
template<typename T>
logical_and_t<Base, wrap_operand_t<T>> operator and(T t) const
{ {
static constexpr bool value = using rhs = wrap_operand_t<T>;
is_expression_t<T>::value // expressions are OK static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
and is_boolean_t<T>::value // the correct value type is required, of course
;
};
template<typename Base> return { *static_cast<const Base*>(this), rhs{t} };
struct expression_operators: public basic_expression_operators<Base, is_boolean_t>
{
template<typename T>
logical_and_t<Base, wrap_operand_t<T>> operator and(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
}
template<typename T>
logical_or_t<Base, wrap_operand_t<T>> operator or(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
}
logical_not_t<Base> operator not() const
{
return { *static_cast<const Base*>(this) };
} }
};
template<typename Base> template<typename T>
struct column_operators logical_or_t<Base, wrap_operand_t<T>> operator or(T t) const
{ {
}; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} };
}
logical_not_t<Base> operator not() const
{
return { *static_cast<const Base*>(this) };
}
}; };
// boolean column operators
template<typename Base>
struct column_operators<Base, boolean>
{
};
// boolean result field
template<typename Db, typename FieldSpec> template<typename Db, typename FieldSpec>
struct result_field_t<boolean, Db, FieldSpec>: public result_field_methods_t<result_field_t<boolean, Db, FieldSpec>> struct result_field_t<boolean, Db, FieldSpec>: public result_field_methods_t<result_field_t<boolean, Db, FieldSpec>>
{ {

View File

@ -33,7 +33,7 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Database> template<typename Database>
struct boolean_expression_t: public boolean::template expression_operators<boolean_expression_t<Database>> struct boolean_expression_t: public expression_operators<boolean_expression_t<Database>, boolean>
{ {
using _traits = make_traits<boolean, tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;

View File

@ -42,13 +42,14 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Table, typename ColumnSpec> template<typename Table, typename ColumnSpec>
struct column_t: public value_type_of<ColumnSpec>::template expression_operators<column_t<Table, ColumnSpec>>, struct column_t:
public value_type_of<ColumnSpec>::template column_operators<column_t<Table, ColumnSpec>> public expression_operators<column_t<Table, ColumnSpec>, value_type_of<ColumnSpec>>,
public column_operators<column_t<Table, ColumnSpec>, value_type_of<ColumnSpec>>
{ {
struct _traits struct _traits
{ {
using _value_type = value_type_of<ColumnSpec>; using _value_type = value_type_of<ColumnSpec>;
using _tags = detail::make_joined_set_t<detail::type_set<tag::is_column, tag::is_expression, tag::is_named_expression>, typename ColumnSpec::_traits::_tags>; using _tags = detail::make_joined_set_t<detail::type_set<tag::is_column, tag::is_expression, tag::is_selectable>, typename ColumnSpec::_traits::_tags>;
}; };
struct _recursive_traits struct _recursive_traits
@ -58,7 +59,9 @@ namespace sqlpp
using _provided_outer_tables = detail::type_set<>; using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<Table>; using _required_tables = detail::type_set<Table>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _can_be_null = column_spec_can_be_null_t<ColumnSpec>; using _tags = typename std::conditional<column_spec_can_be_null_t<ColumnSpec>::value,
detail::type_set<tag::can_be_null>,
detail::type_set<>>::type;
}; };
using _spec_t = ColumnSpec; using _spec_t = ColumnSpec;
@ -66,7 +69,7 @@ namespace sqlpp
using _name_t = typename _spec_t::_name_t; using _name_t = typename _spec_t::_name_t;
template<typename T> template<typename T>
using _is_valid_operand = typename value_type_of<ColumnSpec>::template _is_valid_operand<T>; using _is_valid_operand = is_valid_operand<value_type_of<ColumnSpec>, T>;
column_t() = default; column_t() = default;
column_t(const column_t&) = default; column_t(const column_t&) = default;
@ -90,22 +93,22 @@ namespace sqlpp
auto operator =(T t) const -> assignment_t<column_t, wrap_operand_t<T>> auto operator =(T t) const -> assignment_t<column_t, wrap_operand_t<T>>
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *this, {rhs{t}} }; return { *this, {rhs{t}} };
} }
auto operator =(sqlpp::null_t) const auto operator =(null_t) const
->assignment_t<column_t, sqlpp::null_t> ->assignment_t<column_t, null_t>
{ {
static_assert(can_be_null_t<column_t>::value, "column cannot be null"); static_assert(can_be_null_t<column_t>::value, "column cannot be null");
return { *this, sqlpp::null_t{} }; return { *this, null_t{} };
} }
auto operator =(sqlpp::default_value_t) const auto operator =(default_value_t) const
->assignment_t<column_t, sqlpp::default_value_t> ->assignment_t<column_t, default_value_t>
{ {
return { *this, sqlpp::default_value_t{} }; return { *this, default_value_t{} };
} }
}; };

View File

@ -36,14 +36,15 @@ namespace sqlpp
{ {
// FIXME: Remove First, inherit from text_t // FIXME: Remove First, inherit from text_t
template<typename First, typename... Args> template<typename First, typename... Args>
struct concat_t: public value_type_of<First>::template expression_operators<concat_t<First, Args...>>, struct concat_t:
public alias_operators<concat_t<First, Args...>> public expression_operators<concat_t<First, Args...>, value_type_of<First>>,
public alias_operators<concat_t<First, Args...>>
{ {
using _traits = make_traits<value_type_of<First>, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<value_type_of<First>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<First, Args...>; using _recursive_traits = make_recursive_traits<First, Args...>;
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
static_assert(sqlpp::detail::all_t<is_text_t<First>::value, is_text_t<Args>::value...>::value, "at least one non-text argument detected in concat()"); static_assert(detail::all_t<is_text_t<First>::value, is_text_t<Args>::value...>::value, "at least one non-text argument detected in concat()");
struct _name_t struct _name_t
{ {
static constexpr const char* _get_name() { return "CONCAT"; } static constexpr const char* _get_name() { return "CONCAT"; }

View File

@ -33,14 +33,24 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Flag, typename Expr> template<typename Flag, typename Expr>
struct count_t: public sqlpp::integral::template expression_operators<count_t<Flag, Expr>>, struct count_t:
public alias_operators<count_t<Flag, Expr>> public expression_operators<count_t<Flag, Expr>, integral>,
public alias_operators<count_t<Flag, Expr>>
{ {
using _traits = make_traits<::sqlpp::integral, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<integral, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr>; struct _recursive_traits
{
using _required_tables = required_tables_of<Expr>;
using _provided_tables = provided_tables_of<Expr>;
using _provided_outer_tables = provided_outer_tables_of<Expr>;
using _extra_tables = extra_tables_of<Expr>;
using _parameters = parameters_of<Expr>;
using _tags = detail::make_difference_set_t<detail::joined_set_t<recursive_tags_of<Expr>, recursive_tags_of<aggregate_function>>,
detail::type_set<tag::can_be_null>>;
};
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "count() used with flag other than 'distinct'");
static_assert(is_expression_t<Expr>::value, "count() requires a sql expression as argument"); static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "count() used with flag other than 'distinct'");
struct _name_t struct _name_t
{ {
@ -75,7 +85,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "COUNT("; context << "COUNT(";
if (std::is_same<sqlpp::distinct_t, Flag>::value) if (std::is_same<distinct_t, Flag>::value)
{ {
serialize(Flag(), context); serialize(Flag(), context);
context << ' '; context << ' ';
@ -94,7 +104,7 @@ namespace sqlpp
} }
template<typename T> template<typename T>
auto count(const sqlpp::distinct_t&, T t) -> count_t<sqlpp::distinct_t, wrap_operand_t<T>> auto count(const distinct_t&, T t) -> count_t<distinct_t, wrap_operand_t<T>>
{ {
static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
return { t }; return { t };

View File

@ -43,9 +43,9 @@ namespace sqlpp
}; };
template<typename T> template<typename T>
struct as_tuple<::sqlpp::all_of_t<T>> struct as_tuple<all_of_t<T>>
{ {
static typename ::sqlpp::all_of_t<T>::_column_tuple_t _(::sqlpp::all_of_t<T>) { return { }; } static typename all_of_t<T>::_column_tuple_t _(all_of_t<T>) { return { }; }
}; };
template<typename... Args> template<typename... Args>

View File

@ -27,6 +27,7 @@
#ifndef SQLPP_DETAIL_LOGIC_H #ifndef SQLPP_DETAIL_LOGIC_H
#define SQLPP_DETAIL_LOGIC_H #define SQLPP_DETAIL_LOGIC_H
#include <ciso646> // Required for some compilers to use aliases for boolean operators
#include <type_traits> #include <type_traits>
namespace sqlpp namespace sqlpp

View File

@ -73,7 +73,7 @@ namespace sqlpp
template<typename E, typename SET> template<typename E, typename SET>
struct is_element_of struct is_element_of
{ {
static_assert(::sqlpp::wrong_t<is_element_of>::value, "SET has to be a type set"); static_assert(wrong_t<is_element_of>::value, "SET has to be a type set");
}; };
template<typename E, typename... Elements> template<typename E, typename... Elements>
@ -85,7 +85,7 @@ namespace sqlpp
template<typename L, typename R> template<typename L, typename R>
struct joined_set struct joined_set
{ {
static_assert(::sqlpp::wrong_t<joined_set>::value, "L and R have to be type sets"); static_assert(wrong_t<joined_set>::value, "L and R have to be type sets");
}; };
template<typename... LElements, typename... RElements> template<typename... LElements, typename... RElements>
@ -100,7 +100,7 @@ namespace sqlpp
template<typename L, typename R> template<typename L, typename R>
struct is_superset_of struct is_superset_of
{ {
static_assert(::sqlpp::wrong_t<is_superset_of>::value, "L and R have to be type sets"); static_assert(wrong_t<is_superset_of>::value, "L and R have to be type sets");
}; };
template<typename... LElements, typename... RElements> template<typename... LElements, typename... RElements>
@ -118,7 +118,7 @@ namespace sqlpp
template<typename L, typename R> template<typename L, typename R>
struct is_disjunct_from struct is_disjunct_from
{ {
static_assert(::sqlpp::wrong_t<is_disjunct_from>::value, "invalid argument for is_disjunct_from"); static_assert(wrong_t<is_disjunct_from>::value, "invalid argument for is_disjunct_from");
}; };
template<typename... LElements, typename... RElements> template<typename... LElements, typename... RElements>
@ -174,7 +174,7 @@ namespace sqlpp
template<typename... T> template<typename... T>
struct make_joined_set struct make_joined_set
{ {
static_assert(::sqlpp::wrong_t<make_joined_set>::value, "invalid argument for joined set"); static_assert(wrong_t<make_joined_set>::value, "invalid argument for joined set");
}; };
template<> template<>
@ -197,7 +197,7 @@ namespace sqlpp
template<typename Minuend, typename Subtrahend> template<typename Minuend, typename Subtrahend>
struct make_difference_set struct make_difference_set
{ {
static_assert(::sqlpp::wrong_t<make_difference_set>::value, "invalid argument for difference set"); static_assert(wrong_t<make_difference_set>::value, "invalid argument for difference set");
}; };
template<typename... Minuends, typename... Subtrahends> template<typename... Minuends, typename... Subtrahends>
@ -214,7 +214,7 @@ namespace sqlpp
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct make_intersect_set struct make_intersect_set
{ {
static_assert(::sqlpp::wrong_t<make_intersect_set>::value, "invalid argument for intersect set"); static_assert(wrong_t<make_intersect_set>::value, "invalid argument for intersect set");
}; };
template<typename... LhsElements, typename... RhsElements> template<typename... LhsElements, typename... RhsElements>
@ -232,7 +232,7 @@ namespace sqlpp
template<template<typename> class Transformation, typename T> template<template<typename> class Transformation, typename T>
struct transform_set struct transform_set
{ {
static_assert(::sqlpp::wrong_t<transform_set>::value, "invalid argument for transform_set"); static_assert(wrong_t<transform_set>::value, "invalid argument for transform_set");
}; };
template<template<typename> class Transformation, typename... E> template<template<typename> class Transformation, typename... E>

62
include/sqlpp11/eval.h Normal file
View File

@ -0,0 +1,62 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EVAL_H
#define SQLPP_EVAL_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/field_spec.h>
#include <sqlpp11/alias_provider.h>
#include <sqlpp11/verbatim.h>
namespace sqlpp
{
template<typename Db, typename Expr>
struct eval_t
{
static_assert(is_database<Db>::value, "Db parameter of eval has to be a database connection");
static_assert(is_expression_t<Expr>::value, "Expression parameter of eval has to be an sqlpp expression or a string");
static_assert(required_tables_of<Expr>::size::value == 0, "Expression cannot be used in eval because it requires tables");
using _name_type = alias::a_t::_name_t;
using _value_type = value_type_of<Expr>;
using _field_spec = field_spec_t<_name_type, _value_type, true, false>;
using type = result_field_t<_value_type, Db, _field_spec>;
};
template<typename Db, typename Expr, typename std::enable_if<not std::is_convertible<Expr, std::string>::value, int>::type = 0>
auto eval(Db& db, Expr expr) -> typename eval_t<Db, Expr>::type
{
return db(select(expr.as(alias::a))).front().a;
}
template<typename ValueType, typename Db>
auto eval(Db& db, std::string sql_code) -> decltype(eval(db, verbatim<ValueType>(sql_code)))
{
return eval(db, verbatim<ValueType>(sql_code));
}
}
#endif

View File

@ -32,10 +32,11 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Select> template<typename Select>
struct exists_t: public boolean::template expression_operators<exists_t<Select>>, struct exists_t:
public alias_operators<exists_t<Select>> public expression_operators<exists_t<Select>, boolean>,
public alias_operators<exists_t<Select>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Select>; using _recursive_traits = make_recursive_traits<Select>;
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument"); static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");

View File

@ -39,10 +39,11 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, op::equal_to, Rhs>: public ::sqlpp::boolean::template expression_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>, struct binary_expression_t<Lhs, op::equal_to, Rhs>:
public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>> public expression_operators<binary_expression_t<Lhs, op::equal_to, Rhs>, boolean>,
public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>
{ {
using _traits = make_traits<boolean, sqlpp::tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _lhs_t = Lhs; using _lhs_t = Lhs;
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>;
@ -86,10 +87,11 @@ namespace sqlpp
}; };
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, op::not_equal_to, Rhs>: public ::sqlpp::boolean::template expression_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>, struct binary_expression_t<Lhs, op::not_equal_to, Rhs>:
public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>> public expression_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>, boolean>,
public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>
{ {
using _traits = make_traits<boolean, sqlpp::tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _lhs_t = Lhs; using _lhs_t = Lhs;
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>;
@ -133,10 +135,11 @@ namespace sqlpp
}; };
template<typename Rhs> template<typename Rhs>
struct unary_expression_t<op::logical_not, Rhs>: public ::sqlpp::boolean::template expression_operators<unary_expression_t<op::logical_not, Rhs>>, struct unary_expression_t<op::logical_not, Rhs>:
public alias_operators<unary_expression_t<op::logical_not, Rhs>> public expression_operators<unary_expression_t<op::logical_not, Rhs>, boolean>,
public alias_operators<unary_expression_t<op::logical_not, Rhs>>
{ {
using _traits = make_traits<boolean, sqlpp::tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Rhs>; using _recursive_traits = make_recursive_traits<Rhs>;
unary_expression_t(Rhs rhs): unary_expression_t(Rhs rhs):
@ -177,10 +180,11 @@ namespace sqlpp
}; };
template<typename Lhs, typename O, typename Rhs> template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t: public value_type_of<O>::template expression_operators<binary_expression_t<Lhs, O, Rhs>>, struct binary_expression_t:
public alias_operators<binary_expression_t<Lhs, O, Rhs>> public expression_operators<binary_expression_t<Lhs, O, Rhs>, value_type_of<O>>,
public alias_operators<binary_expression_t<Lhs, O, Rhs>>
{ {
using _traits = make_traits<value_type_of<O>, sqlpp::tag::is_expression>; using _traits = make_traits<value_type_of<O>, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
binary_expression_t(Lhs lhs, Rhs rhs): binary_expression_t(Lhs lhs, Rhs rhs):
@ -215,10 +219,11 @@ namespace sqlpp
}; };
template<typename O, typename Rhs> template<typename O, typename Rhs>
struct unary_expression_t: public value_type_of<O>::template expression_operators<unary_expression_t<O, Rhs>>, struct unary_expression_t:
public alias_operators<unary_expression_t<O, Rhs>> public expression_operators<unary_expression_t<O, Rhs>, value_type_of<O>>,
public alias_operators<unary_expression_t<O, Rhs>>
{ {
using _traits = make_traits<value_type_of<O>, sqlpp::tag::is_expression>; using _traits = make_traits<value_type_of<O>, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Rhs>; using _recursive_traits = make_recursive_traits<Rhs>;
unary_expression_t(Rhs rhs): unary_expression_t(Rhs rhs):

View File

@ -37,53 +37,53 @@ namespace sqlpp
{ {
struct less struct less
{ {
using _traits = make_traits<::sqlpp::boolean>; using _traits = make_traits<boolean>;
static constexpr const char* _name = "<"; static constexpr const char* _name = "<";
}; };
struct less_equal struct less_equal
{ {
using _traits = make_traits<::sqlpp::boolean>; using _traits = make_traits<boolean>;
static constexpr const char* _name = "<="; static constexpr const char* _name = "<=";
}; };
struct equal_to struct equal_to
{ {
using _traits = make_traits<::sqlpp::boolean>; using _traits = make_traits<boolean>;
}; };
struct not_equal_to struct not_equal_to
{ {
using _traits = make_traits<::sqlpp::boolean>; using _traits = make_traits<boolean>;
}; };
struct greater_equal struct greater_equal
{ {
using _traits = make_traits<::sqlpp::boolean>; using _traits = make_traits<boolean>;
static constexpr const char* _name = ">="; static constexpr const char* _name = ">=";
}; };
struct greater struct greater
{ {
using _traits = make_traits<::sqlpp::boolean>; using _traits = make_traits<boolean>;
static constexpr const char* _name = ">"; static constexpr const char* _name = ">";
}; };
struct logical_or struct logical_or
{ {
using _traits = make_traits<::sqlpp::boolean>; using _traits = make_traits<boolean>;
static constexpr const char* _name = " OR "; static constexpr const char* _name = " OR ";
}; };
struct logical_and struct logical_and
{ {
using _traits = make_traits<::sqlpp::boolean>; using _traits = make_traits<boolean>;
static constexpr const char* _name = " AND "; static constexpr const char* _name = " AND ";
}; };
struct logical_not struct logical_not
{ {
using _traits = make_traits<::sqlpp::boolean>; using _traits = make_traits<boolean>;
}; };
template<typename ValueType> template<typename ValueType>
@ -109,13 +109,13 @@ namespace sqlpp
struct divides struct divides
{ {
using _traits = make_traits<::sqlpp::floating_point>; using _traits = make_traits<floating_point>;
static constexpr const char* _name = "/"; static constexpr const char* _name = "/";
}; };
struct modulus struct modulus
{ {
using _traits = make_traits<::sqlpp::integral>; using _traits = make_traits<integral>;
static constexpr const char* _name = "%"; static constexpr const char* _name = "%";
}; };
@ -208,6 +208,12 @@ namespace sqlpp
template<typename Lhs, typename ValueType, typename Rhs> template<typename Lhs, typename ValueType, typename Rhs>
using bitwise_or_t = binary_expression_t<Lhs, op::bitwise_or<ValueType>, Rhs>; using bitwise_or_t = binary_expression_t<Lhs, op::bitwise_or<ValueType>, Rhs>;
template<typename Expr>
using lhs_t = typename Expr::_lhs_t;
template<typename Expr>
using rhs_t = typename Expr::_rhs_t;
} }
#endif #endif

View File

@ -51,22 +51,22 @@ namespace sqlpp
template<typename... Tables> template<typename... Tables>
struct extra_tables_t struct extra_tables_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_extra_tables>; using _traits = make_traits<no_value_t, tag::is_extra_tables>;
struct _recursive_traits struct _recursive_traits
{ {
using _parameters = std::tuple<>; using _parameters = std::tuple<>;
using _required_tables = ::sqlpp::detail::type_set<>; using _required_tables = detail::type_set<>;
using _provided_outer_tables = ::sqlpp::detail::type_set<>; using _provided_outer_tables = detail::type_set<>;
using _provided_tables = ::sqlpp::detail::type_set<>; using _provided_tables = detail::type_set<>;
using _extra_tables = ::sqlpp::detail::type_set<Tables...>; using _extra_tables = detail::type_set<Tables...>;
using _can_be_null = std::false_type; using _tags = detail::type_set<>;
}; };
// FIXME: extra_tables must not require tables! // FIXME: extra_tables must not require tables!
static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()"); static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()");
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in extra_tables()"); static_assert(not detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in extra_tables()");
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in extra_tables()"); static_assert(detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in extra_tables()");
// Data // Data
using _data_t = extra_tables_data_t<Tables...>; using _data_t = extra_tables_data_t<Tables...>;
@ -106,7 +106,7 @@ namespace sqlpp
// NO EXTRA TABLES YET // NO EXTRA TABLES YET
struct no_extra_tables_t struct no_extra_tables_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -140,15 +140,15 @@ namespace sqlpp
struct _methods_t struct _methods_t
{ {
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_extra_tables_t, T>; using _new_statement_t = new_statement<Policies, no_extra_tables_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename... Args> template<typename... Args>
auto extra_tables(Args...) auto extra_tables(Args...) const
-> _new_statement_t<extra_tables_t<Args...>> -> _new_statement_t<extra_tables_t<Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), extra_tables_data_t<Args...>{} }; return { static_cast<const derived_statement_t<Policies>&>(*this), extra_tables_data_t<Args...>{} };
} }
}; };
}; };

View File

@ -38,32 +38,39 @@ namespace sqlpp
// floating_point value type // floating_point value type
struct floating_point struct floating_point
{ {
using _traits = make_traits<floating_point, ::sqlpp::tag::is_floating_point, ::sqlpp::tag::is_value_type>; using _traits = make_traits<floating_point, tag::is_value_type>;
using _tag = ::sqlpp::tag::is_floating_point; using _tag = tag::is_floating_point;
using _cpp_value_type = double; using _cpp_value_type = double;
struct _parameter_t template<typename T>
using _is_valid_operand = is_numeric_t<T>;
};
// floating_point parameter type
template<>
struct parameter_value_t<floating_point>
{ {
using _value_type = floating_point; using _value_type = floating_point;
using _cpp_value_type = typename _value_type::_cpp_value_type;
_parameter_t(): parameter_value_t():
_value(0), _value(0),
_is_null(true) _is_null(true)
{} {}
_parameter_t(const _cpp_value_type& value): parameter_value_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(false) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) parameter_value_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = false; _is_null = false;
return *this; return *this;
} }
_parameter_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t) parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
{ {
if (t._is_trivial()) if (t._is_trivial())
{ {
@ -78,7 +85,7 @@ namespace sqlpp
return *this; return *this;
} }
_parameter_t& operator=(const std::nullptr_t&) parameter_value_t& operator=(const std::nullptr_t&)
{ {
_value = 0; _value = 0;
_is_null = true; _is_null = true;
@ -108,104 +115,103 @@ namespace sqlpp
bool _is_null; bool _is_null;
}; };
template<typename T> // floating_point expression operators
struct _is_valid_operand template<typename Expr>
{ struct expression_operators<Expr, floating_point>:
static constexpr bool value = public basic_expression_operators<Expr, floating_point>
is_expression_t<T>::value // expressions are OK
and is_numeric_t<T>::value // the correct value type is required, of course
;
};
template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
{ {
template<typename T> template<typename T>
plus_t<Base, floating_point, wrap_operand_t<T>> operator +(T t) const using _is_valid_operand = is_valid_operand<floating_point, T>;
template<typename T>
plus_t<Expr, floating_point, wrap_operand_t<T>> operator +(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Expr*>(this), rhs{t} };
} }
template<typename T> template<typename T>
minus_t<Base, floating_point, wrap_operand_t<T>> operator -(T t) const minus_t<Expr, floating_point, wrap_operand_t<T>> operator -(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Expr*>(this), rhs{t} };
} }
template<typename T> template<typename T>
multiplies_t<Base, floating_point, wrap_operand_t<T>> operator *(T t) const multiplies_t<Expr, floating_point, wrap_operand_t<T>> operator *(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Expr*>(this), rhs{t} };
} }
template<typename T> template<typename T>
divides_t<Base, wrap_operand_t<T>> operator /(T t) const divides_t<Expr, wrap_operand_t<T>> operator /(T t) const
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Expr*>(this), rhs{t} };
} }
unary_plus_t<floating_point, Base> operator +() const unary_plus_t<floating_point, Expr> operator +() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Expr*>(this) };
} }
unary_minus_t<floating_point, Base> operator -() const unary_minus_t<floating_point, Expr> operator -() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Expr*>(this) };
} }
}; };
template<typename Base> // floating_point column operators
struct column_operators template<typename Column>
{ struct column_operators<Column, floating_point>
template<typename T> {
auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, floating_point, wrap_operand_t<T>>> template<typename T>
{ using _is_valid_operand = is_valid_operand<floating_point, T>;
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; template<typename T>
} auto operator +=(T t) const -> assignment_t<Column, plus_t<Column, floating_point, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
template<typename T> return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, floating_point, wrap_operand_t<T>>> }
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; template<typename T>
} auto operator -=(T t) const -> assignment_t<Column, minus_t<Column, floating_point, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
template<typename T> return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>> }
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; template<typename T>
} auto operator /=(T t) const -> assignment_t<Column, divides_t<Column, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
template<typename T> return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, floating_point, wrap_operand_t<T>>> }
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; template<typename T>
} auto operator *=(T t) const -> assignment_t<Column, multiplies_t<Column, floating_point, wrap_operand_t<T>>>
}; {
}; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
}
};
// floating_point result field
template<typename Db, typename FieldSpec> template<typename Db, typename FieldSpec>
struct result_field_t<floating_point, Db, FieldSpec>: public result_field_methods_t<result_field_t<floating_point, Db, FieldSpec>> struct result_field_t<floating_point, Db, FieldSpec>: public result_field_methods_t<result_field_t<floating_point, Db, FieldSpec>>
{ {

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Tables> template<typename Database, typename... Tables>
struct from_t struct from_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_from>; using _traits = make_traits<no_value_t, tag::is_from>;
using _recursive_traits = make_recursive_traits<Tables...>; using _recursive_traits = make_recursive_traits<Tables...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -79,7 +79,7 @@ namespace sqlpp
using _known_table_names = detail::transform_set_t<name_of, _known_tables>; using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
static_assert(not detail::is_element_of<typename Table::_name_t, _known_table_names>::value, "Must not use the same table name twice in from()"); static_assert(not detail::is_element_of<typename Table::_name_t, _known_table_names>::value, "Must not use the same table name twice in from()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>; using ok = detail::all_t<_is_dynamic::value, is_table_t<Table>::value>;
_add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
} }
@ -125,7 +125,7 @@ namespace sqlpp
struct no_from_t struct no_from_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -161,12 +161,12 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_from_t, T>; using _new_statement_t = new_statement<Policies, no_from_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename... Tables> template<typename... Tables>
auto from(Tables... tables) auto from(Tables... tables) const
-> _new_statement_t<from_t<void, Tables...>> -> _new_statement_t<from_t<void, Tables...>>
{ {
static_assert(sizeof...(Tables), "at least one table or join argument required in from()"); static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
@ -174,7 +174,7 @@ namespace sqlpp
} }
template<typename... Tables> template<typename... Tables>
auto dynamic_from(Tables... tables) auto dynamic_from(Tables... tables) const
-> _new_statement_t<from_t<_database_t, Tables...>> -> _new_statement_t<from_t<_database_t, Tables...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
@ -183,10 +183,10 @@ namespace sqlpp
private: private:
template<typename Database, typename... Tables> template<typename Database, typename... Tables>
auto _from_impl(Tables... tables) auto _from_impl(Tables... tables) const
-> _new_statement_t<from_t<Database, Tables...>> -> _new_statement_t<from_t<Database, Tables...>>
{ {
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in from()"); static_assert(detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in from()");
static_assert(required_tables_of<from_t<Database, Tables...>>::size::value == 0, "at least one table depends on another table"); static_assert(required_tables_of<from_t<Database, Tables...>>::size::value == 0, "at least one table depends on another table");
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...); static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
@ -195,7 +195,7 @@ namespace sqlpp
static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()"); static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()");
static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()"); static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()");
return { *static_cast<typename Policies::_statement_t*>(this), from_data_t<Database, Tables...>{tables...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), from_data_t<Database, Tables...>{tables...} };
} }
}; };

View File

@ -41,8 +41,10 @@
#include <sqlpp11/max.h> #include <sqlpp11/max.h>
#include <sqlpp11/avg.h> #include <sqlpp11/avg.h>
#include <sqlpp11/sum.h> #include <sqlpp11/sum.h>
#include <sqlpp11/verbatim_table.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/value_or_null.h> #include <sqlpp11/value_or_null.h>
#include <sqlpp11/eval.h>
namespace sqlpp namespace sqlpp
{ {
@ -53,44 +55,6 @@ namespace sqlpp
return { t }; return { t };
} }
template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim
struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>,
public alias_operators<verbatim_t<ValueType>>
{
using _traits = make_traits<ValueType, ::sqlpp::tag::is_expression>;
struct _recursive_traits : public make_recursive_traits<>
{
using _can_be_null = std::true_type; // since we do not know what's going on inside the verbatim, we assume it can be null
};
verbatim_t(std::string verbatim): _verbatim(verbatim) {}
verbatim_t(const verbatim_t&) = default;
verbatim_t(verbatim_t&&) = default;
verbatim_t& operator=(const verbatim_t&) = default;
verbatim_t& operator=(verbatim_t&&) = default;
~verbatim_t() = default;
std::string _verbatim;
};
template<typename Context, typename ValueType>
struct serializer_t<Context, verbatim_t<ValueType>>
{
using T = verbatim_t<ValueType>;
static Context& _(const T& t, Context& context)
{
context << t._verbatim;
return context;
}
};
template<typename ValueType, typename StringType>
auto verbatim(StringType s) -> verbatim_t<ValueType>
{
return { s };
}
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>>
{ {
@ -115,7 +79,7 @@ namespace sqlpp
template<typename Container> template<typename Container>
struct value_list_t // to be used in .in() method struct value_list_t // to be used in .in() method
{ {
using _traits = make_traits<value_type_t<typename Container::value_type>, ::sqlpp::tag::is_expression>; using _traits = make_traits<value_type_t<typename Container::value_type>, tag::is_expression>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _container_t = Container; using _container_t = Container;

View File

@ -59,16 +59,16 @@ namespace sqlpp
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct group_by_t struct group_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_group_by>; using _traits = make_traits<no_value_t, tag::is_group_by>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()"); static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()"); static_assert(detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()");
// Data // Data
using _data_t = group_by_data_t<Database, Expressions...>; using _data_t = group_by_data_t<Database, Expressions...>;
@ -90,7 +90,7 @@ namespace sqlpp
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, "expression uses tables unknown to this statement in group_by::add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in group_by::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = detail::all_t<_is_dynamic::value, is_expression_t<Expression>::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
} }
@ -135,7 +135,7 @@ namespace sqlpp
// NO GROUP BY YET // NO GROUP BY YET
struct no_group_by_t struct no_group_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -170,23 +170,23 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_group_by_t, T>; using _new_statement_t = new_statement<Policies, no_group_by_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename... Args> template<typename... Args>
auto group_by(Args... args) auto group_by(Args... args) const
-> _new_statement_t<group_by_t<void, Args...>> -> _new_statement_t<group_by_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), group_by_data_t<void, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), group_by_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
auto dynamic_group_by(Args... args) auto dynamic_group_by(Args... args) const
-> _new_statement_t<group_by_t<_database_t, Args...>> -> _new_statement_t<group_by_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), group_by_data_t<_database_t, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), group_by_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };

View File

@ -58,13 +58,13 @@ namespace sqlpp
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct having_t struct having_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_having>; using _traits = make_traits<no_value_t, tag::is_having>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()"); static_assert(detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()");
// Data // Data
using _data_t = having_data_t<Database, Expressions...>; using _data_t = having_data_t<Database, Expressions...>;
@ -86,7 +86,7 @@ namespace sqlpp
static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in having::add()"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in having::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = detail::all_t<_is_dynamic::value, is_expression_t<Expression>::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
} }
@ -133,7 +133,7 @@ namespace sqlpp
// NO HAVING YET // NO HAVING YET
struct no_having_t struct no_having_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -168,23 +168,23 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_having_t, T>; using _new_statement_t = new_statement<Policies, no_having_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename... Args> template<typename... Args>
auto having(Args... args) auto having(Args... args) const
-> _new_statement_t<having_t<void, Args...>> -> _new_statement_t<having_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), having_data_t<void, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), having_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
auto dynamic_having(Args... args) auto dynamic_having(Args... args) const
-> _new_statement_t<having_t<_database_t, Args...>> -> _new_statement_t<having_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), having_data_t<_database_t, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), having_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };

View File

@ -35,10 +35,11 @@
namespace sqlpp namespace sqlpp
{ {
template<bool NotInverted, typename Operand, typename... Args> template<bool NotInverted, typename Operand, typename... Args>
struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>, struct in_t:
public alias_operators<in_t<NotInverted, Operand, Args...>> public expression_operators<in_t<NotInverted, Operand, Args...>, boolean>,
public alias_operators<in_t<NotInverted, Operand, Args...>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand, Args...>; using _recursive_traits = make_recursive_traits<Operand, Args...>;
static constexpr bool _inverted = not NotInverted; static constexpr bool _inverted = not NotInverted;
@ -78,7 +79,11 @@ namespace sqlpp
{ {
serialize(t._operand, context); serialize(t._operand, context);
context << (t._inverted ? " NOT IN(" : " IN("); context << (t._inverted ? " NOT IN(" : " IN(");
interpret_tuple(t._args, ',', context); if (sizeof...(Args) == 1)
serialize(std::get<0>(t._args), context); // FIXME: this is a bit of a hack until there is a better overall strategy for using braces
// see https://github.com/rbock/sqlpp11/issues/18
else
interpret_tuple(t._args, ',', context);
context << ')'; context << ')';
return context; return context;
} }

View File

@ -28,6 +28,7 @@
#define SQLPP_INSERT_H #define SQLPP_INSERT_H
#include <sqlpp11/statement.h> #include <sqlpp11/statement.h>
#include <sqlpp11/connection.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_insert.h> #include <sqlpp11/prepared_insert.h>
@ -48,7 +49,7 @@ namespace sqlpp
template<typename Policies> template<typename Policies>
struct _result_methods_t struct _result_methods_t
{ {
using _statement_t = typename Policies::_statement_t; using _statement_t = derived_statement_t<Policies>;
const _statement_t& _get_statement() const const _statement_t& _get_statement() const
{ {
@ -111,6 +112,7 @@ namespace sqlpp
constexpr auto dynamic_insert(const Database&) constexpr auto dynamic_insert(const Database&)
-> decltype(blank_insert_t<Database>()) -> decltype(blank_insert_t<Database>())
{ {
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
return { blank_insert_t<Database>() }; return { blank_insert_t<Database>() };
} }
@ -118,6 +120,7 @@ namespace sqlpp
constexpr auto dynamic_insert_into(const Database&, Table table) constexpr auto dynamic_insert_into(const Database&, Table table)
-> decltype(blank_insert_t<Database>().into(table)) -> decltype(blank_insert_t<Database>().into(table))
{ {
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
return { blank_insert_t<Database>().into(table) }; return { blank_insert_t<Database>().into(table) };
} }
} }

View File

@ -49,7 +49,7 @@ namespace sqlpp
{ {
struct type struct type
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
}; };
}; };
@ -62,7 +62,7 @@ namespace sqlpp
using _column_t = Column; using _column_t = Column;
static constexpr bool _trivial_value_is_null = trivial_value_is_null_t<Column>::value; static constexpr bool _trivial_value_is_null = trivial_value_is_null_t<Column>::value;
using _pure_value_t = typename value_type_of<Column>::_cpp_value_type; using _pure_value_t = typename value_type_of<Column>::_cpp_value_type;
using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type; using _wrapped_value_t = wrap_operand_t<_pure_value_t>;
using _tvin_t = tvin_t<_wrapped_value_t>; using _tvin_t = tvin_t<_wrapped_value_t>;
insert_value_t(rhs_wrap_t<_wrapped_value_t, _trivial_value_is_null> rhs): insert_value_t(rhs_wrap_t<_wrapped_value_t, _trivial_value_is_null> rhs):

View File

@ -35,6 +35,7 @@
#include <sqlpp11/insert_value.h> #include <sqlpp11/insert_value.h>
#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>
namespace sqlpp namespace sqlpp
{ {
@ -105,7 +106,7 @@ namespace sqlpp
insert_list_data_t(Assignments... assignments): insert_list_data_t(Assignments... assignments):
_assignments(assignments...), _assignments(assignments...),
_columns({assignments._lhs}...), _columns({assignments._lhs}...),
_values({assignments._rhs}...) _values(assignments._rhs...)
{} {}
insert_list_data_t(const insert_list_data_t&) = default; insert_list_data_t(const insert_list_data_t&) = default;
@ -115,8 +116,8 @@ namespace sqlpp
~insert_list_data_t() = default; ~insert_list_data_t() = default;
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments) std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
std::tuple<simple_column_t<typename Assignments::_lhs_t>...> _columns; std::tuple<simple_column_t<lhs_t<Assignments>>...> _columns;
std::tuple<typename Assignments::_rhs_t...> _values; std::tuple<rhs_t<Assignments>...> _values;
interpretable_list_t<Database> _dynamic_columns; interpretable_list_t<Database> _dynamic_columns;
interpretable_list_t<Database> _dynamic_values; interpretable_list_t<Database> _dynamic_values;
}; };
@ -124,8 +125,8 @@ namespace sqlpp
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
struct insert_list_t struct insert_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_insert_list>; using _traits = make_traits<no_value_t, tag::is_insert_list>;
using _recursive_traits = make_recursive_traits<typename Assignments::_lhs_t..., typename Assignments::_rhs_t...>; using _recursive_traits = make_recursive_traits<lhs_t<Assignments>..., rhs_t<Assignments>...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -152,12 +153,12 @@ namespace sqlpp
{ {
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()");
static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments"); static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_t...>; using _assigned_columns = detail::make_type_set_t<lhs_t<Assignments>...>;
static_assert(not detail::is_element_of<typename Assignment::_lhs_t, _assigned_columns>::value, "Must not assign value to column twice"); static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(not must_not_insert_t<typename Assignment::_lhs_t>::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, "add() contains a column from a foreign table"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table");
using ok = ::sqlpp::detail::all_t< using ok = detail::all_t<
_is_dynamic::value, _is_dynamic::value,
is_assignment_t<Assignment>::value>; is_assignment_t<Assignment>::value>;
@ -168,7 +169,7 @@ namespace sqlpp
template<typename Assignment> template<typename Assignment>
void _add_impl(Assignment assignment, const std::true_type&) void _add_impl(Assignment assignment, const std::true_type&)
{ {
_data._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_lhs_t>{assignment._lhs}); _data._dynamic_columns.emplace_back(simple_column_t<lhs_t<Assignment>>{assignment._lhs});
_data._dynamic_values.emplace_back(assignment._rhs); _data._dynamic_values.emplace_back(assignment._rhs);
} }
@ -225,7 +226,7 @@ namespace sqlpp
template<typename... Columns> template<typename... Columns>
struct column_list_t struct column_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_column_list>; using _traits = make_traits<no_value_t, tag::is_column_list>;
using _recursive_traits = make_recursive_traits<Columns...>; using _recursive_traits = make_recursive_traits<Columns...>;
using _value_tuple_t = typename column_list_data_t<Columns...>::_value_tuple_t; using _value_tuple_t = typename column_list_data_t<Columns...>::_value_tuple_t;
@ -241,13 +242,13 @@ namespace sqlpp
template<typename... Assignments> template<typename... Assignments>
void add(Assignments... assignments) void add(Assignments... assignments)
{ {
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments"); static_assert(detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments");
using _arg_value_tuple = std::tuple<insert_value_t<typename Assignments::_lhs_t>...>; using _arg_value_tuple = std::tuple<insert_value_t<lhs_t<Assignments>>...>;
using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>; using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>;
static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments"); static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments");
using ok = ::sqlpp::detail::all_t< using ok = detail::all_t<
::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, detail::all_t<is_assignment_t<Assignments>::value...>::value,
_args_correct::value>; _args_correct::value>;
_add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert _add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
@ -257,7 +258,7 @@ namespace sqlpp
template<typename... Assignments> template<typename... Assignments>
void _add_impl(const std::true_type&, Assignments... assignments) void _add_impl(const std::true_type&, Assignments... assignments)
{ {
return _data._insert_values.emplace_back(insert_value_t<typename Assignments::_lhs_t>{assignments._rhs}...); return _data._insert_values.emplace_back(insert_value_t<lhs_t<Assignments>>{assignments._rhs}...);
} }
template<typename... Assignments> template<typename... Assignments>
@ -294,7 +295,7 @@ namespace sqlpp
// NO INSERT COLUMNS/VALUES YET // NO INSERT COLUMNS/VALUES YET
struct no_insert_value_list_t struct no_insert_value_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -329,28 +330,28 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_insert_value_list_t, T>; using _new_statement_t = new_statement<Policies, no_insert_value_list_t, T>;
static void _check_consistency() static void _check_consistency()
{ {
static_assert(wrong_t<_methods_t>::value, "insert values required, e.g. set(...) or default_values()"); static_assert(wrong_t<_methods_t>::value, "insert values required, e.g. set(...) or default_values()");
} }
auto default_values() auto default_values() const
-> _new_statement_t<insert_default_values_t> -> _new_statement_t<insert_default_values_t>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), insert_default_values_data_t{} }; return { static_cast<const derived_statement_t<Policies>&>(*this), insert_default_values_data_t{} };
} }
template<typename... Columns> template<typename... Columns>
auto columns(Columns... columns) auto columns(Columns... columns) const
-> _new_statement_t<column_list_t<Columns...>> -> _new_statement_t<column_list_t<Columns...>>
{ {
static_assert(sizeof...(Columns), "at least one column required in columns()"); static_assert(sizeof...(Columns), "at least one column required in columns()");
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected in columns()"); static_assert(not detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected in columns()");
static_assert(::sqlpp::detail::all_t<is_column_t<Columns>::value...>::value, "at least one argument is not a column in columns()"); static_assert(detail::all_t<is_column_t<Columns>::value...>::value, "at least one argument is not a column in columns()");
static_assert(::sqlpp::detail::none_t<must_not_insert_t<Columns>::value...>::value, "at least one column argument has a must_not_insert tag in its definition"); static_assert(detail::none_t<must_not_insert_t<Columns>::value...>::value, "at least one column argument has a must_not_insert tag in its definition");
using _column_required_tables = ::sqlpp::detail::make_joined_set_t<required_tables_of<Columns>...>; using _column_required_tables = detail::make_joined_set_t<required_tables_of<Columns>...>;
static_assert(_column_required_tables::size::value == 1, "columns() contains columns from several tables"); static_assert(_column_required_tables::size::value == 1, "columns() contains columns from several tables");
using _table = typename detail::first_arg_t<Columns...>::_table; using _table = typename detail::first_arg_t<Columns...>::_table;
@ -358,43 +359,43 @@ namespace sqlpp
using set_columns = detail::make_type_set_t<Columns...>; using set_columns = detail::make_type_set_t<Columns...>;
static_assert(detail::is_subset_of<required_columns, set_columns>::value, "At least one required column is missing in columns()"); static_assert(detail::is_subset_of<required_columns, set_columns>::value, "At least one required column is missing in columns()");
return { *static_cast<typename Policies::_statement_t*>(this), column_list_data_t<Columns...>{columns...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), column_list_data_t<Columns...>{columns...} };
} }
template<typename... Assignments> template<typename... Assignments>
auto set(Assignments... assignments) auto set(Assignments... assignments) const
-> _new_statement_t<insert_list_t<void, Assignments...>> -> _new_statement_t<insert_list_t<void, Assignments...>>
{ {
static_assert(sizeof...(Assignments), "at least one assignment expression required in set()"); static_assert(sizeof...(Assignments), "at least one assignment expression required in set()");
static_assert(sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()"); static_assert(detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()");
using _table = typename detail::first_arg_t<Assignments...>::_lhs_t::_table; using _table = typename lhs_t<detail::first_arg_t<Assignments...>>::_table;
using required_columns = typename _table::_required_insert_columns; using required_columns = typename _table::_required_insert_columns;
using columns = detail::make_type_set_t<typename Assignments::_lhs_t...>; using columns = detail::make_type_set_t<lhs_t<Assignments>...>;
static_assert(detail::is_subset_of<required_columns, columns>::value, "At least one required column is missing in set()"); static_assert(detail::is_subset_of<required_columns, columns>::value, "At least one required column is missing in set()");
return _set_impl<void>(assignments...); return _set_impl<void>(assignments...);
} }
template<typename... Assignments> template<typename... Assignments>
auto dynamic_set(Assignments... assignments) auto dynamic_set(Assignments... assignments) const
-> _new_statement_t<insert_list_t<_database_t, Assignments...>> -> _new_statement_t<insert_list_t<_database_t, Assignments...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement");
static_assert(detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()");
return _set_impl<_database_t>(assignments...); return _set_impl<_database_t>(assignments...);
} }
private: private:
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
auto _set_impl(Assignments... assignments) auto _set_impl(Assignments... assignments) const
-> _new_statement_t<insert_list_t<Database, Assignments...>> -> _new_statement_t<insert_list_t<Database, Assignments...>>
{ {
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()"); static_assert(not detail::has_duplicates<lhs_t<Assignments>...>::value, "at least one duplicate column detected in set()");
static_assert(sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()"); static_assert(detail::none_t<must_not_insert_t<lhs_t<Assignments>>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
static_assert(sqlpp::detail::none_t<must_not_insert_t<typename Assignments::_lhs_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
using _column_required_tables = ::sqlpp::detail::make_joined_set_t<required_tables_of<typename Assignments::_lhs_t>...>; using _column_required_tables = detail::make_joined_set_t<required_tables_of<lhs_t<Assignments>>...>;
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from several tables"); static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from several tables");
return { *static_cast<typename Policies::_statement_t*>(this), insert_list_data_t<Database, Assignments...>{assignments...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), insert_list_data_t<Database, Assignments...>{assignments...} };
} }
}; };
}; };

View File

@ -40,204 +40,209 @@ namespace sqlpp
// integral value type // integral value type
struct integral struct integral
{ {
using _traits = make_traits<integral, ::sqlpp::tag::is_integral, ::sqlpp::tag::is_value_type>; using _traits = make_traits<integral, tag::is_value_type>;
using _tag = ::sqlpp::tag::is_integral; using _tag = tag::is_integral;
using _cpp_value_type = int64_t; using _cpp_value_type = int64_t;
struct _parameter_t template<typename T>
using _is_valid_operand = is_numeric_t<T>;
};
// integral parameter value
template<>
struct parameter_value_t<integral>
{
using _value_type = integral;
using _cpp_value_type = typename _value_type::_cpp_value_type;
parameter_value_t():
_value(0),
_is_null(true)
{}
explicit parameter_value_t(const _cpp_value_type& value):
_value(value),
_is_null(false)
{}
parameter_value_t& operator=(const _cpp_value_type& value)
{ {
using _value_type = integral; _value = value;
_is_null = false;
return *this;
}
_parameter_t(): parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
_value(0), {
_is_null(true) if (t._is_trivial())
{}
explicit _parameter_t(const _cpp_value_type& value):
_value(value),
_is_null(false)
{}
_parameter_t& operator=(const _cpp_value_type& value)
{
_value = value;
_is_null = false;
return *this;
}
_parameter_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
{
if (t._is_trivial())
{
_value = 0;
_is_null = true;
}
else
{
_value = t._value._t;
_is_null = false;
}
return *this;
}
void set_null()
{ {
_value = 0; _value = 0;
_is_null = true; _is_null = true;
} }
else
bool is_null() const
{ {
return _is_null; _value = t._value._t;
_is_null = false;
} }
return *this;
}
const _cpp_value_type& value() const void set_null()
{
return _value;
}
operator _cpp_value_type() const { return _value; }
template<typename Target>
void _bind(Target& target, size_t index) const
{
target._bind_integral_parameter(index, &_value, _is_null);
}
private:
_cpp_value_type _value;
bool _is_null;
};
template<typename T>
struct _is_valid_operand
{
static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_numeric_t<T>::value // the correct value type is required, of course
;
};
template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
{ {
template<typename T> _value = 0;
plus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator +(T t) const _is_null = true;
{ }
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; bool is_null() const
} {
return _is_null;
}
template<typename T> const _cpp_value_type& value() const
minus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator -(T t) const {
{ return _value;
using rhs = wrap_operand_t<T>; }
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; operator _cpp_value_type() const { return _value; }
}
template<typename T> template<typename Target>
multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>> operator *(T t) const void _bind(Target& target, size_t index) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
divides_t<Base, wrap_operand_t<T>> operator /(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
modulus_t<Base, wrap_operand_t<T>> operator %(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
unary_plus_t<integral, Base> operator +() const
{ {
return { *static_cast<const Base*>(this) }; target._bind_integral_parameter(index, &_value, _is_null);
} }
unary_minus_t<integral, Base> operator -() const private:
{ _cpp_value_type _value;
return { *static_cast<const Base*>(this) }; bool _is_null;
}
template<typename T>
bitwise_and_t<Base, value_type_t<T>, wrap_operand_t<T>> operator &(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
bitwise_or_t<Base, value_type_t<T>, wrap_operand_t<T>> operator |(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
};
template<typename Base>
struct column_operators
{
template<typename T>
auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
template<typename T>
auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
template<typename T>
auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
template<typename T>
auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
};
}; };
// integral expression operators
template<typename Base>
struct expression_operators<Base, integral>: public basic_expression_operators<Base, integral>
{
template<typename T>
using _is_valid_operand = is_valid_operand<integral, T>;
template<typename T>
plus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator +(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
minus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator -(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>> operator *(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
divides_t<Base, wrap_operand_t<T>> operator /(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
modulus_t<Base, wrap_operand_t<T>> operator %(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
unary_plus_t<integral, Base> operator +() const
{
return { *static_cast<const Base*>(this) };
}
unary_minus_t<integral, Base> operator -() const
{
return { *static_cast<const Base*>(this) };
}
template<typename T>
bitwise_and_t<Base, value_type_t<T>, wrap_operand_t<T>> operator &(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
bitwise_or_t<Base, value_type_t<T>, wrap_operand_t<T>> operator |(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
};
// integral column operators
template<typename Base>
struct column_operators<Base, integral>
{
template<typename T>
using _is_valid_operand = is_valid_operand<integral, T>;
template<typename T>
auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
}
template<typename T>
auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
}
template<typename T>
auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
}
template<typename T>
auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
}
};
// integral result field
template<typename Db, typename FieldSpec> template<typename Db, typename FieldSpec>
struct result_field_t<integral, Db, FieldSpec>: public result_field_methods_t<result_field_t<integral, Db, FieldSpec>> struct result_field_t<integral, Db, FieldSpec>: public result_field_methods_t<result_field_t<integral, Db, FieldSpec>>
{ {
@ -308,6 +313,7 @@ namespace sqlpp
_cpp_value_type _value; _cpp_value_type _value;
}; };
// ostream operator for integral result field
template<typename Db, typename FieldSpec> template<typename Db, typename FieldSpec>
inline std::ostream& operator<<(std::ostream& os, const result_field_t<integral, Db, FieldSpec>& e) inline std::ostream& operator<<(std::ostream& os, const result_field_t<integral, Db, FieldSpec>& e)
{ {

View File

@ -47,7 +47,7 @@ namespace sqlpp
} }
template<typename Tuple, typename Separator, typename Context, size_t... Is> template<typename Tuple, typename Separator, typename Context, size_t... Is>
auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const ::sqlpp::detail::index_sequence<Is...>&) auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const detail::index_sequence<Is...>&)
-> Context& -> Context&
{ {
// Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4. // Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4.
@ -63,7 +63,7 @@ namespace sqlpp
auto interpret_tuple(const Tuple& t, const Separator& separator, Context& context) auto interpret_tuple(const Tuple& t, const Separator& separator, Context& context)
-> Context& -> Context&
{ {
return interpret_tuple_impl(t, separator, context, ::sqlpp::detail::make_index_sequence<std::tuple_size<Tuple>::value>{}); return interpret_tuple_impl(t, separator, context, detail::make_index_sequence<std::tuple_size<Tuple>::value>{});
} }
} }

View File

@ -52,16 +52,16 @@ namespace sqlpp
interpretable_t& operator=(interpretable_t&&) = default; interpretable_t& operator=(interpretable_t&&) = default;
~interpretable_t() = default; ~interpretable_t() = default;
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const serializer_context_t& serialize(serializer_context_t& context) const
{ {
return _impl->serialize(context); return _impl->serialize(context);
} }
// This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same // This method only exists if Db::_serializer_context_t and serializer_context_t are not the same
template<typename Context> template<typename Context>
auto serialize(Context& context) const auto serialize(Context& context) const
-> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value -> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value
and not std::is_same<Context, sqlpp::serializer_context_t>::value, Context&>::type and not std::is_same<Context, serializer_context_t>::value, Context&>::type
{ {
return _impl->db_serialize(context); return _impl->db_serialize(context);
} }
@ -74,7 +74,7 @@ namespace sqlpp
private: private:
struct _impl_base struct _impl_base
{ {
virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0; virtual serializer_context_t& serialize(serializer_context_t& context) const = 0;
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0; virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0; virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
}; };
@ -87,9 +87,9 @@ namespace sqlpp
_t(t) _t(t)
{} {}
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const serializer_context_t& serialize(serializer_context_t& context) const
{ {
sqlpp::serialize(_t, context); ::sqlpp::serialize(_t, context);
return context; return context;
} }

View File

@ -84,8 +84,8 @@ namespace sqlpp
if (not first) if (not first)
{ {
context << separator; context << separator;
first = false;
} }
first = false;
serialize(entry, context); serialize(entry, context);
} }
return context; return context;

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<typename Database, typename Table> template<typename Database, typename Table>
struct into_t struct into_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_into>; using _traits = make_traits<no_value_t, tag::is_into>;
using _recursive_traits = make_recursive_traits<Table>; using _recursive_traits = make_recursive_traits<Table>;
static_assert(is_table_t<Table>::value, "argument has to be a table"); static_assert(is_table_t<Table>::value, "argument has to be a table");
@ -103,7 +103,7 @@ namespace sqlpp
// NO INTO YET // NO INTO YET
struct no_into_t struct no_into_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -138,7 +138,7 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_into_t, T>; using _new_statement_t = new_statement<Policies, no_into_t, T>;
static void _check_consistency() static void _check_consistency()
{ {
@ -146,10 +146,10 @@ namespace sqlpp
} }
template<typename... Args> template<typename... Args>
auto into(Args... args) auto into(Args... args) const
-> _new_statement_t<into_t<void, Args...>> -> _new_statement_t<into_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), into_data_t<void, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), into_data_t<void, Args...>{args...} };
} }
}; };
}; };

View File

@ -34,19 +34,15 @@
namespace sqlpp namespace sqlpp
{ {
template<bool NotInverted, typename Operand> template<bool NotInverted, typename Operand>
struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>, struct is_null_t:
public alias_operators<is_null_t<NotInverted, Operand>> public expression_operators<is_null_t<NotInverted, Operand>, boolean>,
public alias_operators<is_null_t<NotInverted, Operand>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand>; using _recursive_traits = make_recursive_traits<Operand>;
static constexpr bool _inverted = not NotInverted; static constexpr bool _inverted = not NotInverted;
struct _value_type: public boolean
{
using _is_named_expression = std::true_type;
};
struct _name_t struct _name_t
{ {
static constexpr const char* _get_name() { return _inverted ? "IS NOT NULL" : "IS NULL"; } static constexpr const char* _get_name() { return _inverted ? "IS NOT NULL" : "IS NULL"; }
@ -71,9 +67,9 @@ namespace sqlpp
}; };
template<typename Context, bool NotInverted, typename Operand> template<typename Context, bool NotInverted, typename Operand>
struct serializer_t<Context, ::sqlpp::is_null_t<NotInverted, Operand>> struct serializer_t<Context, is_null_t<NotInverted, Operand>>
{ {
using T = ::sqlpp::is_null_t<NotInverted, Operand>; using T = is_null_t<NotInverted, Operand>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {

View File

@ -73,7 +73,7 @@ namespace sqlpp
using _provided_outer_tables = typename JoinType::template _provided_outer_tables<Lhs, Rhs>; using _provided_outer_tables = typename JoinType::template _provided_outer_tables<Lhs, Rhs>;
using _extra_tables = detail::make_joined_set_t<extra_tables_of<Lhs>, extra_tables_of<Rhs>>; using _extra_tables = detail::make_joined_set_t<extra_tables_of<Lhs>, extra_tables_of<Rhs>>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Lhs>, parameters_of<Rhs>>; using _parameters = detail::make_parameter_tuple_t<parameters_of<Lhs>, parameters_of<Rhs>>;
using _can_be_null = std::false_type; using _tags = detail::type_set<>;
}; };
@ -82,7 +82,7 @@ namespace sqlpp
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join"); 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(is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
static_assert(::sqlpp::detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value, "joined tables must not be identical"); static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value, "joined tables must not be identical");
static_assert(_recursive_traits::_required_tables::size::value == 0, "joined tables must not depend on other tables"); static_assert(_recursive_traits::_required_tables::size::value == 0, "joined tables must not depend on other tables");
@ -94,6 +94,8 @@ namespace sqlpp
-> set_on_t<on_t<void, Expr...>> -> set_on_t<on_t<void, Expr...>>
{ {
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()"); static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
static_assert(detail::all_t<is_expression_t<Expr>::value...>::value, "at least one argument is not an expression in on()");
return { _lhs, return { _lhs,
_rhs, _rhs,
{std::tuple<Expr...>{expr...}} {std::tuple<Expr...>{expr...}}

View File

@ -34,15 +34,13 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Operand, typename Pattern> template<typename Operand, typename Pattern>
struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>, struct like_t:
public alias_operators<like_t<Operand, Pattern>> public expression_operators<like_t<Operand, Pattern>, boolean>,
public alias_operators<like_t<Operand, Pattern>>
{ {
using _traits = make_traits<boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand, Pattern>; using _recursive_traits = make_recursive_traits<Operand, Pattern>;
static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text");
static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text");
struct _name_t struct _name_t
{ {
static constexpr const char* _get_name() { return "LIKE"; } static constexpr const char* _get_name() { return "LIKE"; }
@ -50,6 +48,8 @@ namespace sqlpp
struct _member_t struct _member_t
{ {
T like; T like;
T& operator()() { return like; }
const T& operator()() const { return like; }
}; };
}; };

View File

@ -54,7 +54,7 @@ namespace sqlpp
template<typename Limit> template<typename Limit>
struct limit_t struct limit_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_limit>; using _traits = make_traits<no_value_t, tag::is_limit>;
using _recursive_traits = make_recursive_traits<Limit>; using _recursive_traits = make_recursive_traits<Limit>;
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter"); static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
@ -105,7 +105,7 @@ namespace sqlpp
template<typename Limit> template<typename Limit>
dynamic_limit_data_t(Limit value): dynamic_limit_data_t(Limit value):
_initialized(true), _initialized(true),
_value(typename wrap_operand<Limit>::type(value)) _value(wrap_operand_t<Limit>(value))
{ {
} }
@ -123,7 +123,7 @@ namespace sqlpp
template<typename Database> template<typename Database>
struct dynamic_limit_t struct dynamic_limit_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_limit>; using _traits = make_traits<no_value_t, tag::is_limit>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -137,7 +137,7 @@ namespace sqlpp
void set(Limit value) void set(Limit value)
{ {
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Limit>::type; using arg_t = wrap_operand_t<Limit>;
_data._value = arg_t{value}; _data._value = arg_t{value};
_data._initialized = true; _data._initialized = true;
} }
@ -172,7 +172,7 @@ namespace sqlpp
struct no_limit_t struct no_limit_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -207,22 +207,22 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_limit_t, T>; using _new_statement_t = new_statement<Policies, no_limit_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename Arg> template<typename Arg>
auto limit(Arg arg) auto limit(Arg arg) const
-> _new_statement_t<limit_t<typename wrap_operand<Arg>::type>> -> _new_statement_t<limit_t<wrap_operand_t<Arg>>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), limit_data_t<typename wrap_operand<Arg>::type>{{arg}} }; return { static_cast<const derived_statement_t<Policies>&>(*this), limit_data_t<wrap_operand_t<Arg>>{{arg}} };
} }
auto dynamic_limit() auto dynamic_limit() const
-> _new_statement_t<dynamic_limit_t<_database_t>> -> _new_statement_t<dynamic_limit_t<_database_t>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_limit_data_t<_database_t>{} }; return { static_cast<const derived_statement_t<Policies>&>(*this), dynamic_limit_data_t<_database_t>{} };
} }
}; };
}; };

View File

@ -32,13 +32,12 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Expr> template<typename Expr>
struct max_t: public value_type_of<Expr>::template expression_operators<max_t<Expr>>, struct max_t:
public alias_operators<max_t<Expr>> public expression_operators<max_t<Expr>, value_type_of<Expr>>,
public alias_operators<max_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr, aggregate_function>;
static_assert(is_expression_t<Expr>::value, "max() requires a value expression as argument");
struct _name_t struct _name_t
{ {
@ -82,7 +81,7 @@ namespace sqlpp
template<typename T> template<typename T>
auto max(T t) -> max_t<wrap_operand_t<T>> auto max(T t) -> max_t<wrap_operand_t<T>>
{ {
static_assert(is_expression_t<wrap_operand_t<T>>::value, "max() requires a value expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "max() requires an expression as argument");
return { t }; return { t };
} }

View File

@ -32,13 +32,12 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Expr> template<typename Expr>
struct min_t: public value_type_of<Expr>::template expression_operators<min_t<Expr>>, struct min_t:
public alias_operators<min_t<Expr>> public expression_operators<min_t<Expr>, value_type_of<Expr>>,
public alias_operators<min_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr, aggregate_function>;
static_assert(is_expression_t<Expr>::value, "min() requires a value expression as argument");
struct _name_t struct _name_t
{ {
@ -82,7 +81,7 @@ namespace sqlpp
template<typename T> template<typename T>
auto min(T t) -> min_t<wrap_operand_t<T>> auto min(T t) -> min_t<wrap_operand_t<T>>
{ {
static_assert(is_expression_t<wrap_operand_t<T>>::value, "min() requires a value expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "min() requires an expression as argument");
return { t }; return { t };
} }

View File

@ -44,7 +44,7 @@ namespace sqlpp
using _traits = make_traits<no_value_t>; using _traits = make_traits<no_value_t>;
using _recursive_traits = make_recursive_traits<Columns...>; using _recursive_traits = make_recursive_traits<Columns...>;
static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions"); static_assert(detail::all_t<is_selectable_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
multi_column_t(std::tuple<Columns...> columns): multi_column_t(std::tuple<Columns...> columns):
_columns(columns) _columns(columns)
@ -66,20 +66,16 @@ namespace sqlpp
return { *this }; return { *this };
} }
using _value_type = no_value_t;
using _is_multi_column = std::true_type;
std::tuple<Columns...> _columns; std::tuple<Columns...> _columns;
}; };
template<typename AliasProvider, typename... Columns> template<typename AliasProvider, typename... Columns>
struct multi_column_alias_t struct multi_column_alias_t
{ {
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_multi_column, tag::is_named_expression>; using _traits = make_traits<no_value_t, tag::is_alias, tag::is_multi_column, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Columns...>; using _recursive_traits = make_recursive_traits<Columns...>;
static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions"); static_assert(detail::all_t<is_selectable_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
using _name_t = typename AliasProvider::_name_t; using _name_t = typename AliasProvider::_name_t;
@ -101,12 +97,6 @@ namespace sqlpp
multi_column_alias_t& operator=(multi_column_alias_t&&) = default; multi_column_alias_t& operator=(multi_column_alias_t&&) = default;
~multi_column_alias_t() = default; ~multi_column_alias_t() = default;
struct _value_type: public no_value_t
{
using _is_named_expression = std::true_type;
};
using _is_multi_column = std::true_type;
std::tuple<Columns...> _columns; std::tuple<Columns...> _columns;
}; };

View File

@ -50,16 +50,16 @@ namespace sqlpp
named_interpretable_t& operator=(named_interpretable_t&&) = default; named_interpretable_t& operator=(named_interpretable_t&&) = default;
~named_interpretable_t() = default; ~named_interpretable_t() = default;
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const serializer_context_t& serialize(serializer_context_t& context) const
{ {
return _impl->serialize(context); return _impl->serialize(context);
} }
// This method only exists if Db::_serializer_context_t and sqlpp::serializer_context_t are not the same // This method only exists if Db::_serializer_context_t and serializer_context_t are not the same
template<typename Context> template<typename Context>
auto serialize(Context& context) const auto serialize(Context& context) const
-> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value -> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value
and not std::is_same<Context, sqlpp::serializer_context_t>::value, Context&>::type and not std::is_same<Context, serializer_context_t>::value, Context&>::type
{ {
return _impl->db_serialize(context); return _impl->db_serialize(context);
} }
@ -77,7 +77,7 @@ namespace sqlpp
private: private:
struct _impl_base struct _impl_base
{ {
virtual sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const = 0; virtual serializer_context_t& serialize(serializer_context_t& context) const = 0;
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0; virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0; virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
virtual std::string _get_name() const = 0; virtual std::string _get_name() const = 0;
@ -91,9 +91,9 @@ namespace sqlpp
_t(t) _t(t)
{} {}
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const serializer_context_t& serialize(serializer_context_t& context) const
{ {
sqlpp::serialize(_t, context); ::sqlpp::serialize(_t, context);
return context; return context;
} }

View File

@ -28,28 +28,24 @@
#define SQLPP_NO_VALUE_H #define SQLPP_NO_VALUE_H
#include <type_traits> #include <type_traits>
#include <sqlpp11/value_type_fwd.h>
namespace sqlpp namespace sqlpp
{ {
struct no_value_t struct no_value_t
{ {
using _tag = void; using _tag = void;
template<typename T>
struct _is_valid_operand
{
static constexpr bool value = false;
};
template<typename Base>
struct expression_operators
{
};
template<typename Base>
struct column_operators
{
};
}; };
template<typename Base>
struct expression_operators<Base, no_value_t>
{
};
template<typename Base>
struct column_operators<Base, no_value_t>
{
};
} }
#endif #endif

View File

@ -35,7 +35,7 @@ namespace sqlpp
{ {
struct noop struct noop
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
struct _name_t {}; struct _name_t {};

View File

@ -54,7 +54,7 @@ namespace sqlpp
template<typename Offset> template<typename Offset>
struct offset_t struct offset_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_offset>; using _traits = make_traits<no_value_t, tag::is_offset>;
using _recursive_traits = make_recursive_traits<Offset>; using _recursive_traits = make_recursive_traits<Offset>;
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter"); static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
@ -105,7 +105,7 @@ namespace sqlpp
template<typename Offset> template<typename Offset>
dynamic_offset_data_t(Offset value): dynamic_offset_data_t(Offset value):
_initialized(true), _initialized(true),
_value(typename wrap_operand<Offset>::type(value)) _value(wrap_operand_t<Offset>(value))
{ {
} }
@ -123,7 +123,7 @@ namespace sqlpp
template<typename Database> template<typename Database>
struct dynamic_offset_t struct dynamic_offset_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_offset>; using _traits = make_traits<no_value_t, tag::is_offset>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -137,7 +137,7 @@ namespace sqlpp
void set(Offset value) void set(Offset value)
{ {
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Offset>::type; using arg_t = wrap_operand_t<Offset>;
_data._value = arg_t{value}; _data._value = arg_t{value};
_data._initialized = true; _data._initialized = true;
} }
@ -171,9 +171,9 @@ namespace sqlpp
void set_offset(Offset value) void set_offset(Offset value)
{ {
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Offset>::type; using arg_t = wrap_operand_t<Offset>;
static_cast<typename Policies::_statement_t*>(this)->_offset()._value = arg_t{value}; static_cast<derived_statement_t<Policies>*>(this)->_offset()._value = arg_t{value};
static_cast<typename Policies::_statement_t*>(this)->_offset()._initialized = true; static_cast<derived_statement_t<Policies>*>(this)->_offset()._initialized = true;
} }
}; };
@ -183,7 +183,7 @@ namespace sqlpp
struct no_offset_t struct no_offset_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -218,22 +218,22 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_offset_t, T>; using _new_statement_t = new_statement<Policies, no_offset_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename Arg> template<typename Arg>
auto offset(Arg arg) auto offset(Arg arg) const
-> _new_statement_t<offset_t<typename wrap_operand<Arg>::type>> -> _new_statement_t<offset_t<wrap_operand_t<Arg>>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), offset_data_t<typename wrap_operand<Arg>::type>{{arg}} }; return { static_cast<const derived_statement_t<Policies>&>(*this), offset_data_t<wrap_operand_t<Arg>>{{arg}} };
} }
auto dynamic_offset() auto dynamic_offset() const
-> _new_statement_t<dynamic_offset_t<_database_t>> -> _new_statement_t<dynamic_offset_t<_database_t>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_offset_data_t<_database_t>{} }; return { static_cast<const derived_statement_t<Policies>&>(*this), dynamic_offset_data_t<_database_t>{} };
} }
}; };
}; };

View File

@ -43,7 +43,6 @@ namespace sqlpp
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()"); static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()");
static_assert(detail::all_t<is_expression_t<Expr>::value...>::value, "at least one argument is not an expression in on()");
template<typename E> template<typename E>
void add(E expr) void add(E expr)

View File

@ -59,16 +59,16 @@ namespace sqlpp
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct order_by_t struct order_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_order_by>; using _traits = make_traits<no_value_t, tag::is_order_by>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()"); static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()"); static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in order_by()"); static_assert(detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in order_by()");
// Data // Data
using _data_t = order_by_data_t<Database, Expressions...>; using _data_t = order_by_data_t<Database, Expressions...>;
@ -90,7 +90,7 @@ namespace sqlpp
static_assert(is_expression_t<Expression>::value, "invalid expression argument in order_by::add()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in order_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in order_by::add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in order_by::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = detail::all_t<_is_dynamic::value, is_expression_t<Expression>::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
} }
@ -135,7 +135,7 @@ namespace sqlpp
// NO ORDER BY YET // NO ORDER BY YET
struct no_order_by_t struct no_order_by_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -170,23 +170,23 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_order_by_t, T>; using _new_statement_t = new_statement<Policies, no_order_by_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename... Args> template<typename... Args>
auto order_by(Args... args) auto order_by(Args... args) const
-> _new_statement_t<order_by_t<void, Args...>> -> _new_statement_t<order_by_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), order_by_data_t<void, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), order_by_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
auto dynamic_order_by(Args... args) auto dynamic_order_by(Args... args) const
-> _new_statement_t<order_by_t<_database_t, Args...>> -> _new_statement_t<order_by_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), order_by_data_t<_database_t, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), order_by_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };

View File

@ -34,7 +34,8 @@
namespace sqlpp namespace sqlpp
{ {
template<typename ValueType, typename NameType> template<typename ValueType, typename NameType>
struct parameter_t: public ValueType::template expression_operators<parameter_t<ValueType, NameType>> struct parameter_t:
public expression_operators<parameter_t<ValueType, NameType>, ValueType>
{ {
using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>; using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>;
struct _recursive_traits struct _recursive_traits
@ -44,10 +45,10 @@ namespace sqlpp
using _provided_outer_tables = detail::type_set<>; using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<>; using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _can_be_null = std::true_type; using _tags = detail::type_set<tag::can_be_null>;
}; };
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>; using _instance_t = member_t<NameType, parameter_value_t<ValueType>>;
parameter_t() parameter_t()
{} {}
@ -75,7 +76,7 @@ namespace sqlpp
auto parameter(const NamedExpr&) auto parameter(const NamedExpr&)
-> parameter_t<value_type_of<NamedExpr>, NamedExpr> -> parameter_t<value_type_of<NamedExpr>, NamedExpr>
{ {
static_assert(is_named_expression_t<NamedExpr>::value, "not a named expression"); static_assert(is_selectable_t<NamedExpr>::value, "not a named expression");
return {}; return {};
} }

View File

@ -52,12 +52,12 @@ namespace sqlpp
template<typename Target> template<typename Target>
void _bind(Target& target) const void _bind(Target& target) const
{ {
_bind_impl(target, ::sqlpp::detail::make_index_sequence<size::value>{}); _bind_impl(target, detail::make_index_sequence<size::value>{});
} }
private: private:
template<typename Target, size_t... Is> template<typename Target, size_t... Is>
void _bind_impl(Target& target, const ::sqlpp::detail::index_sequence<Is...>&) const void _bind_impl(Target& target, const detail::index_sequence<Is...>&) const
{ {
using swallow = int[]; // see interpret_tuple.h using swallow = int[]; // see interpret_tuple.h
(void) swallow{(static_cast<typename std::tuple_element<Is, const _member_tuple_t>::type&>(*this)()._bind(target, Is), 0)...}; (void) swallow{(static_cast<typename std::tuple_element<Is, const _member_tuple_t>::type&>(*this)()._bind(target, Is), 0)...};

View File

@ -50,6 +50,8 @@ namespace sqlpp
template<typename Original, typename Needle, typename Replacement> template<typename Original, typename Needle, typename Replacement>
using update_policies_t = typename update_policies_impl<Original, Needle, Replacement>::type; using update_policies_t = typename update_policies_impl<Original, Needle, Replacement>::type;
template<typename Policies, typename Needle, typename Replacement>
using new_statement = typename Policies::template _new_statement_t<Needle, Replacement>;
} }

View File

@ -28,6 +28,7 @@
#define SQLPP_REMOVE_H #define SQLPP_REMOVE_H
#include <sqlpp11/statement.h> #include <sqlpp11/statement.h>
#include <sqlpp11/connection.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_remove.h> #include <sqlpp11/prepared_remove.h>
@ -48,7 +49,7 @@ namespace sqlpp
template<typename Policies> template<typename Policies>
struct _result_methods_t struct _result_methods_t
{ {
using _statement_t = typename Policies::_statement_t; using _statement_t = derived_statement_t<Policies>;
const _statement_t& _get_statement() const const _statement_t& _get_statement() const
{ {
@ -115,6 +116,7 @@ namespace sqlpp
auto dynamic_remove(const Database&) auto dynamic_remove(const Database&)
-> decltype(blank_remove_t<Database>()) -> decltype(blank_remove_t<Database>())
{ {
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
return { blank_remove_t<Database>() }; return { blank_remove_t<Database>() };
} }
@ -122,6 +124,7 @@ namespace sqlpp
auto dynamic_remove_from(const Database&, Table table) auto dynamic_remove_from(const Database&, Table table)
-> decltype(blank_remove_t<Database>().from(table)) -> decltype(blank_remove_t<Database>().from(table))
{ {
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
return { blank_remove_t<Database>().from(table) }; return { blank_remove_t<Database>().from(table) };
} }
} }

View File

@ -32,7 +32,7 @@
namespace sqlpp namespace sqlpp
{ {
template<typename ValueType, typename Db, typename Field> template<typename ValueType, typename Db, typename FieldSpec>
struct result_field_t struct result_field_t
{ {
static_assert(wrong_t<result_field_t>::value, "Missing specialization for result_field_t"); static_assert(wrong_t<result_field_t>::value, "Missing specialization for result_field_t");

View File

@ -88,7 +88,9 @@ namespace sqlpp
using _provided_outer_tables = detail::type_set<>; using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<>; using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _can_be_null = column_spec_can_be_null_t<_field_spec_t>; using _tags = typename std::conditional<column_spec_can_be_null_t<_field_spec_t>::value,
detail::type_set<tag::can_be_null>,
detail::type_set<>>::type;
}; };
}; };

View File

@ -41,9 +41,9 @@ namespace sqlpp
template<typename Db, std::size_t index, typename FieldSpec> template<typename Db, std::size_t index, typename FieldSpec>
struct result_field: struct result_field:
public FieldSpec::_name_t::template _member_t<result_field_t<value_type_of<FieldSpec>, Db, FieldSpec>> public member_t<FieldSpec, result_field_t<value_type_of<FieldSpec>, Db, FieldSpec>>
{ {
using _field = typename FieldSpec::_name_t::template _member_t<result_field_t<value_type_of<FieldSpec>, Db, FieldSpec>>; using _field = member_t<FieldSpec, result_field_t<value_type_of<FieldSpec>, Db, FieldSpec>>;
result_field() = default; result_field() = default;
@ -66,9 +66,9 @@ namespace sqlpp
template<std::size_t index, typename AliasProvider, typename Db, typename... FieldSpecs> template<std::size_t index, typename AliasProvider, typename Db, typename... FieldSpecs>
struct result_field<Db, index, multi_field_spec_t<AliasProvider, std::tuple<FieldSpecs...>>>: struct result_field<Db, index, multi_field_spec_t<AliasProvider, std::tuple<FieldSpecs...>>>:
public AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_field_index_sequence<index, FieldSpecs...>, FieldSpecs...>> public member_t<AliasProvider, result_row_impl<Db, detail::make_field_index_sequence<index, FieldSpecs...>, FieldSpecs...>>
{ {
using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_field_index_sequence<index, FieldSpecs...>, FieldSpecs...>>; using _multi_field = member_t<AliasProvider, result_row_impl<Db, detail::make_field_index_sequence<index, FieldSpecs...>, FieldSpecs...>>;
result_field() = default; result_field() = default;

View File

@ -30,6 +30,7 @@
#include <sqlpp11/statement.h> #include <sqlpp11/statement.h>
#include <sqlpp11/noop.h> #include <sqlpp11/noop.h>
#include <sqlpp11/connection.h>
#include <sqlpp11/select_flag_list.h> #include <sqlpp11/select_flag_list.h>
#include <sqlpp11/select_column_list.h> #include <sqlpp11/select_column_list.h>
#include <sqlpp11/from.h> #include <sqlpp11/from.h>
@ -94,6 +95,7 @@ namespace sqlpp
template<typename Database> template<typename Database>
blank_select_t<Database> dynamic_select(const Database&) blank_select_t<Database> dynamic_select(const Database&)
{ {
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
return { }; return { };
} }
@ -101,6 +103,7 @@ namespace sqlpp
auto dynamic_select(const Database&, Columns... columns) auto dynamic_select(const Database&, Columns... columns)
-> decltype(blank_select_t<Database>().columns(columns...)) -> decltype(blank_select_t<Database>().columns(columns...))
{ {
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
return blank_select_t<Database>().columns(columns...); return blank_select_t<Database>().columns(columns...);
} }

View File

@ -54,7 +54,7 @@ namespace sqlpp
template<typename Column> template<typename Column>
struct select_traits<Column> struct select_traits<Column>
{ {
using _traits = make_traits<value_type_of<Column>, tag::is_select_column_list, tag::is_return_value, tag::is_expression, tag::is_named_expression>; using _traits = make_traits<value_type_of<Column>, tag::is_select_column_list, tag::is_return_value, tag::is_expression, tag::is_selectable>;
using _name_t = typename Column::_name_t; using _name_t = typename Column::_name_t;
}; };
} }
@ -152,17 +152,17 @@ namespace sqlpp
template<typename Database, typename... Columns> template<typename Database, typename... Columns>
struct select_column_list_t struct select_column_list_t
{ {
using _traits = typename ::sqlpp::detail::select_traits<Columns...>::_traits; using _traits = typename detail::select_traits<Columns...>::_traits;
using _recursive_traits = make_recursive_traits<Columns...>; using _recursive_traits = make_recursive_traits<Columns...>;
using _name_t = typename ::sqlpp::detail::select_traits<Columns...>::_name_t; using _name_t = typename detail::select_traits<Columns...>::_name_t;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Columns), "at least one select expression required"); static_assert(_is_dynamic::value or sizeof...(Columns), "at least one select expression required");
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected"); static_assert(not detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected");
static_assert(::sqlpp::detail::all_t<(is_named_expression_t<Columns>::value or is_multi_column_t<Columns>::value)...>::value, "at least one argument is not a named expression"); static_assert(detail::all_t<(is_selectable_t<Columns>::value or is_multi_column_t<Columns>::value)...>::value, "at least one argument is not a named expression");
static_assert(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected"); static_assert(not detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected");
struct _column_type {}; struct _column_type {};
@ -183,14 +183,14 @@ namespace sqlpp
void add(NamedExpression namedExpression) void add(NamedExpression 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_named_expression_t<NamedExpression>::value, "invalid named expression argument in selected_columns::add()"); static_assert(is_selectable_t<NamedExpression>::value, "invalid named expression argument in selected_columns::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<NamedExpression>::value, "named expression uses tables unknown to this statement in selected_columns::add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<NamedExpression>::value, "named expression uses tables unknown to this statement in selected_columns::add()");
using column_names = ::sqlpp::detail::make_type_set_t<typename Columns::_name_t...>; using column_names = detail::make_type_set_t<typename Columns::_name_t...>;
static_assert(not ::sqlpp::detail::is_element_of<typename NamedExpression::_name_t, column_names>::value, "a column of this name is present in the select already"); static_assert(not detail::is_element_of<typename NamedExpression::_name_t, column_names>::value, "a column of this name is present in the select already");
using ok = ::sqlpp::detail::all_t< using ok = detail::all_t<
_is_dynamic::value, _is_dynamic::value,
is_named_expression_t<NamedExpression>::value is_selectable_t<NamedExpression>::value
>; >;
_add_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert
@ -238,7 +238,7 @@ namespace sqlpp
template<typename Policies> template<typename Policies>
struct _result_methods_t struct _result_methods_t
{ {
using _statement_t = typename Policies::_statement_t; using _statement_t = derived_statement_t<Policies>;
const _statement_t& _get_statement() const const _statement_t& _get_statement() const
{ {
@ -278,7 +278,7 @@ namespace sqlpp
_alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const _alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const
{ {
static_assert(Policies::_can_be_used_as_table::value, "statement cannot be used as table, e.g. due to missing tables"); static_assert(Policies::_can_be_used_as_table::value, "statement cannot be used as table, e.g. due to missing tables");
static_assert(::sqlpp::detail::none_t<is_multi_column_t<Columns>::value...>::value, "cannot use multi-columns in sub selects"); static_assert(detail::none_t<is_multi_column_t<Columns>::value...>::value, "cannot use multi-columns in sub selects");
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider); return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
} }
@ -310,7 +310,7 @@ namespace sqlpp
{ {
_statement_t::_check_consistency(); _statement_t::_check_consistency();
return {{}, get_dynamic_names(), db.prepare_select(_get_statement())}; return {make_parameter_list_t<_statement_t>{}, get_dynamic_names(), db.prepare_select(_get_statement())};
} }
}; };
@ -326,7 +326,7 @@ namespace sqlpp
struct no_select_column_list_t struct no_select_column_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop, ::sqlpp::tag::is_missing>; using _traits = make_traits<no_value_t, tag::is_noop, tag::is_missing>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
struct _name_t {}; struct _name_t {};
@ -364,23 +364,23 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_select_column_list_t, T>; using _new_statement_t = new_statement<Policies, no_select_column_list_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename... Args> template<typename... Args>
auto columns(Args... args) auto columns(Args... args) const
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<void, Args...>> -> _new_statement_t<detail::make_select_column_list_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), typename ::sqlpp::detail::make_select_column_list_t<void, Args...>::_data_t{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} }; return { static_cast<const derived_statement_t<Policies>&>(*this), typename detail::make_select_column_list_t<void, Args...>::_data_t{std::tuple_cat(detail::as_tuple<Args>::_(args)...)} };
} }
template<typename... Args> template<typename... Args>
auto dynamic_columns(Args... args) auto dynamic_columns(Args... args) const
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>> -> _new_statement_t<detail::make_select_column_list_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), typename ::sqlpp::detail::make_select_column_list_t<_database_t, Args...>::_data_t{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} }; return { static_cast<const derived_statement_t<Policies>&>(*this), typename detail::make_select_column_list_t<_database_t, Args...>::_data_t{std::tuple_cat(detail::as_tuple<Args>::_(args)...)} };
} }
}; };
}; };

View File

@ -59,14 +59,14 @@ namespace sqlpp
template<typename Database, typename... Flags> template<typename Database, typename... Flags>
struct select_flag_list_t struct select_flag_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_select_flag_list>; using _traits = make_traits<no_value_t, tag::is_select_flag_list>;
using _recursive_traits = make_recursive_traits<Flags...>; using _recursive_traits = make_recursive_traits<Flags...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(not ::sqlpp::detail::has_duplicates<Flags...>::value, "at least one duplicate argument detected in select flag list"); static_assert(not detail::has_duplicates<Flags...>::value, "at least one duplicate argument detected in select flag list");
static_assert(::sqlpp::detail::all_t<is_select_flag_t<Flags>::value...>::value, "at least one argument is not a select flag in select flag list"); static_assert(detail::all_t<is_select_flag_t<Flags>::value...>::value, "at least one argument is not a select flag in select flag list");
// Data // Data
using _data_t = select_flag_list_data_t<Database, Flags...>; using _data_t = select_flag_list_data_t<Database, Flags...>;
@ -88,7 +88,7 @@ namespace sqlpp
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, "flag uses tables unknown to this statement in select_flags::add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Flag>::value, "flag uses tables unknown to this statement in select_flags::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_select_flag_t<Flag>::value>; using ok = detail::all_t<_is_dynamic::value, is_select_flag_t<Flag>::value>;
_add_impl(flag, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(flag, ok()); // dispatch to prevent compile messages after the static_assert
} }
@ -134,7 +134,7 @@ namespace sqlpp
struct no_select_flag_list_t struct no_select_flag_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -169,23 +169,23 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_select_flag_list_t, T>; using _new_statement_t = new_statement<Policies, no_select_flag_list_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename... Args> template<typename... Args>
auto flags(Args... args) auto flags(Args... args) const
-> _new_statement_t<select_flag_list_t<void, Args...>> -> _new_statement_t<select_flag_list_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), select_flag_list_data_t<void, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), select_flag_list_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
auto dynamic_flags(Args... args) auto dynamic_flags(Args... args) const
-> _new_statement_t<select_flag_list_t<_database_t, Args...>> -> _new_statement_t<select_flag_list_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), select_flag_list_data_t<_database_t, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), select_flag_list_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };

View File

@ -51,7 +51,7 @@ namespace sqlpp
typename Select, typename Select,
typename... NamedExpr typename... NamedExpr
> >
struct select_pseudo_table_t: public sqlpp::table_t<select_pseudo_table_t< struct select_pseudo_table_t: public table_t<select_pseudo_table_t<
Select, Select,
NamedExpr...>, select_column_spec_t<Select, NamedExpr>...> NamedExpr...>, select_column_spec_t<Select, NamedExpr>...>
{ {

View File

@ -37,7 +37,7 @@ namespace sqlpp
{ {
Column _column; Column _column;
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
}; };

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<typename Database, typename Table> template<typename Database, typename Table>
struct single_table_t struct single_table_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_single_table>; using _traits = make_traits<no_value_t, tag::is_single_table>;
using _recursive_traits = make_recursive_traits<Table>; using _recursive_traits = make_recursive_traits<Table>;
static_assert(is_table_t<Table>::value, "argument has to be a table"); static_assert(is_table_t<Table>::value, "argument has to be a table");
@ -103,7 +103,7 @@ namespace sqlpp
// NO INTO YET // NO INTO YET
struct no_single_table_t struct no_single_table_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -138,15 +138,15 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_single_table_t, T>; using _new_statement_t = new_statement<Policies, no_single_table_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename... Args> template<typename... Args>
auto from(Args... args) auto from(Args... args) const
-> _new_statement_t<single_table_t<void, Args...>> -> _new_statement_t<single_table_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), single_table_data_t<void, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), single_table_data_t<void, Args...>{args...} };
} }
}; };
}; };

View File

@ -35,7 +35,7 @@ namespace sqlpp
template<typename Select> template<typename Select>
struct some_t struct some_t
{ {
using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::is_multi_expression>; using _traits = make_traits<value_type_of<Select>, tag::is_multi_expression>;
using _recursive_traits = make_recursive_traits<Select>; using _recursive_traits = make_recursive_traits<Select>;
struct _name_t struct _name_t

View File

@ -41,7 +41,7 @@ namespace sqlpp
template<typename Expression, sort_type SortType> template<typename Expression, sort_type SortType>
struct sort_order_t struct sort_order_t
{ {
using _traits = make_traits<no_value_t, tag::is_sort_order, sqlpp::tag::is_expression>; using _traits = make_traits<no_value_t, tag::is_sort_order, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Expression>; using _recursive_traits = make_recursive_traits<Expression>;
Expression _expression; Expression _expression;

View File

@ -98,6 +98,13 @@ namespace sqlpp
no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value
>::type; >::type;
using _can_be_null = detail::any_t<
can_be_null_t<_result_type_provider>::value,
detail::make_intersect_set_t<
required_tables_of<_result_type_provider>,
_all_provided_outer_tables
>::size::value != 0>;
using _traits = make_traits<_value_type, tag_if<tag::is_expression, not std::is_same<_value_type, no_value_t>::value>>; using _traits = make_traits<_value_type, tag_if<tag::is_expression, not std::is_same<_value_type, no_value_t>::value>>;
struct _recursive_traits struct _recursive_traits
@ -107,12 +114,9 @@ namespace sqlpp
using _provided_outer_tables = detail::type_set<>; using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Policies>...>; using _parameters = detail::make_parameter_tuple_t<parameters_of<Policies>...>;
using _can_be_null = detail::any_t< using _tags = typename std::conditional<_can_be_null::value,
can_be_null_t<_result_type_provider>::value, detail::type_set<tag::can_be_null>,
::sqlpp::detail::make_intersect_set_t< detail::type_set<>>::type;
required_tables_of<_result_type_provider>,
provided_outer_tables_of<statement_policies_t>
>::size::value != 0>;
}; };
}; };
} }
@ -122,16 +126,16 @@ namespace sqlpp
> >
struct statement_t: struct statement_t:
public Policies::template _member_t<detail::statement_policies_t<Db, Policies...>>..., public Policies::template _member_t<detail::statement_policies_t<Db, Policies...>>...,
public detail::statement_policies_t<Db, Policies...>::_value_type::template expression_operators<statement_t<Db, Policies...>>, public expression_operators<statement_t<Db, Policies...>, value_type_of<detail::statement_policies_t<Db, Policies...>>>,
public detail::statement_policies_t<Db, Policies...>::_result_methods_t, public detail::statement_policies_t<Db, Policies...>::_result_methods_t,
public Policies::template _methods_t<detail::statement_policies_t<Db, Policies...>>... public Policies::template _methods_t<detail::statement_policies_t<Db, Policies...>>...
{ {
using _policies_t = typename detail::statement_policies_t<Db, Policies...>; using _policies_t = typename detail::statement_policies_t<Db, Policies...>;
using _traits = make_traits<value_type_of<_policies_t>, using _traits = make_traits<value_type_of<_policies_t>,
::sqlpp::tag::is_select, tag::is_select,
tag_if<tag::is_expression, is_expression_t<_policies_t>::value>, tag_if<tag::is_expression, is_expression_t<_policies_t>::value>,
tag_if<tag::is_named_expression, is_expression_t<_policies_t>::value>, tag_if<tag::is_selectable, is_expression_t<_policies_t>::value>,
tag::requires_braces>; tag::requires_braces>;
using _recursive_traits = typename _policies_t::_recursive_traits; using _recursive_traits = typename _policies_t::_recursive_traits;
using _used_outer_tables = typename _policies_t::_all_provided_outer_tables; using _used_outer_tables = typename _policies_t::_all_provided_outer_tables;
@ -184,7 +188,7 @@ namespace sqlpp
struct serializer_t<Context, statement_t<Database, Policies...>> struct serializer_t<Context, statement_t<Database, Policies...>>
{ {
using T = statement_t<Database, Policies...>; using T = statement_t<Database, Policies...>;
using P = ::sqlpp::detail::statement_policies_t<Database, Policies...>; using P = detail::statement_policies_t<Database, Policies...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -198,7 +202,7 @@ namespace sqlpp
template<typename NameData> template<typename NameData>
struct statement_name_t struct statement_name_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data

View File

@ -32,13 +32,14 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Flag, typename Expr> template<typename Flag, typename Expr>
struct sum_t: public value_type_of<Expr>::template expression_operators<sum_t<Flag, Expr>>, struct sum_t:
public alias_operators<sum_t<Flag, Expr>> public expression_operators<sum_t<Flag, Expr>, value_type_of<Expr>>,
public alias_operators<sum_t<Flag, Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>; using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr>; using _recursive_traits = make_recursive_traits<Expr, aggregate_function>;
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "sum() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "sum() used with flag other than 'distinct'");
static_assert(is_numeric_t<Expr>::value, "sum() requires a numeric expression as argument"); static_assert(is_numeric_t<Expr>::value, "sum() requires a numeric expression as argument");
struct _name_t struct _name_t
@ -74,7 +75,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "SUM("; context << "SUM(";
if (std::is_same<sqlpp::distinct_t, Flag>::value) if (std::is_same<distinct_t, Flag>::value)
{ {
serialize(Flag(), context); serialize(Flag(), context);
context << ' '; context << ' ';
@ -88,13 +89,15 @@ namespace sqlpp
template<typename T> template<typename T>
auto sum(T t) -> sum_t<noop, wrap_operand_t<T>> auto sum(T t) -> sum_t<noop, wrap_operand_t<T>>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "sum() cannot be used on an aggregate function");
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument"); static_assert(is_numeric_t<wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument");
return { t }; return { t };
} }
template<typename T> template<typename T>
auto sum(const sqlpp::distinct_t&, T t) -> sum_t<sqlpp::distinct_t, wrap_operand_t<T>> auto sum(const distinct_t&, T t) -> sum_t<distinct_t, wrap_operand_t<T>>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "sum() cannot be used on an aggregate function");
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument"); static_assert(is_numeric_t<wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument");
return { t }; return { t };
} }

View File

@ -40,7 +40,9 @@ namespace sqlpp
struct table_base_t {}; struct table_base_t {};
template<typename Table, typename... ColumnSpec> template<typename Table, typename... ColumnSpec>
struct table_t: public table_base_t, public ColumnSpec::_name_t::template _member_t<column_t<Table, ColumnSpec>>... struct table_t:
public table_base_t,
public member_t<ColumnSpec, column_t<Table, ColumnSpec>>...
{ {
using _traits = make_traits<no_value_t, tag::is_table>; using _traits = make_traits<no_value_t, tag::is_table>;
@ -51,7 +53,7 @@ namespace sqlpp
using _provided_tables = detail::type_set<Table>; using _provided_tables = detail::type_set<Table>;
using _provided_outer_tables = detail::type_set<>; using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _can_be_null = std::false_type; using _tags = detail::type_set<>;
}; };
static_assert(sizeof...(ColumnSpec), "at least one column required per table"); static_assert(sizeof...(ColumnSpec), "at least one column required per table");
@ -62,31 +64,31 @@ namespace sqlpp
template<typename T> template<typename T>
join_t<inner_join_t, Table, T> join(T t) join_t<inner_join_t, Table, T> join(T t) const
{ {
return { *static_cast<const Table*>(this), t }; return { *static_cast<const Table*>(this), t };
} }
template<typename T> template<typename T>
join_t<inner_join_t, Table, T> inner_join(T t) join_t<inner_join_t, Table, T> inner_join(T t) const
{ {
return { *static_cast<const Table*>(this), t }; return { *static_cast<const Table*>(this), t };
} }
template<typename T> template<typename T>
join_t<outer_join_t, Table, T> outer_join(T t) join_t<outer_join_t, Table, T> outer_join(T t) const
{ {
return { *static_cast<const Table*>(this), t }; return { *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) join_t<left_outer_join_t, Table, T> left_outer_join(T t) const
{ {
return { *static_cast<const Table*>(this), t }; return { *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) join_t<right_outer_join_t, Table, T> right_outer_join(T t) const
{ {
return { *static_cast<const Table*>(this), t }; return { *static_cast<const Table*>(this), t };
} }

View File

@ -36,10 +36,11 @@
namespace sqlpp namespace sqlpp
{ {
template<typename AliasProvider, typename Table, typename... ColumnSpec> template<typename AliasProvider, typename Table, typename... ColumnSpec>
struct table_alias_t: public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>... struct table_alias_t:
public member_t<ColumnSpec, column_t<AliasProvider, ColumnSpec>>...
{ {
//FIXME: Need to add join functionality //FIXME: Need to add join functionality
using _traits = make_traits<value_type_of<Table>, tag::is_table, tag::is_alias, tag_if<tag::is_named_expression, is_expression_t<Table>::value>>; using _traits = make_traits<value_type_of<Table>, tag::is_table, tag::is_alias, tag_if<tag::is_selectable, is_expression_t<Table>::value>>;
struct _recursive_traits struct _recursive_traits
{ {
@ -48,13 +49,13 @@ namespace sqlpp
using _provided_tables = detail::type_set<AliasProvider>; using _provided_tables = detail::type_set<AliasProvider>;
using _provided_outer_tables = detail::type_set<>; using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>; using _extra_tables = detail::type_set<>;
using _can_be_null = std::false_type; using _tags = detail::type_set<>;
}; };
static_assert(required_tables_of<Table>::size::value == 0, "table aliases must not depend on external tables"); static_assert(required_tables_of<Table>::size::value == 0, "table aliases must not depend on external tables");
using _name_t = typename AliasProvider::_name_t; using _name_t = typename AliasProvider::_name_t;
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>; using _column_tuple_t = std::tuple<column_t<AliasProvider, ColumnSpec>...>;
table_alias_t(Table table): table_alias_t(Table table):
_table(table) _table(table)

View File

@ -39,32 +39,39 @@ namespace sqlpp
// text value type // text value type
struct text struct text
{ {
using _traits = make_traits<text, ::sqlpp::tag::is_text, ::sqlpp::tag::is_value_type>; using _traits = make_traits<text, tag::is_value_type>;
using _tag = ::sqlpp::tag::is_text; using _tag = tag::is_text;
using _cpp_value_type = std::string; using _cpp_value_type = std::string;
struct _parameter_t template<typename T>
using _is_valid_operand = is_text_t<T>;
};
// text parameter type
template<>
struct parameter_value_t<text>
{ {
using _value_type = text; using _value_type = text;
using _cpp_value_type = typename _value_type::_cpp_value_type;
_parameter_t(): parameter_value_t():
_value(""), _value(""),
_is_null(true) _is_null(true)
{} {}
_parameter_t(const _cpp_value_type& value): parameter_value_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(false) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) parameter_value_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = false; _is_null = false;
return *this; return *this;
} }
_parameter_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t) parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
{ {
if (t._is_trivial()) if (t._is_trivial())
{ {
@ -79,7 +86,7 @@ namespace sqlpp
return *this; return *this;
} }
_parameter_t& operator=(const std::nullptr_t&) parameter_value_t& operator=(const std::nullptr_t&)
{ {
_value = ""; _value = "";
_is_null = true; _is_null = true;
@ -110,51 +117,50 @@ namespace sqlpp
}; };
// text expression operators
template<typename Base>
struct expression_operators<Base, text>: public basic_expression_operators<Base, text>
{
template<typename T> template<typename T>
struct _is_valid_operand using _is_valid_operand = is_valid_operand<text, T>;
{
static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_text_t<T>::value // the correct value type is required, of course
;
};
template<typename Base> template<typename T>
struct expression_operators: public basic_expression_operators<Base, is_text_t> concat_t<Base, wrap_operand_t<T>> operator+(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T>
like_t<Base, wrap_operand_t<T>> like(T t) const
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid argument for like()");
return { *static_cast<const Base*>(this), {t} };
}
};
// text column operators
template<typename Base>
struct column_operators<Base, text>
{ {
template<typename T> template<typename T>
concat_t<Base, wrap_operand_t<T>> operator+(T t) const using _is_valid_operand = is_valid_operand<text, T>;
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} };
}
template<typename T> template<typename T>
like_t<Base, wrap_operand_t<T>> like(T t) const auto operator +=(T t) const -> assignment_t<Base, concat_t<Base, wrap_operand_t<T>>>
{ {
using rhs = wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid argument for like()"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), concat_t<Base, wrap_operand_t<T>>{ *static_cast<const Base*>(this), rhs{t} } };
} }
}; };
template<typename Base> // text result field
struct column_operators
{
template<typename T>
auto operator +=(T t) const -> assignment_t<Base, concat_t<Base, wrap_operand_t<T>>>
{
using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
}
};
};
template<typename Db, typename FieldSpec> template<typename Db, typename FieldSpec>
struct result_field_t<text, Db, FieldSpec>: public result_field_methods_t<result_field_t<text, Db, FieldSpec>> struct result_field_t<text, Db, FieldSpec>: public result_field_methods_t<result_field_t<text, Db, FieldSpec>>
{ {

View File

@ -32,30 +32,59 @@
namespace sqlpp namespace sqlpp
{ {
namespace tag
{
struct can_be_null{};
struct contains_aggregate_function{};
};
namespace detail namespace detail
{ {
template<typename T, typename Enable = void> template<typename T, typename Enable = void>
struct can_be_null_impl { using type = std::false_type; }; struct can_be_null_impl { using type = std::false_type; };
template<typename T> template<typename T>
struct can_be_null_impl<T, typename std::enable_if<T::_recursive_traits::_can_be_null::value>::type> { using type = std::true_type; }; struct can_be_null_impl<T, typename std::enable_if<is_element_of<tag::can_be_null, typename T::_recursive_traits::_tags>::value>::type> { using type = std::true_type; };
} }
template<typename T> template<typename T>
using can_be_null_t = typename detail::can_be_null_impl<T>::type; using can_be_null_t = typename detail::can_be_null_impl<T>::type;
namespace tag\ namespace detail
{\ {
struct can_be_null{};\ template<typename T, typename Enable = void>
};\ struct contains_aggregate_function_impl { using type = std::false_type; };
namespace detail\ template<typename T>
{\ struct contains_aggregate_function_impl<T, typename std::enable_if<is_element_of<tag::contains_aggregate_function, typename T::_recursive_traits::_tags>::value>::type> { using type = std::true_type; };
template<typename T, typename Enable = void>\ }
struct column_spec_can_be_null_impl { using type = std::false_type; };\ template<typename T>
template<typename T>\ using contains_aggregate_function_t = typename detail::contains_aggregate_function_impl<T>::type;
struct column_spec_can_be_null_impl<T, typename std::enable_if<detail::is_element_of<tag::can_be_null, typename T::_traits::_tags>::value>::type> { using type = std::true_type; };\
}\ namespace detail
template<typename T>\ {
template<typename T, typename Enable = void>
struct column_spec_can_be_null_impl { using type = std::false_type; };
template<typename T>
struct column_spec_can_be_null_impl<T, typename std::enable_if<detail::is_element_of<tag::can_be_null, typename T::_traits::_tags>::value>::type> { using type = std::true_type; };
}
template<typename T>
using column_spec_can_be_null_t = typename detail::column_spec_can_be_null_impl<T>::type; using column_spec_can_be_null_t = typename detail::column_spec_can_be_null_impl<T>::type;
namespace tag
{
struct is_expression{};
};
namespace detail
{
template<typename T, typename Enable = void>
struct is_expression_impl { using type = std::false_type; };
template<typename T>
struct is_expression_impl<T, typename std::enable_if<
detail::is_element_of<tag::is_expression, typename T::_traits::_tags>::value
and not detail::is_element_of<tag::contains_aggregate_function, typename T::_recursive_traits::_tags>::value
>::type> { using type = std::true_type; };
}
template<typename T>
using is_expression_t = typename detail::is_expression_impl<T>::type;
#define SQLPP_VALUE_TRAIT_GENERATOR(name) \ #define SQLPP_VALUE_TRAIT_GENERATOR(name) \
namespace tag\ namespace tag\
{\ {\
@ -82,8 +111,7 @@ namespace sqlpp
detail::is_element_of<tag::is_floating_point, typename T::_traits::_tags>::value>; detail::is_element_of<tag::is_floating_point, typename T::_traits::_tags>::value>;
SQLPP_VALUE_TRAIT_GENERATOR(is_text); SQLPP_VALUE_TRAIT_GENERATOR(is_text);
SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value); SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value);
SQLPP_VALUE_TRAIT_GENERATOR(is_expression); SQLPP_VALUE_TRAIT_GENERATOR(is_selectable);
SQLPP_VALUE_TRAIT_GENERATOR(is_named_expression);
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression); SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression);
SQLPP_VALUE_TRAIT_GENERATOR(is_alias); SQLPP_VALUE_TRAIT_GENERATOR(is_alias);
SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag); SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag);
@ -140,80 +168,35 @@ namespace sqlpp
namespace detail namespace detail
{ {
template<typename T>
struct value_type_of_impl
{
using type = typename T::_traits::_value_type;
};
template<typename T>
struct required_table_of_impl
{
using type = typename T::_recursive_traits::_required_tables;
};
template<typename T>
struct provided_table_of_impl
{
using type = typename T::_recursive_traits::_provided_tables;
};
template<typename T>
struct provided_outer_table_of_impl
{
using type = typename T::_recursive_traits::_provided_outer_tables;
};
template<typename T>
struct extra_table_of_impl
{
using type = typename T::_recursive_traits::_extra_tables;
};
template<typename T>
struct parameters_of_impl
{
using type = typename T::_recursive_traits::_parameters;
};
template<typename T>
struct name_of_impl
{
using type = typename T::_name_t;
};
template<typename... T> template<typename... T>
struct make_parameter_tuple_impl using make_parameter_tuple_t = decltype(std::tuple_cat(std::declval<T>()...));
{
using type = decltype(std::tuple_cat(std::declval<T>()...));
};
template<typename... T>
using make_parameter_tuple_t = typename make_parameter_tuple_impl<T...>::type;
} }
template<typename T> template<typename T>
using value_type_of = typename detail::value_type_of_impl<T>::type; using value_type_of = typename T::_traits::_value_type;
template<typename T> template<typename T>
using cpp_value_type_of = typename value_type_of<T>::_cpp_value_type; using cpp_value_type_of = typename value_type_of<T>::_cpp_value_type;
template<typename T> template<typename T>
using required_tables_of = typename detail::required_table_of_impl<T>::type; using required_tables_of = typename T::_recursive_traits::_required_tables;
template<typename T> template<typename T>
using provided_tables_of = typename detail::provided_table_of_impl<T>::type; using provided_tables_of = typename T::_recursive_traits::_provided_tables;
template<typename T> template<typename T>
using provided_outer_tables_of = typename detail::provided_outer_table_of_impl<T>::type; using provided_outer_tables_of = typename T::_recursive_traits::_provided_outer_tables;
template<typename T> template<typename T>
using extra_tables_of = typename detail::extra_table_of_impl<T>::type; using extra_tables_of = typename T::_recursive_traits::_extra_tables;
template<typename T> template<typename T>
using parameters_of = typename detail::parameters_of_impl<T>::type; using parameters_of = typename T::_recursive_traits::_parameters;
template<typename T> template<typename T>
using name_of = typename detail::name_of_impl<T>::type; using recursive_tags_of = typename T::_recursive_traits::_tags;
template<typename T>
using name_of = typename T::_name_t;
template<typename ValueType, typename... Tags> template<typename ValueType, typename... Tags>
struct make_traits struct make_traits
@ -221,6 +204,7 @@ namespace sqlpp
using _value_type = ValueType; using _value_type = ValueType;
using _tags = detail::make_type_set_t<typename ValueType::_tag, Tags...>; using _tags = detail::make_type_set_t<typename ValueType::_tag, Tags...>;
}; };
template<typename... Arguments> template<typename... Arguments>
struct make_recursive_traits struct make_recursive_traits
{ {
@ -229,9 +213,31 @@ namespace sqlpp
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Arguments>...>; using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Arguments>...>;
using _extra_tables = detail::make_joined_set_t<extra_tables_of<Arguments>...>; using _extra_tables = detail::make_joined_set_t<extra_tables_of<Arguments>...>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Arguments>...>; using _parameters = detail::make_parameter_tuple_t<parameters_of<Arguments>...>;
using _can_be_null = detail::any_t<can_be_null_t<Arguments>::value...>; using _tags = detail::make_joined_set_t<recursive_tags_of<Arguments>...>;
}; };
template<typename... Tags>
struct recursive_tags
{
using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
using _parameters = std::tuple<>;
using _tags = detail::type_set<Tags...>;
};
struct aggregate_function
{
struct _traits { using _value_type = void; using _tags = detail::type_set<>; };
using _recursive_traits = recursive_tags<tag::contains_aggregate_function>;
};
template<typename NameProvider, typename Member>
using member_t = typename NameProvider::_name_t::template _member_t<Member>;
template<typename Policies>
using derived_statement_t = typename Policies::_statement_t;
} }
#endif #endif

View File

@ -28,7 +28,7 @@
#define SQLPP_UPDATE_H #define SQLPP_UPDATE_H
#include <sqlpp11/statement.h> #include <sqlpp11/statement.h>
#include <sqlpp11/connection.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_update.h> #include <sqlpp11/prepared_update.h>
@ -49,7 +49,7 @@ namespace sqlpp
template<typename Policies> template<typename Policies>
struct _result_methods_t struct _result_methods_t
{ {
using _statement_t = typename Policies::_statement_t; using _statement_t = derived_statement_t<Policies>;
const _statement_t& _get_statement() const const _statement_t& _get_statement() const
{ {
@ -109,6 +109,7 @@ namespace sqlpp
constexpr auto dynamic_update(const Database&, Table table) constexpr auto dynamic_update(const Database&, Table table)
-> decltype(blank_update_t<Database>().from(table)) -> decltype(blank_update_t<Database>().from(table))
{ {
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
return { blank_update_t<Database>().from(table) }; return { blank_update_t<Database>().from(table) };
} }
} }

View File

@ -56,7 +56,7 @@ namespace sqlpp
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
struct update_list_t struct update_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_update_list>; using _traits = make_traits<no_value_t, tag::is_update_list>;
using _recursive_traits = make_recursive_traits<Assignments...>; using _recursive_traits = make_recursive_traits<Assignments...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -78,12 +78,12 @@ namespace sqlpp
{ {
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()");
static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add()"); static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add()");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_t...>; using _assigned_columns = detail::make_type_set_t<lhs_t<Assignments>...>;
static_assert(not detail::is_element_of<typename Assignment::_lhs_t, _assigned_columns>::value, "Must not assign value to column twice"); static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_lhs_t>::value, "add() argument must not be updated"); static_assert(detail::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, "assignment uses tables unknown to this statement in add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "assignment uses tables unknown to this statement in add()");
using ok = ::sqlpp::detail::all_t< using ok = detail::all_t<
_is_dynamic::value, _is_dynamic::value,
is_assignment_t<Assignment>::value>; is_assignment_t<Assignment>::value>;
@ -130,7 +130,7 @@ namespace sqlpp
struct no_update_list_t struct no_update_list_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>; using _traits = make_traits<no_value_t, tag::is_where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -165,7 +165,7 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_update_list_t, T>; using _new_statement_t = new_statement<Policies, no_update_list_t, T>;
static void _check_consistency() static void _check_consistency()
{ {
@ -173,7 +173,7 @@ namespace sqlpp
} }
template<typename... Assignments> template<typename... Assignments>
auto set(Assignments... assignments) auto set(Assignments... assignments) const
-> _new_statement_t<update_list_t<void, Assignments...>> -> _new_statement_t<update_list_t<void, Assignments...>>
{ {
static_assert(sizeof...(Assignments), "at least one assignment expression required in set()"); static_assert(sizeof...(Assignments), "at least one assignment expression required in set()");
@ -181,7 +181,7 @@ namespace sqlpp
} }
template<typename... Assignments> template<typename... Assignments>
auto dynamic_set(Assignments... assignments) auto dynamic_set(Assignments... assignments) const
-> _new_statement_t<update_list_t<_database_t, Assignments...>> -> _new_statement_t<update_list_t<_database_t, Assignments...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set() must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_set() must not be called in a static statement");
@ -190,17 +190,17 @@ namespace sqlpp
private: private:
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
auto _set_impl(Assignments... assignments) auto _set_impl(Assignments... assignments) const
-> _new_statement_t<update_list_t<Database, Assignments...>> -> _new_statement_t<update_list_t<Database, Assignments...>>
{ {
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()"); static_assert(detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()");
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()"); static_assert(not detail::has_duplicates<lhs_t<Assignments>...>::value, "at least one duplicate column detected in set()");
static_assert(::sqlpp::detail::none_t<must_not_update_t<typename Assignments::_lhs_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()"); static_assert(detail::none_t<must_not_update_t<lhs_t<Assignments>>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
using _column_required_tables = ::sqlpp::detail::make_joined_set_t<required_tables_of<typename Assignments::_lhs_t>...>; using _column_required_tables = detail::make_joined_set_t<required_tables_of<lhs_t<Assignments>>...>;
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from more than one table"); static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from more than one table");
return { *static_cast<typename Policies::_statement_t*>(this), update_list_data_t<Database, Assignments...>{assignments...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), update_list_data_t<Database, Assignments...>{assignments...} };
} }
}; };
}; };

View File

@ -57,16 +57,16 @@ namespace sqlpp
template<typename Database, typename... Tables> template<typename Database, typename... Tables>
struct using_t struct using_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_using_>; using _traits = make_traits<no_value_t, tag::is_using_>;
using _recursive_traits = make_recursive_traits<Tables...>; using _recursive_traits = make_recursive_traits<Tables...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()"); static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()");
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in using()"); static_assert(not detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in using()");
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not an table in using()"); static_assert(detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not an table in using()");
// Data // Data
using _data_t = using_data_t<Database, Tables...>; using _data_t = using_data_t<Database, Tables...>;
@ -81,7 +81,7 @@ namespace sqlpp
static_assert(_is_dynamic::value, "add must not be called for static using()"); static_assert(_is_dynamic::value, "add must not be called for static using()");
static_assert(is_table_t<Table>::value, "invalid table argument in add()"); static_assert(is_table_t<Table>::value, "invalid table argument in add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>; using ok = detail::all_t<_is_dynamic::value, is_table_t<Table>::value>;
_add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
} }
@ -128,7 +128,7 @@ namespace sqlpp
// NO USING YET // NO USING YET
struct no_using_t struct no_using_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>; using _traits = make_traits<no_value_t, tag::is_where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -163,23 +163,23 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_using_t, T>; using _new_statement_t = new_statement<Policies, no_using_t, T>;
static void _check_consistency() {} static void _check_consistency() {}
template<typename... Args> template<typename... Args>
auto using_(Args... args) auto using_(Args... args) const
-> _new_statement_t<using_t<void, Args...>> -> _new_statement_t<using_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), using_data_t<void, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), using_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
auto dynamic_using(Args... args) auto dynamic_using(Args... args) const
-> _new_statement_t<using_t<_database_t, Args...>> -> _new_statement_t<using_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), using_data_t<_database_t, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), using_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_VALUE_TYPE_FWD_H
#define SQLPP_VALUE_TYPE_FWD_H
#include <sqlpp11/wrong.h>
#include <sqlpp11/type_traits.h>
namespace sqlpp
{
template<typename ValueType>
struct parameter_value_t
{
static_assert(wrong_t<parameter_value_t>::value, "Missing parameter value type for ValueType");
};
template<typename Column, typename ValueType>
struct column_operators
{
static_assert(wrong_t<column_operators>::value, "Missing column operators for ValueType");
};
template<typename Expr, typename ValueType>
struct expression_operators
{
static_assert(wrong_t<expression_operators>::value, "Missing expression operators for ValueType");
};
template<typename ValueType, typename T>
struct is_valid_operand
{
static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and ValueType::template _is_valid_operand<T>::value // the correct value type is required, of course
;
};
}
#endif

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_VERBATIM_H
#define SQLPP_VERBATIM_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/serialize.h>
namespace sqlpp
{
template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim
struct verbatim_t:
public expression_operators<verbatim_t<ValueType>, ValueType>,
public alias_operators<verbatim_t<ValueType>>
{
using _traits = make_traits<ValueType, tag::is_expression>;
struct _recursive_traits : public make_recursive_traits<>
{
using _tags = detail::type_set<tag::can_be_null>; // since we do not know what's going on inside the verbatim, we assume it can be null
};
verbatim_t(std::string verbatim): _verbatim(verbatim) {}
verbatim_t(const verbatim_t&) = default;
verbatim_t(verbatim_t&&) = default;
verbatim_t& operator=(const verbatim_t&) = default;
verbatim_t& operator=(verbatim_t&&) = default;
~verbatim_t() = default;
std::string _verbatim;
};
template<typename Context, typename ValueType>
struct serializer_t<Context, verbatim_t<ValueType>>
{
using T = verbatim_t<ValueType>;
static Context& _(const T& t, Context& context)
{
context << t._verbatim;
return context;
}
};
template<typename ValueType, typename StringType>
auto verbatim(StringType s) -> verbatim_t<ValueType>
{
return { s };
}
}
#endif

View File

@ -46,9 +46,9 @@ namespace sqlpp
}; };
} }
struct verbatim_table_t: public sqlpp::table_t<verbatim_table_t, detail::unusable_pseudo_column_t> struct verbatim_table_t: public table_t<verbatim_table_t, detail::unusable_pseudo_column_t>
{ {
struct _recursive_traits: public sqlpp::table_t<verbatim_table_t, detail::unusable_pseudo_column_t>::_recursive_traits struct _recursive_traits: public table_t<verbatim_table_t, detail::unusable_pseudo_column_t>::_recursive_traits
{ {
using _provided_outer_tables = detail::type_set<verbatim_table_t>; using _provided_outer_tables = detail::type_set<verbatim_table_t>;
}; };

View File

@ -58,14 +58,14 @@ namespace sqlpp
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct where_t struct where_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>; using _traits = make_traits<no_value_t, tag::is_where>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()"); static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in where()");
static_assert(sqlpp::detail::none_t<is_assignment_t<Expressions>::value...>::value, "at least one argument is an assignment in where()"); static_assert(detail::none_t<is_assignment_t<Expressions>::value...>::value, "at least one argument is an assignment in where()");
static_assert(sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()"); static_assert(detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()");
// Data // Data
using _data_t = where_data_t<Database, Expressions...>; using _data_t = where_data_t<Database, Expressions...>;
@ -87,7 +87,7 @@ namespace sqlpp
static_assert(is_expression_t<Expression>::value, "invalid expression argument in where::add()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in where::add()");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in where::add()"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in where::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = detail::all_t<_is_dynamic::value, is_expression_t<Expression>::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
} }
@ -141,7 +141,7 @@ namespace sqlpp
template<> template<>
struct where_t<void, bool> struct where_t<void, bool>
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>; using _traits = make_traits<no_value_t, tag::is_where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -181,10 +181,10 @@ namespace sqlpp
}; };
// NO WHERE YET // NO WHERE YET
template<bool Required> template<bool WhereRequired>
struct no_where_t struct no_where_t
{ {
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_where>; using _traits = make_traits<no_value_t, tag::is_where>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
// Data // Data
@ -220,26 +220,28 @@ namespace sqlpp
{ {
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T> template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_where_t, T>; using _new_statement_t = new_statement<Policies, no_where_t, T>;
static void _check_consistency() static void _check_consistency()
{ {
static_assert(Required ? wrong_t<_methods_t>::value : true, "where expression required, e.g. where(true)"); static constexpr bool _tables_provided = (Policies::_all_provided_tables::size::value > 0);
static constexpr bool _required = WhereRequired and _tables_provided;
static_assert(not _required, "where expression required, e.g. where(true)");
} }
template<typename... Args> template<typename... Args>
auto where(Args... args) auto where(Args... args) const
-> _new_statement_t<where_t<void, Args...>> -> _new_statement_t<where_t<void, Args...>>
{ {
return { *static_cast<typename Policies::_statement_t*>(this), where_data_t<void, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), where_data_t<void, Args...>{args...} };
} }
template<typename... Args> template<typename... Args>
auto dynamic_where(Args... args) auto dynamic_where(Args... args) const
-> _new_statement_t<where_t<_database_t, Args...>> -> _new_statement_t<where_t<_database_t, Args...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_where must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), where_data_t<_database_t, Args...>{args...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), where_data_t<_database_t, Args...>{args...} };
} }
}; };
}; };

View File

@ -28,8 +28,10 @@
#define SQLPP_DETAIL_WRAP_OPERAND_H #define SQLPP_DETAIL_WRAP_OPERAND_H
#include <string> #include <string>
#include <sqlpp11/wrap_operand_fwd.h>
#include <sqlpp11/serializer.h> #include <sqlpp11/serializer.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/basic_expression_operators.h>
namespace sqlpp namespace sqlpp
{ {
@ -38,9 +40,9 @@ namespace sqlpp
struct floating_point; struct floating_point;
struct text; struct text;
struct boolean_operand struct boolean_operand: public alias_operators<boolean_operand>
{ {
using _traits = make_traits<::sqlpp::boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>; using _traits = make_traits<boolean, tag::is_expression, tag::is_wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = bool; using _value_t = bool;
@ -76,9 +78,9 @@ namespace sqlpp
} }
}; };
struct integral_operand struct integral_operand: public alias_operators<integral_operand>
{ {
using _traits = make_traits<::sqlpp::integral, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>; using _traits = make_traits<integral, tag::is_expression, tag::is_wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = int64_t; using _value_t = int64_t;
@ -115,9 +117,9 @@ namespace sqlpp
}; };
struct floating_point_operand struct floating_point_operand: public alias_operators<floating_point_operand>
{ {
using _traits = make_traits<::sqlpp::floating_point, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>; using _traits = make_traits<floating_point, tag::is_expression, tag::is_wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = double; using _value_t = double;
@ -153,9 +155,9 @@ namespace sqlpp
} }
}; };
struct text_operand struct text_operand: public alias_operators<text_operand>
{ {
using _traits = make_traits<::sqlpp::text, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>; using _traits = make_traits<text, tag::is_expression, tag::is_wrapped_value>;
using _recursive_traits = make_recursive_traits<>; using _recursive_traits = make_recursive_traits<>;
using _value_t = std::string; using _value_t = std::string;
@ -191,7 +193,7 @@ namespace sqlpp
} }
}; };
template<typename T, typename Enable = void> template<typename T, typename Enable>
struct wrap_operand struct wrap_operand
{ {
using type = T; using type = T;
@ -221,11 +223,6 @@ namespace sqlpp
using type = text_operand; using type = text_operand;
}; };
// FIXME: Need to allow std::ref arguments
template<typename T>
using wrap_operand_t = typename wrap_operand<T>::type;
} }
#endif #endif

View File

@ -0,0 +1,40 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_DETAIL_WRAP_OPERAND_FWD_H
#define SQLPP_DETAIL_WRAP_OPERAND_FWD_H
namespace sqlpp
{
template<typename T, typename Enable = void>
struct wrap_operand;
template<typename T>
using wrap_operand_t = typename wrap_operand<T>::type;
}
#endif

View File

@ -175,7 +175,6 @@ for tableCreation in tableCreations:
print(' struct ' + tableClass + ': ' + NAMESPACE + '::table_t<' + tableTemplateParameters + '>', file=header) print(' struct ' + tableClass + ': ' + NAMESPACE + '::table_t<' + tableTemplateParameters + '>', file=header)
print(' {', file=header) print(' {', file=header)
print(' using _value_type = ' + NAMESPACE + '::no_value_t;', file=header)
print(' struct _name_t', file=header) print(' struct _name_t', file=header)
print(' {', file=header) print(' {', file=header)
print(' static constexpr const char* _get_name() { return "' + sqlTableName + '"; }', file=header) print(' static constexpr const char* _get_name() { return "' + sqlTableName + '"; }', file=header)

View File

@ -1,31 +1,33 @@
include_directories(${CMAKE_BINARY_DIR}/tests) include_directories("${CMAKE_SOURCE_DIR}/tests")
add_custom_target(test_sqlpp_constraints COMMAND true) add_custom_target(test_sqlpp_constraints COMMAND true)
function(test_constraint name pattern) function(test_constraint name pattern)
add_executable( add_executable(
${name} "${name}"
EXCLUDE_FROM_ALL EXCLUDE_FROM_ALL
${name}.cpp "${name}.cpp"
) )
add_custom_command(OUTPUT ${name}.out add_custom_command(OUTPUT "${name}.out"
COMMAND ${CMAKE_MAKE_PROGRAM} ${name} > ${CMAKE_CURRENT_BINARY_DIR}/${name}.out 2>&1 || true COMMAND "${CMAKE_MAKE_PROGRAM}" "${name}" > "${CMAKE_CURRENT_BINARY_DIR}/${name}.out" 2>&1 || true
COMMAND grep ${pattern} ${CMAKE_CURRENT_BINARY_DIR}/${name}.out > /dev/null COMMAND grep "${pattern}" "${CMAKE_CURRENT_BINARY_DIR}/${name}.out" > /dev/null
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
COMMENT "${name}" COMMENT "${name}"
) VERBATIM)
add_custom_target(test_${name} DEPENDS ${name}.out COMMAND true) add_custom_target("test_${name}" DEPENDS "${name}.out" COMMAND true)
add_dependencies(test_sqlpp_constraints test_${name}) add_dependencies(test_sqlpp_constraints "test_${name}")
endfunction(testconstraint)
endfunction(test_constraint)
test_constraint(count_of_count "requires an expression as argument")
test_constraint(max_of_max "requires an expression as argument")
test_constraint(no_conversion_operator_if_null_not_trivial "int i = row.alpha") test_constraint(no_conversion_operator_if_null_not_trivial "int i = row.alpha")
test_constraint(require_insert "required column is missing") test_constraint(require_insert "required column is missing")
test_constraint(must_not_insert "one assignment is prohibited") test_constraint(must_not_insert "one assignment is prohibited")
test_constraint(must_not_update "one assignment is prohibited")

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/functions.h>
#include <iostream>
MockDb db;
int main()
{
test::TabBar t;
count(count(t.alpha));
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/functions.h>
#include <iostream>
MockDb db;
int main()
{
test::TabBar t;
max(max(t.alpha));
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "Sample.h"
#include "MockDb.h"
#include <sqlpp11/update.h>
MockDb db;
int main()
{
test::TabBar t;
update(t).set(t.alpha = 7, t.gamma = false, t.beta = "alpha must not be set");
}

View File

@ -1,9 +1,9 @@
macro (build_and_run arg) macro (build_and_run arg)
# Add headers to sources to enable file browsing in IDEs # Add headers to sources to enable file browsing in IDEs
include_directories(${CMAKE_BINARY_DIR}/tests) include_directories("${CMAKE_BINARY_DIR}/tests")
add_executable(${arg} ${arg}.cpp ${sqlpp_headers} ${CMAKE_CURRENT_LIST_DIR}/Sample.h) add_executable("${arg}" "${arg}.cpp" ${sqlpp_headers} "${CMAKE_CURRENT_LIST_DIR}/Sample.h")
add_test(${arg} ${arg}) add_test("${arg}" "${arg}")
endmacro () endmacro ()
build_and_run(BooleanExpressionTest) build_and_run(BooleanExpressionTest)
@ -21,8 +21,7 @@ build_and_run(ResultTest)
# if you want to use the generator, you can do something like this: # if you want to use the generator, you can do something like this:
#find_package(PythonInterp REQUIRED) #find_package(PythonInterp REQUIRED)
#add_custom_command( #add_custom_command(
# OUTPUT ${CMAKE_CURRENT_LIST_DIR}/Sample.h # OUTPUT "${CMAKE_CURRENT_LIST_DIR}/Sample.h"
# COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripts/ddl2cpp ${CMAKE_CURRENT_LIST_DIR}/sample.sql Sample test # COMMAND "${PYTHON_EXECUTABLE}" "${CMAKE_SOURCE_DIR}/scripts/ddl2cpp" "${CMAKE_CURRENT_LIST_DIR}/sample.sql" Sample test
# DEPENDS ${CMAKE_CURRENT_LIST_DIR}/sample.sql # DEPENDS "${CMAKE_CURRENT_LIST_DIR}/sample.sql"
# ) # VERBATIM)

View File

@ -50,15 +50,15 @@ int main()
using TI = decltype(t.alpha.in(1, 2, 3)); using TI = decltype(t.alpha.in(1, 2, 3));
using TF = decltype(f.omega.in(1.0, 2.0, 3.0)); using TF = decltype(f.omega.in(1.0, 2.0, 3.0));
using TT = decltype(t.beta.in("a", "b", "c")); using TT = decltype(t.beta.in("a", "b", "c"));
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TF>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement");
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");
@ -69,15 +69,15 @@ int main()
using TI = decltype(t.alpha.in(sqlpp::value_list(std::vector<int>({1, 2, 3})))); using TI = decltype(t.alpha.in(sqlpp::value_list(std::vector<int>({1, 2, 3}))));
using TF = decltype(f.omega.in(sqlpp::value_list(std::vector<float>({1.0, 2.0, 3.0})))); using TF = decltype(f.omega.in(sqlpp::value_list(std::vector<float>({1.0, 2.0, 3.0}))));
using TT = decltype(t.beta.in(sqlpp::value_list(std::vector<std::string>({"a", "b", "c"})))); using TT = decltype(t.beta.in(sqlpp::value_list(std::vector<std::string>({"a", "b", "c"}))));
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TF>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement");
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");
@ -88,15 +88,15 @@ int main()
using TI = decltype(t.alpha.not_in(1, 2, 3)); using TI = decltype(t.alpha.not_in(1, 2, 3));
using TF = decltype(f.omega.not_in(1.0, 2.0, 3.0)); using TF = decltype(f.omega.not_in(1.0, 2.0, 3.0));
using TT = decltype(t.beta.not_in("a", "b", "c")); using TT = decltype(t.beta.not_in("a", "b", "c"));
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TF>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement");
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");
@ -107,15 +107,15 @@ int main()
using TI = decltype(t.alpha.not_in(sqlpp::value_list(std::vector<int>({1, 2, 3})))); using TI = decltype(t.alpha.not_in(sqlpp::value_list(std::vector<int>({1, 2, 3}))));
using TF = decltype(f.omega.not_in(sqlpp::value_list(std::vector<float>({1.0, 2.0, 3.0})))); using TF = decltype(f.omega.not_in(sqlpp::value_list(std::vector<float>({1.0, 2.0, 3.0}))));
using TT = decltype(t.beta.not_in(sqlpp::value_list(std::vector<std::string>({"a", "b", "c"})))); using TT = decltype(t.beta.not_in(sqlpp::value_list(std::vector<std::string>({"a", "b", "c"}))));
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TF>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement");
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");
@ -124,7 +124,7 @@ int main()
// Test like // Test like
{ {
using TT = decltype(t.beta.like("%c%")); using TT = decltype(t.beta.like("%c%"));
static_assert(sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement");
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");
@ -141,15 +141,15 @@ int main()
static_assert(std::is_same<TI, TTI>::value, "type requirement"); static_assert(std::is_same<TI, TTI>::value, "type requirement");
static_assert(std::is_same<TF, TTF>::value, "type requirement"); static_assert(std::is_same<TF, TTF>::value, "type requirement");
static_assert(std::is_same<TT, TTT>::value, "type requirement"); static_assert(std::is_same<TT, TTT>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TF>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement");
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");
@ -166,15 +166,15 @@ int main()
static_assert(std::is_same<TI, TTI>::value, "type requirement"); static_assert(std::is_same<TI, TTI>::value, "type requirement");
static_assert(std::is_same<TF, TTF>::value, "type requirement"); static_assert(std::is_same<TF, TTF>::value, "type requirement");
static_assert(std::is_same<TT, TTT>::value, "type requirement"); static_assert(std::is_same<TT, TTT>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TF>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement");
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");
@ -187,11 +187,11 @@ int main()
{ {
using TI = decltype(exists(select(t.alpha).from(t))); using TI = decltype(exists(select(t.alpha).from(t)));
using TT = decltype(exists(select(t.beta).from(t))); using TT = decltype(exists(select(t.beta).from(t)));
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TT>::value, "type requirement");
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");
@ -206,17 +206,17 @@ int main()
using TI = decltype(any(select(t.alpha).from(t))); using TI = decltype(any(select(t.alpha).from(t)));
using TT = decltype(any(select(t.beta).from(t))); using TT = decltype(any(select(t.beta).from(t)));
using TF = decltype(any(select(f.omega).from(f))); using TF = decltype(any(select(f.omega).from(f)));
static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_multi_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t<TI>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_multi_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t<TF>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TF>::value, "tFpe requirement"); static_assert(sqlpp::is_numeric_t<TF>::value, "tFpe requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_multi_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t<TT>::value, "type requirement");
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_integral_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_integral_t<TT>::value, "type requirement");
@ -229,18 +229,18 @@ int main()
using TI = decltype(some(select(t.alpha).from(t))); using TI = decltype(some(select(t.alpha).from(t)));
using TT = decltype(some(select(t.beta).from(t))); using TT = decltype(some(select(t.beta).from(t)));
using TF = decltype(some(select(f.omega).from(f))); using TF = decltype(some(select(f.omega).from(f)));
static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_multi_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t<TI>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TI>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_multi_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t<TF>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_text_t<TF>::value, "type requirement");
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_named_expression_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_multi_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_multi_expression_t<TT>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<TT>::value, "type requirement"); static_assert(not 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");
@ -254,11 +254,11 @@ int main()
{ {
using TI = decltype(avg(t.alpha)); using TI = decltype(avg(t.alpha));
using TF = decltype(avg(f.omega)); using TF = decltype(avg(f.omega));
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TI>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_integral_t<TF>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
@ -269,15 +269,15 @@ int main()
using TI = decltype(count(t.alpha)); using TI = decltype(count(t.alpha));
using TT = decltype(count(t.beta)); using TT = decltype(count(t.beta));
using TF = decltype(count(f.omega)); using TF = decltype(count(f.omega));
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_floating_point_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TF>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_floating_point_t<TF>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TT>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TT>::value, "type requirement");
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");
@ -288,15 +288,15 @@ int main()
using TI = decltype(max(t.alpha)); using TI = decltype(max(t.alpha));
using TF = decltype(max(f.omega)); using TF = decltype(max(f.omega));
using TT = decltype(max(t.beta)); using TT = decltype(max(t.beta));
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_floating_point_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_integral_t<TF>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TT>::value, "type requirement");
static_assert(sqlpp::is_text_t<TT>::value, "type requirement"); static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
} }
@ -306,15 +306,15 @@ int main()
using TI = decltype(min(t.alpha)); using TI = decltype(min(t.alpha));
using TF = decltype(min(f.omega)); using TF = decltype(min(f.omega));
using TT = decltype(min(t.beta)); using TT = decltype(min(t.beta));
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_floating_point_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_integral_t<TF>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(not sqlpp::is_numeric_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<TT>::value, "type requirement");
static_assert(sqlpp::is_text_t<TT>::value, "type requirement"); static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
} }
@ -323,11 +323,11 @@ int main()
{ {
using TI = decltype(sum(t.alpha)); using TI = decltype(sum(t.alpha));
using TF = decltype(sum(f.omega)); using TF = decltype(sum(f.omega));
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TI>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_floating_point_t<TI>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<TF>::value, "type requirement"); static_assert(sqlpp::is_selectable_t<TF>::value, "type requirement");
static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<TF>::value, "type requirement"); static_assert(not sqlpp::is_integral_t<TF>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
@ -342,13 +342,13 @@ int main()
using TI = decltype(sqlpp::value(7)); using TI = decltype(sqlpp::value(7));
using TF = decltype(sqlpp::value(1.5)); using TF = decltype(sqlpp::value(1.5));
using TT = decltype(sqlpp::value("cheesecake")); using TT = decltype(sqlpp::value("cheesecake"));
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_text_t<TT>::value, "type requirement"); static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
} }
@ -358,13 +358,13 @@ int main()
using TI = decltype(flatten(t.alpha, db)); using TI = decltype(flatten(t.alpha, db));
using TF = decltype(flatten(f.omega, db)); using TF = decltype(flatten(f.omega, db));
using TT = decltype(flatten(t.beta, db)); using TT = decltype(flatten(t.beta, db));
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_text_t<TT>::value, "type requirement"); static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
} }
@ -382,13 +382,13 @@ int main()
static_assert(std::is_same<TI, TIN>::value, "type_requirement"); static_assert(std::is_same<TI, TIN>::value, "type_requirement");
static_assert(std::is_same<TF, TFN>::value, "type_requirement"); static_assert(std::is_same<TF, TFN>::value, "type_requirement");
static_assert(std::is_same<TT, TTN>::value, "type_requirement"); static_assert(std::is_same<TT, TTN>::value, "type_requirement");
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_text_t<TT>::value, "type requirement"); static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
} }
@ -398,20 +398,20 @@ int main()
using TI = decltype(sqlpp::verbatim<sqlpp::bigint>("42")); using TI = decltype(sqlpp::verbatim<sqlpp::bigint>("42"));
using TF = decltype(sqlpp::verbatim<sqlpp::floating_point>("1.5")); using TF = decltype(sqlpp::verbatim<sqlpp::floating_point>("1.5"));
using TT = decltype(sqlpp::verbatim<sqlpp::text>("cheesecake")); using TT = decltype(sqlpp::verbatim<sqlpp::text>("cheesecake"));
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement"); static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TB>::value, "type requirement");
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement"); static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TI>::value, "type requirement");
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement"); static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<TT>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<TT>::value, "type requirement");
static_assert(sqlpp::is_text_t<TT>::value, "type requirement"); static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
} }
// test verbatim_table // test verbatim_table
{ {
using T = decltype(sqlpp::verbatim_table("cheesecake")); using T = decltype(sqlpp::verbatim_table("cheesecake"));
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement"); static_assert(sqlpp::is_table_t<T>::value, "type requirement");
} }
@ -419,7 +419,7 @@ int main()
// test verbatim_table alias // test verbatim_table alias
{ {
using T = decltype(sqlpp::verbatim_table("cheesecake").as(kaesekuchen)); using T = decltype(sqlpp::verbatim_table("cheesecake").as(kaesekuchen));
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(not sqlpp::is_selectable_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_table_t<T>::value, "type requirement"); static_assert(sqlpp::is_table_t<T>::value, "type requirement");
static_assert(sqlpp::is_alias_t<T>::value, "type requirement"); static_assert(sqlpp::is_alias_t<T>::value, "type requirement");

View File

@ -179,6 +179,9 @@ int main()
printer.reset(); printer.reset();
std::cerr << serialize(x, printer).str() << std::endl; std::cerr << serialize(x, printer).str() << std::endl;
printer.reset();
std::cerr << serialize(select(all_of(t)).from(t).where(t.alpha.in(select(f.epsilon).from(f).where(true))), printer).str() << std::endl;
return 0; return 0;

View File

@ -41,6 +41,12 @@ struct MockDbT: public sqlpp::connection
{ {
std::ostringstream _os; std::ostringstream _os;
_serializer_context_t() = default;
_serializer_context_t(const _serializer_context_t& rhs)
{
_os << rhs._os.str();
}
std::string str() const std::string str() const
{ {
return _os.str(); return _os.str();
@ -159,8 +165,6 @@ struct MockDbT: public sqlpp::connection
template<typename PreparedInsert> template<typename PreparedInsert>
size_t run_prepared_insert(const PreparedInsert& x) size_t run_prepared_insert(const PreparedInsert& x)
{ {
_serializer_context_t context;
::sqlpp::serialize(x, context);
return 0; return 0;
} }
@ -175,8 +179,6 @@ struct MockDbT: public sqlpp::connection
template<typename PreparedSelect> template<typename PreparedSelect>
result_t run_prepared_select(PreparedSelect& x) result_t run_prepared_select(PreparedSelect& x)
{ {
_serializer_context_t context;
::sqlpp::serialize(x, context);
return {}; return {};
} }

View File

@ -81,9 +81,9 @@ int main()
using Exp = decltype((t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha)) or t.gamma != parameter(t.gamma)); using Exp = decltype((t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha)) or t.gamma != parameter(t.gamma));
using T = sqlpp::make_parameter_list_t<Exp>; using T = sqlpp::make_parameter_list_t<Exp>;
T npl; T npl;
static_assert(std::is_same<typename sqlpp::value_type_of<decltype(t.alpha)>::_parameter_t, decltype(npl.alpha)>::value, "type requirement"); static_assert(std::is_same<sqlpp::parameter_value_t<sqlpp::value_type_of<decltype(t.alpha)>>, decltype(npl.alpha)>::value, "type requirement");
static_assert(std::is_same<typename sqlpp::value_type_of<decltype(t.beta)>::_parameter_t, decltype(npl.beta)>::value, "type requirement"); static_assert(std::is_same<sqlpp::parameter_value_t<sqlpp::value_type_of<decltype(t.beta)>>, decltype(npl.beta)>::value, "type requirement");
static_assert(std::is_same<typename sqlpp::value_type_of<decltype(t.gamma)>::_parameter_t, decltype(npl.gamma)>::value, "type requirement"); static_assert(std::is_same<sqlpp::parameter_value_t<sqlpp::value_type_of<decltype(t.gamma)>>, decltype(npl.gamma)>::value, "type requirement");
} }
// Wonderful, now take a look at the parameter list of a select // Wonderful, now take a look at the parameter list of a select
@ -96,9 +96,9 @@ int main()
using T = sqlpp::make_parameter_list_t<S>; using T = sqlpp::make_parameter_list_t<S>;
T npl; T npl;
static_assert(std::is_same<typename sqlpp::value_type_of<decltype(t.alpha)>::_parameter_t, decltype(npl.alpha)>::value, "type requirement"); static_assert(std::is_same<sqlpp::parameter_value_t<sqlpp::value_type_of<decltype(t.alpha)>>, decltype(npl.alpha)>::value, "type requirement");
static_assert(std::is_same<typename sqlpp::value_type_of<decltype(t.beta)>::_parameter_t, decltype(npl.beta)>::value, "type requirement"); static_assert(std::is_same<sqlpp::parameter_value_t<sqlpp::value_type_of<decltype(t.beta)>>, decltype(npl.beta)>::value, "type requirement");
static_assert(std::is_same<typename sqlpp::value_type_of<decltype(t.gamma)>::_parameter_t, decltype(npl.gamma)>::value, "type requirement"); static_assert(std::is_same<sqlpp::parameter_value_t<sqlpp::value_type_of<decltype(t.gamma)>>, decltype(npl.gamma)>::value, "type requirement");
npl.alpha = 7; npl.alpha = 7;
auto x = npl; auto x = npl;
x = npl; x = npl;

View File

@ -43,7 +43,7 @@ int main()
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)).from(t).where(true))) for (const auto& row : db(select(all_of(t), t.beta.like("")).from(t).where(true)))
{ {
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");

Some files were not shown because too many files have changed in this diff Show More