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.
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)
enable_testing()
@ -34,10 +38,11 @@ elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
endif ()
set(include_dir "${PROJECT_SOURCE_DIR}/include")
file(GLOB_RECURSE sqlpp_headers ${include_dir}/*.h)
include_directories(${include_dir})
file(GLOB_RECURSE sqlpp_headers "${include_dir}/*.h")
include_directories("${include_dir}")
add_subdirectory(tests)
add_subdirectory(test_constraints)
add_subdirectory(examples)
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
* Ulrich Küttler: Feedback and extensions
* Metafeed GmbH: Production code using 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.

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
Upcoming talks at
Upcoming talks/workshops) at
* 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
* 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.4 on Ubuntu-12.4
* g++-4.8 on Ubuntu-12.4
* g++-4.8 on cygwin 64bit
* g++-4.9 on Debian Unstable
__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>
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>;
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");

View File

@ -41,7 +41,7 @@ namespace sqlpp
template<typename AliasProvider>
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>
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>;
struct _name_t

View File

@ -40,7 +40,7 @@ namespace sqlpp
template<typename Lhs, typename Rhs>
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 _lhs_t = Lhs;

View File

@ -32,13 +32,14 @@
namespace sqlpp
{
template<typename Flag, typename Expr>
struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>>,
struct avg_t:
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 _recursive_traits = make_recursive_traits<Expr>;
using _traits = make_traits<floating_point, tag::is_expression, tag::is_selectable>;
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");
struct _name_t
@ -74,7 +75,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << "AVG(";
if (std::is_same<sqlpp::distinct_t, Flag>::value)
if (std::is_same<distinct_t, Flag>::value)
{
serialize(Flag(), context);
context << ' ';
@ -88,13 +89,15 @@ namespace sqlpp
template<typename 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");
return { 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");
return { t };
}

View File

@ -27,18 +27,19 @@
#ifndef 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/sort_order.h>
#include <sqlpp11/expression_fwd.h>
#include <sqlpp11/in_fwd.h>
#include <sqlpp11/is_null_fwd.h>
#include <sqlpp11/wrap_operand.h>
#include <sqlpp11/wrap_operand_fwd.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
// basic operators
template<typename Base, template<typename> class IsCorrectValueType>
template<typename Expr, typename ValueType>
struct basic_expression_operators
{
template<typename T>
@ -47,107 +48,107 @@ namespace sqlpp
static constexpr bool value =
(is_expression_t<T>::value // expressions are OK
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>
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>;
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>
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>;
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>
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>;
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>
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>;
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>
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>;
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>
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>;
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...
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");
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>
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");
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
{
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
struct boolean
{
using _traits = make_traits<boolean, ::sqlpp::tag::is_boolean, ::sqlpp::tag::is_value_type>;
using _tag = ::sqlpp::tag::is_boolean;
using _traits = make_traits<boolean, tag::is_value_type>;
using _tag = tag::is_boolean;
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 _cpp_value_type = typename _value_type::_cpp_value_type;
_parameter_t():
parameter_value_t():
_value(false),
_is_null(true)
{}
_parameter_t(const _cpp_value_type& value):
parameter_value_t(const _cpp_value_type& value):
_value(value),
_is_null(false)
{}
_parameter_t& operator=(const _cpp_value_type& value)
parameter_value_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)
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
{
if (t._is_trivial())
{
@ -80,7 +87,7 @@ namespace sqlpp
return *this;
}
_parameter_t& operator=(const std::nullptr_t&)
parameter_value_t& operator=(const std::nullptr_t&)
{
_value = false;
_is_null = true;
@ -110,18 +117,13 @@ namespace sqlpp
bool _is_null;
};
template<typename T>
struct _is_valid_operand
{
static constexpr bool value =
is_expression_t<T>::value // expressions are OK
and is_boolean_t<T>::value // the correct value type is required, of course
;
};
// boolean expression operators
template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_boolean_t>
struct expression_operators<Base, boolean>: public basic_expression_operators<Base, boolean>
{
template<typename T>
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
{
@ -146,12 +148,13 @@ namespace sqlpp
}
};
// boolean column operators
template<typename Base>
struct column_operators
struct column_operators<Base, boolean>
{
};
};
// boolean result field
template<typename Db, typename 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
{
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 _recursive_traits = make_recursive_traits<>;

View File

@ -42,13 +42,14 @@
namespace sqlpp
{
template<typename Table, typename ColumnSpec>
struct column_t: public value_type_of<ColumnSpec>::template expression_operators<column_t<Table, ColumnSpec>>,
public value_type_of<ColumnSpec>::template column_operators<column_t<Table, ColumnSpec>>
struct column_t:
public expression_operators<column_t<Table, ColumnSpec>, value_type_of<ColumnSpec>>,
public column_operators<column_t<Table, ColumnSpec>, value_type_of<ColumnSpec>>
{
struct _traits
{
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
@ -58,7 +59,9 @@ namespace sqlpp
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<Table>;
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;
@ -66,7 +69,7 @@ namespace sqlpp
using _name_t = typename _spec_t::_name_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(const column_t&) = default;
@ -90,22 +93,22 @@ namespace sqlpp
auto operator =(T t) const -> assignment_t<column_t, 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}} };
}
auto operator =(sqlpp::null_t) const
->assignment_t<column_t, sqlpp::null_t>
auto operator =(null_t) const
->assignment_t<column_t, null_t>
{
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
->assignment_t<column_t, sqlpp::default_value_t>
auto operator =(default_value_t) const
->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
template<typename First, typename... Args>
struct concat_t: public value_type_of<First>::template expression_operators<concat_t<First, Args...>>,
struct concat_t:
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...>;
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
{
static constexpr const char* _get_name() { return "CONCAT"; }

View File

@ -33,14 +33,24 @@
namespace sqlpp
{
template<typename Flag, typename Expr>
struct count_t: public sqlpp::integral::template expression_operators<count_t<Flag, Expr>>,
struct count_t:
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 _recursive_traits = make_recursive_traits<Expr>;
using _traits = make_traits<integral, tag::is_expression, tag::is_selectable>;
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
{
@ -75,7 +85,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << "COUNT(";
if (std::is_same<sqlpp::distinct_t, Flag>::value)
if (std::is_same<distinct_t, Flag>::value)
{
serialize(Flag(), context);
context << ' ';
@ -94,7 +104,7 @@ namespace sqlpp
}
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");
return { t };

View File

@ -43,9 +43,9 @@ namespace sqlpp
};
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>

View File

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

View File

@ -73,7 +73,7 @@ namespace sqlpp
template<typename E, typename SET>
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>
@ -85,7 +85,7 @@ namespace sqlpp
template<typename L, typename R>
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>
@ -100,7 +100,7 @@ namespace sqlpp
template<typename L, typename R>
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>
@ -118,7 +118,7 @@ namespace sqlpp
template<typename L, typename R>
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>
@ -174,7 +174,7 @@ namespace sqlpp
template<typename... T>
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<>
@ -197,7 +197,7 @@ namespace sqlpp
template<typename Minuend, typename Subtrahend>
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>
@ -214,7 +214,7 @@ namespace sqlpp
template<typename Lhs, typename Rhs>
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>
@ -232,7 +232,7 @@ namespace sqlpp
template<template<typename> class Transformation, typename T>
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>

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
{
template<typename Select>
struct exists_t: public boolean::template expression_operators<exists_t<Select>>,
struct exists_t:
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>;
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");

View File

@ -39,10 +39,11 @@
namespace sqlpp
{
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 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 _lhs_t = Lhs;
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>
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 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 _lhs_t = Lhs;
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>
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 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>;
unary_expression_t(Rhs rhs):
@ -177,10 +180,11 @@ namespace sqlpp
};
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 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>;
binary_expression_t(Lhs lhs, Rhs rhs):
@ -215,10 +219,11 @@ namespace sqlpp
};
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 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>;
unary_expression_t(Rhs rhs):

View File

@ -37,53 +37,53 @@ namespace sqlpp
{
struct less
{
using _traits = make_traits<::sqlpp::boolean>;
using _traits = make_traits<boolean>;
static constexpr const char* _name = "<";
};
struct less_equal
{
using _traits = make_traits<::sqlpp::boolean>;
using _traits = make_traits<boolean>;
static constexpr const char* _name = "<=";
};
struct equal_to
{
using _traits = make_traits<::sqlpp::boolean>;
using _traits = make_traits<boolean>;
};
struct not_equal_to
{
using _traits = make_traits<::sqlpp::boolean>;
using _traits = make_traits<boolean>;
};
struct greater_equal
{
using _traits = make_traits<::sqlpp::boolean>;
using _traits = make_traits<boolean>;
static constexpr const char* _name = ">=";
};
struct greater
{
using _traits = make_traits<::sqlpp::boolean>;
using _traits = make_traits<boolean>;
static constexpr const char* _name = ">";
};
struct logical_or
{
using _traits = make_traits<::sqlpp::boolean>;
using _traits = make_traits<boolean>;
static constexpr const char* _name = " OR ";
};
struct logical_and
{
using _traits = make_traits<::sqlpp::boolean>;
using _traits = make_traits<boolean>;
static constexpr const char* _name = " AND ";
};
struct logical_not
{
using _traits = make_traits<::sqlpp::boolean>;
using _traits = make_traits<boolean>;
};
template<typename ValueType>
@ -109,13 +109,13 @@ namespace sqlpp
struct divides
{
using _traits = make_traits<::sqlpp::floating_point>;
using _traits = make_traits<floating_point>;
static constexpr const char* _name = "/";
};
struct modulus
{
using _traits = make_traits<::sqlpp::integral>;
using _traits = make_traits<integral>;
static constexpr const char* _name = "%";
};
@ -208,6 +208,12 @@ namespace sqlpp
template<typename Lhs, typename ValueType, typename 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

View File

@ -51,22 +51,22 @@ namespace sqlpp
template<typename... Tables>
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
{
using _parameters = std::tuple<>;
using _required_tables = ::sqlpp::detail::type_set<>;
using _provided_outer_tables = ::sqlpp::detail::type_set<>;
using _provided_tables = ::sqlpp::detail::type_set<>;
using _extra_tables = ::sqlpp::detail::type_set<Tables...>;
using _can_be_null = std::false_type;
using _required_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _provided_tables = detail::type_set<>;
using _extra_tables = detail::type_set<Tables...>;
using _tags = detail::type_set<>;
};
// FIXME: extra_tables must not require 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(::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(not detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected 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
using _data_t = extra_tables_data_t<Tables...>;
@ -106,7 +106,7 @@ namespace sqlpp
// NO EXTRA TABLES YET
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<>;
// Data
@ -140,15 +140,15 @@ namespace sqlpp
struct _methods_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() {}
template<typename... Args>
auto extra_tables(Args...)
auto extra_tables(Args...) const
-> _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
struct floating_point
{
using _traits = make_traits<floating_point, ::sqlpp::tag::is_floating_point, ::sqlpp::tag::is_value_type>;
using _tag = ::sqlpp::tag::is_floating_point;
using _traits = make_traits<floating_point, tag::is_value_type>;
using _tag = tag::is_floating_point;
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 _cpp_value_type = typename _value_type::_cpp_value_type;
_parameter_t():
parameter_value_t():
_value(0),
_is_null(true)
{}
_parameter_t(const _cpp_value_type& value):
parameter_value_t(const _cpp_value_type& value):
_value(value),
_is_null(false)
{}
_parameter_t& operator=(const _cpp_value_type& value)
parameter_value_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)
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
{
if (t._is_trivial())
{
@ -78,7 +85,7 @@ namespace sqlpp
return *this;
}
_parameter_t& operator=(const std::nullptr_t&)
parameter_value_t& operator=(const std::nullptr_t&)
{
_value = 0;
_is_null = true;
@ -108,104 +115,103 @@ namespace sqlpp
bool _is_null;
};
template<typename T>
struct _is_valid_operand
// floating_point expression operators
template<typename Expr>
struct expression_operators<Expr, floating_point>:
public basic_expression_operators<Expr, floating_point>
{
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 T>
using _is_valid_operand = is_valid_operand<floating_point, T>;
template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
{
template<typename T>
plus_t<Base, floating_point, wrap_operand_t<T>> operator +(T t) const
plus_t<Expr, floating_point, 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), rhs{t} };
return { *static_cast<const Expr*>(this), rhs{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>;
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>
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>;
return { *static_cast<const Base*>(this), rhs{t} };
return { *static_cast<const Expr*>(this), rhs{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>;
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>
struct column_operators
// floating_point 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>>>
using _is_valid_operand = is_valid_operand<floating_point, 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");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
}
template<typename T>
auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, floating_point, wrap_operand_t<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");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
}
template<typename T>
auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<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");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
}
template<typename T>
auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, floating_point, wrap_operand_t<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 Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
}
};
};
// floating_point result field
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>>
{

View File

@ -59,7 +59,7 @@ namespace sqlpp
template<typename Database, typename... Tables>
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 _is_dynamic = is_database<Database>;
@ -79,7 +79,7 @@ namespace sqlpp
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()");
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
}
@ -125,7 +125,7 @@ namespace sqlpp
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<>;
// Data
@ -161,12 +161,12 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename... Tables>
auto from(Tables... tables)
auto from(Tables... tables) const
-> _new_statement_t<from_t<void, Tables...>>
{
static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
@ -174,7 +174,7 @@ namespace sqlpp
}
template<typename... Tables>
auto dynamic_from(Tables... tables)
auto dynamic_from(Tables... tables) const
-> _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");
@ -183,10 +183,10 @@ namespace sqlpp
private:
template<typename Database, typename... Tables>
auto _from_impl(Tables... tables)
auto _from_impl(Tables... tables) const
-> _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 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_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/avg.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/eval.h>
namespace sqlpp
{
@ -53,44 +55,6 @@ namespace sqlpp
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>
auto flatten(const Expression& exp, Db& db) -> verbatim_t<value_type_of<Expression>>
{
@ -115,7 +79,7 @@ namespace sqlpp
template<typename Container>
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 _container_t = Container;

View File

@ -59,16 +59,16 @@ namespace sqlpp
template<typename Database, typename... Expressions>
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 _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(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
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(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
}
@ -135,7 +135,7 @@ namespace sqlpp
// NO GROUP BY YET
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<>;
// Data
@ -170,23 +170,23 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename... Args>
auto group_by(Args... args)
auto group_by(Args... args) const
-> _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>
auto dynamic_group_by(Args... args)
auto dynamic_group_by(Args... args) const
-> _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");
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>
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 _is_dynamic = is_database<Database>;
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
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(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
}
@ -133,7 +133,7 @@ namespace sqlpp
// NO HAVING YET
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<>;
// Data
@ -168,23 +168,23 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename... Args>
auto having(Args... args)
auto having(Args... args) const
-> _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>
auto dynamic_having(Args... args)
auto dynamic_having(Args... args) const
-> _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");
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
{
template<bool NotInverted, typename Operand, typename... Args>
struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>,
struct in_t:
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...>;
static constexpr bool _inverted = not NotInverted;
@ -78,6 +79,10 @@ namespace sqlpp
{
serialize(t._operand, context);
context << (t._inverted ? " NOT IN(" : " IN(");
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 << ')';
return context;

View File

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

View File

@ -49,7 +49,7 @@ namespace sqlpp
{
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<>;
};
};
@ -62,7 +62,7 @@ namespace sqlpp
using _column_t = Column;
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 _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>;
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/simple_column.h>
#include <sqlpp11/no_data.h>
#include <sqlpp11/policy_update.h>
namespace sqlpp
{
@ -105,7 +106,7 @@ namespace sqlpp
insert_list_data_t(Assignments... assignments):
_assignments(assignments...),
_columns({assignments._lhs}...),
_values({assignments._rhs}...)
_values(assignments._rhs...)
{}
insert_list_data_t(const insert_list_data_t&) = default;
@ -115,8 +116,8 @@ namespace sqlpp
~insert_list_data_t() = default;
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<typename Assignments::_rhs_t...> _values;
std::tuple<simple_column_t<lhs_t<Assignments>>...> _columns;
std::tuple<rhs_t<Assignments>...> _values;
interpretable_list_t<Database> _dynamic_columns;
interpretable_list_t<Database> _dynamic_values;
};
@ -124,8 +125,8 @@ namespace sqlpp
template<typename Database, typename... Assignments>
struct insert_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::is_insert_list>;
using _recursive_traits = make_recursive_traits<typename Assignments::_lhs_t..., typename Assignments::_rhs_t...>;
using _traits = make_traits<no_value_t, tag::is_insert_list>;
using _recursive_traits = make_recursive_traits<lhs_t<Assignments>..., rhs_t<Assignments>...>;
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_assignment_t<Assignment>::value, "add() arguments require to be assigments");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_t...>;
static_assert(not detail::is_element_of<typename Assignment::_lhs_t, _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");
using _assigned_columns = detail::make_type_set_t<lhs_t<Assignments>...>;
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(not must_not_insert_t<lhs_t<Assignment>>::value, "add() argument must not be used in insert");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table");
using ok = ::sqlpp::detail::all_t<
using ok = detail::all_t<
_is_dynamic::value,
is_assignment_t<Assignment>::value>;
@ -168,7 +169,7 @@ namespace sqlpp
template<typename Assignment>
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);
}
@ -225,7 +226,7 @@ namespace sqlpp
template<typename... Columns>
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 _value_tuple_t = typename column_list_data_t<Columns...>::_value_tuple_t;
@ -241,13 +242,13 @@ namespace sqlpp
template<typename... Assignments>
void add(Assignments... assignments)
{
static_assert(::sqlpp::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>...>;
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<lhs_t<Assignments>>...>;
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");
using ok = ::sqlpp::detail::all_t<
::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value,
using ok = detail::all_t<
detail::all_t<is_assignment_t<Assignments>::value...>::value,
_args_correct::value>;
_add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
@ -257,7 +258,7 @@ namespace sqlpp
template<typename... 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>
@ -294,7 +295,7 @@ namespace sqlpp
// NO INSERT COLUMNS/VALUES YET
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<>;
// Data
@ -329,28 +330,28 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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_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>
{
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>
auto columns(Columns... columns)
auto columns(Columns... columns) const
-> _new_statement_t<column_list_t<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(::sqlpp::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");
using _column_required_tables = ::sqlpp::detail::make_joined_set_t<required_tables_of<Columns>...>;
static_assert(not detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected 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(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 = detail::make_joined_set_t<required_tables_of<Columns>...>;
static_assert(_column_required_tables::size::value == 1, "columns() contains columns from several tables");
using _table = typename detail::first_arg_t<Columns...>::_table;
@ -358,43 +359,43 @@ namespace sqlpp
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()");
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>
auto set(Assignments... assignments)
auto set(Assignments... assignments) const
-> _new_statement_t<insert_list_t<void, Assignments...>>
{
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 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()");
return _set_impl<void>(assignments...);
}
template<typename... Assignments>
auto dynamic_set(Assignments... assignments)
auto dynamic_set(Assignments... assignments) const
-> _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(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...);
}
private:
template<typename Database, typename... Assignments>
auto _set_impl(Assignments... assignments)
auto _set_impl(Assignments... assignments) const
-> _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(sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment 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()");
static_assert(not detail::has_duplicates<lhs_t<Assignments>...>::value, "at least one duplicate column detected 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()");
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");
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,32 +40,39 @@ namespace sqlpp
// integral value type
struct integral
{
using _traits = make_traits<integral, ::sqlpp::tag::is_integral, ::sqlpp::tag::is_value_type>;
using _tag = ::sqlpp::tag::is_integral;
using _traits = make_traits<integral, tag::is_value_type>;
using _tag = tag::is_integral;
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_t():
parameter_value_t():
_value(0),
_is_null(true)
{}
explicit _parameter_t(const _cpp_value_type& value):
explicit parameter_value_t(const _cpp_value_type& value):
_value(value),
_is_null(false)
{}
_parameter_t& operator=(const _cpp_value_type& value)
parameter_value_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)
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
{
if (t._is_trivial())
{
@ -109,18 +116,13 @@ namespace sqlpp
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
;
};
// integral expression operators
template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
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
{
@ -196,16 +198,20 @@ namespace sqlpp
};
// integral column operators
template<typename Base>
struct column_operators
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} } };
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
}
template<typename T>
@ -214,7 +220,7 @@ namespace sqlpp
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} } };
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
}
template<typename T>
@ -223,7 +229,7 @@ namespace sqlpp
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} } };
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
}
template<typename T>
@ -232,12 +238,11 @@ namespace sqlpp
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} } };
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
}
};
};
// integral result field
template<typename Db, typename 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;
};
// ostream operator for integral result field
template<typename Db, typename FieldSpec>
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>
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&
{
// 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)
-> 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() = 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);
}
// 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>
auto serialize(Context& context) const
-> 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);
}
@ -74,7 +74,7 @@ namespace sqlpp
private:
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 _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
};
@ -87,9 +87,9 @@ namespace sqlpp
_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;
}

View File

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

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<typename Database, typename Table>
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>;
static_assert(is_table_t<Table>::value, "argument has to be a table");
@ -103,7 +103,7 @@ namespace sqlpp
// NO INTO YET
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<>;
// Data
@ -138,7 +138,7 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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()
{
@ -146,10 +146,10 @@ namespace sqlpp
}
template<typename... Args>
auto into(Args... args)
auto into(Args... args) const
-> _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
{
template<bool NotInverted, typename Operand>
struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>,
struct is_null_t:
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>;
static constexpr bool _inverted = not NotInverted;
struct _value_type: public boolean
{
using _is_named_expression = std::true_type;
};
struct _name_t
{
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>
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)
{

View File

@ -73,7 +73,7 @@ namespace sqlpp
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 _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(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");
@ -94,6 +94,8 @@ namespace sqlpp
-> set_on_t<on_t<void, Expr...>>
{
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,
_rhs,
{std::tuple<Expr...>{expr...}}

View File

@ -34,15 +34,13 @@
namespace sqlpp
{
template<typename Operand, typename Pattern>
struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>,
struct like_t:
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>;
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
{
static constexpr const char* _get_name() { return "LIKE"; }
@ -50,6 +48,8 @@ namespace sqlpp
struct _member_t
{
T like;
T& operator()() { return like; }
const T& operator()() const { return like; }
};
};

View File

@ -54,7 +54,7 @@ namespace sqlpp
template<typename Limit>
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>;
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
@ -105,7 +105,7 @@ namespace sqlpp
template<typename Limit>
dynamic_limit_data_t(Limit value):
_initialized(true),
_value(typename wrap_operand<Limit>::type(value))
_value(wrap_operand_t<Limit>(value))
{
}
@ -123,7 +123,7 @@ namespace sqlpp
template<typename Database>
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<>;
// Data
@ -137,7 +137,7 @@ namespace sqlpp
void set(Limit value)
{
// 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._initialized = true;
}
@ -172,7 +172,7 @@ namespace sqlpp
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<>;
// Data
@ -207,22 +207,22 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename Arg>
auto limit(Arg arg)
-> _new_statement_t<limit_t<typename wrap_operand<Arg>::type>>
auto limit(Arg arg) const
-> _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>>
{
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
{
template<typename Expr>
struct max_t: public value_type_of<Expr>::template expression_operators<max_t<Expr>>,
struct max_t:
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 _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_expression_t<Expr>::value, "max() requires a value expression as argument");
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr, aggregate_function>;
struct _name_t
{
@ -82,7 +81,7 @@ namespace sqlpp
template<typename 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 };
}

View File

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

View File

@ -44,7 +44,7 @@ namespace sqlpp
using _traits = make_traits<no_value_t>;
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):
_columns(columns)
@ -66,20 +66,16 @@ namespace sqlpp
return { *this };
}
using _value_type = no_value_t;
using _is_multi_column = std::true_type;
std::tuple<Columns...> _columns;
};
template<typename AliasProvider, typename... Columns>
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...>;
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;
@ -101,12 +97,6 @@ namespace sqlpp
multi_column_alias_t& operator=(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;
};

View File

@ -50,16 +50,16 @@ namespace sqlpp
named_interpretable_t& operator=(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);
}
// 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>
auto serialize(Context& context) const
-> 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);
}
@ -77,7 +77,7 @@ namespace sqlpp
private:
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 _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
virtual std::string _get_name() const = 0;
@ -91,9 +91,9 @@ namespace sqlpp
_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;
}

View File

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

View File

@ -35,7 +35,7 @@ namespace sqlpp
{
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<>;
struct _name_t {};

View File

@ -54,7 +54,7 @@ namespace sqlpp
template<typename Offset>
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>;
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
@ -105,7 +105,7 @@ namespace sqlpp
template<typename Offset>
dynamic_offset_data_t(Offset value):
_initialized(true),
_value(typename wrap_operand<Offset>::type(value))
_value(wrap_operand_t<Offset>(value))
{
}
@ -123,7 +123,7 @@ namespace sqlpp
template<typename Database>
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<>;
// Data
@ -137,7 +137,7 @@ namespace sqlpp
void set(Offset value)
{
// 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._initialized = true;
}
@ -171,9 +171,9 @@ namespace sqlpp
void set_offset(Offset value)
{
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Offset>::type;
static_cast<typename Policies::_statement_t*>(this)->_offset()._value = arg_t{value};
static_cast<typename Policies::_statement_t*>(this)->_offset()._initialized = true;
using arg_t = wrap_operand_t<Offset>;
static_cast<derived_statement_t<Policies>*>(this)->_offset()._value = arg_t{value};
static_cast<derived_statement_t<Policies>*>(this)->_offset()._initialized = true;
}
};
@ -183,7 +183,7 @@ namespace sqlpp
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<>;
// Data
@ -218,22 +218,22 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename Arg>
auto offset(Arg arg)
-> _new_statement_t<offset_t<typename wrap_operand<Arg>::type>>
auto offset(Arg arg) const
-> _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>>
{
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>;
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>
void add(E expr)

View File

@ -59,16 +59,16 @@ namespace sqlpp
template<typename Database, typename... Expressions>
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 _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(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
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(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
}
@ -135,7 +135,7 @@ namespace sqlpp
// NO ORDER BY YET
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<>;
// Data
@ -170,23 +170,23 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename... Args>
auto order_by(Args... args)
auto order_by(Args... args) const
-> _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>
auto dynamic_order_by(Args... args)
auto dynamic_order_by(Args... args) const
-> _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");
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
{
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>;
struct _recursive_traits
@ -44,10 +45,10 @@ namespace sqlpp
using _provided_outer_tables = detail::type_set<>;
using _required_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()
{}
@ -75,7 +76,7 @@ namespace sqlpp
auto parameter(const 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 {};
}

View File

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

View File

@ -32,7 +32,7 @@
namespace sqlpp
{
template<typename ValueType, typename Db, typename Field>
template<typename ValueType, typename Db, typename FieldSpec>
struct 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 _required_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>
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;
@ -66,9 +66,9 @@ namespace sqlpp
template<std::size_t index, typename AliasProvider, typename Db, typename... 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;

View File

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

View File

@ -54,7 +54,7 @@ namespace sqlpp
template<typename 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;
};
}
@ -152,17 +152,17 @@ namespace sqlpp
template<typename Database, typename... Columns>
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 _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>;
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(::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(not ::sqlpp::detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected");
static_assert(not detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected");
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 detail::has_duplicates<typename Columns::_name_t...>::value, "at least one duplicate name detected");
struct _column_type {};
@ -183,14 +183,14 @@ namespace sqlpp
void add(NamedExpression namedExpression)
{
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()");
using column_names = ::sqlpp::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");
using column_names = detail::make_type_set_t<typename Columns::_name_t...>;
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_named_expression_t<NamedExpression>::value
is_selectable_t<NamedExpression>::value
>;
_add_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert
@ -238,7 +238,7 @@ namespace sqlpp
template<typename Policies>
struct _result_methods_t
{
using _statement_t = typename Policies::_statement_t;
using _statement_t = derived_statement_t<Policies>;
const _statement_t& _get_statement() const
{
@ -278,7 +278,7 @@ namespace sqlpp
_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(::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);
}
@ -310,7 +310,7 @@ namespace sqlpp
{
_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
{
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<>;
struct _name_t {};
@ -364,23 +364,23 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename... Args>
auto columns(Args... args)
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<void, Args...>>
auto columns(Args... args) const
-> _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>
auto dynamic_columns(Args... args)
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>>
auto dynamic_columns(Args... args) const
-> _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");
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>
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 _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
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(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
}
@ -134,7 +134,7 @@ namespace sqlpp
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<>;
// Data
@ -169,23 +169,23 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename... Args>
auto flags(Args... args)
auto flags(Args... args) const
-> _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>
auto dynamic_flags(Args... args)
auto dynamic_flags(Args... args) const
-> _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");
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... 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,
NamedExpr...>, select_column_spec_t<Select, NamedExpr>...>
{

View File

@ -37,7 +37,7 @@ namespace sqlpp
{
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<>;
};

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<typename Database, typename Table>
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>;
static_assert(is_table_t<Table>::value, "argument has to be a table");
@ -103,7 +103,7 @@ namespace sqlpp
// NO INTO YET
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<>;
// Data
@ -138,15 +138,15 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename... Args>
auto from(Args... args)
auto from(Args... args) const
-> _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>
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>;
struct _name_t

View File

@ -41,7 +41,7 @@ namespace sqlpp
template<typename Expression, sort_type SortType>
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>;
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
>::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>>;
struct _recursive_traits
@ -107,12 +114,9 @@ namespace sqlpp
using _provided_outer_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Policies>...>;
using _can_be_null = detail::any_t<
can_be_null_t<_result_type_provider>::value,
::sqlpp::detail::make_intersect_set_t<
required_tables_of<_result_type_provider>,
provided_outer_tables_of<statement_policies_t>
>::size::value != 0>;
using _tags = typename std::conditional<_can_be_null::value,
detail::type_set<tag::can_be_null>,
detail::type_set<>>::type;
};
};
}
@ -122,16 +126,16 @@ namespace sqlpp
>
struct statement_t:
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 Policies::template _methods_t<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>,
::sqlpp::tag::is_select,
tag::is_select,
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>;
using _recursive_traits = typename _policies_t::_recursive_traits;
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...>>
{
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)
{
@ -198,7 +202,7 @@ namespace sqlpp
template<typename NameData>
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<>;
// Data

View File

@ -32,13 +32,14 @@
namespace sqlpp
{
template<typename Flag, typename Expr>
struct sum_t: public value_type_of<Expr>::template expression_operators<sum_t<Flag, Expr>>,
struct sum_t:
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 _recursive_traits = make_recursive_traits<Expr>;
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
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");
struct _name_t
@ -74,7 +75,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << "SUM(";
if (std::is_same<sqlpp::distinct_t, Flag>::value)
if (std::is_same<distinct_t, Flag>::value)
{
serialize(Flag(), context);
context << ' ';
@ -88,13 +89,15 @@ namespace sqlpp
template<typename 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");
return { 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");
return { t };
}

View File

@ -40,7 +40,9 @@ namespace sqlpp
struct table_base_t {};
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>;
@ -51,7 +53,7 @@ namespace sqlpp
using _provided_tables = detail::type_set<Table>;
using _provided_outer_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");
@ -62,31 +64,31 @@ namespace sqlpp
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 };
}
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 };
}
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 };
}
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 };
}
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 };
}

View File

@ -36,10 +36,11 @@
namespace sqlpp
{
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
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
{
@ -48,13 +49,13 @@ namespace sqlpp
using _provided_tables = detail::type_set<AliasProvider>;
using _provided_outer_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");
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(table)

View File

@ -39,32 +39,39 @@ namespace sqlpp
// text value type
struct text
{
using _traits = make_traits<text, ::sqlpp::tag::is_text, ::sqlpp::tag::is_value_type>;
using _tag = ::sqlpp::tag::is_text;
using _traits = make_traits<text, tag::is_value_type>;
using _tag = tag::is_text;
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 _cpp_value_type = typename _value_type::_cpp_value_type;
_parameter_t():
parameter_value_t():
_value(""),
_is_null(true)
{}
_parameter_t(const _cpp_value_type& value):
parameter_value_t(const _cpp_value_type& value):
_value(value),
_is_null(false)
{}
_parameter_t& operator=(const _cpp_value_type& value)
parameter_value_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)
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
{
if (t._is_trivial())
{
@ -79,7 +86,7 @@ namespace sqlpp
return *this;
}
_parameter_t& operator=(const std::nullptr_t&)
parameter_value_t& operator=(const std::nullptr_t&)
{
_value = "";
_is_null = true;
@ -110,18 +117,13 @@ namespace sqlpp
};
template<typename T>
struct _is_valid_operand
{
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
;
};
// text expression operators
template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_text_t>
struct expression_operators<Base, text>: public basic_expression_operators<Base, text>
{
template<typename T>
using _is_valid_operand = is_valid_operand<text, T>;
template<typename T>
concat_t<Base, wrap_operand_t<T>> operator+(T t) const
{
@ -141,20 +143,24 @@ namespace sqlpp
}
};
// text column operators
template<typename Base>
struct column_operators
struct column_operators<Base, text>
{
template<typename T>
using _is_valid_operand = is_valid_operand<text, T>;
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} } };
return { *static_cast<const Base*>(this), concat_t<Base, wrap_operand_t<T>>{ *static_cast<const Base*>(this), rhs{t} } };
}
};
};
// text result field
template<typename Db, typename 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 tag
{
struct can_be_null{};
struct contains_aggregate_function{};
};
namespace detail
{
template<typename T, typename Enable = void>
struct can_be_null_impl { using type = std::false_type; };
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>
using can_be_null_t = typename detail::can_be_null_impl<T>::type;
namespace tag\
{\
struct can_be_null{};\
};\
namespace detail\
{\
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>\
namespace detail
{
template<typename T, typename Enable = void>
struct contains_aggregate_function_impl { using type = std::false_type; };
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>
using contains_aggregate_function_t = typename detail::contains_aggregate_function_impl<T>::type;
namespace detail
{
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;
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) \
namespace tag\
{\
@ -82,8 +111,7 @@ namespace sqlpp
detail::is_element_of<tag::is_floating_point, typename T::_traits::_tags>::value>;
SQLPP_VALUE_TRAIT_GENERATOR(is_text);
SQLPP_VALUE_TRAIT_GENERATOR(is_wrapped_value);
SQLPP_VALUE_TRAIT_GENERATOR(is_expression);
SQLPP_VALUE_TRAIT_GENERATOR(is_named_expression);
SQLPP_VALUE_TRAIT_GENERATOR(is_selectable);
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression);
SQLPP_VALUE_TRAIT_GENERATOR(is_alias);
SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag);
@ -140,80 +168,35 @@ namespace sqlpp
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>
struct make_parameter_tuple_impl
{
using type = decltype(std::tuple_cat(std::declval<T>()...));
};
template<typename... T>
using make_parameter_tuple_t = typename make_parameter_tuple_impl<T...>::type;
using make_parameter_tuple_t = decltype(std::tuple_cat(std::declval<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>
using cpp_value_type_of = typename value_type_of<T>::_cpp_value_type;
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>
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>
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>
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>
using parameters_of = typename detail::parameters_of_impl<T>::type;
using parameters_of = typename T::_recursive_traits::_parameters;
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>
struct make_traits
@ -221,6 +204,7 @@ namespace sqlpp
using _value_type = ValueType;
using _tags = detail::make_type_set_t<typename ValueType::_tag, Tags...>;
};
template<typename... Arguments>
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 _extra_tables = detail::make_joined_set_t<extra_tables_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

View File

@ -28,7 +28,7 @@
#define SQLPP_UPDATE_H
#include <sqlpp11/statement.h>
#include <sqlpp11/connection.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_update.h>
@ -49,7 +49,7 @@ namespace sqlpp
template<typename Policies>
struct _result_methods_t
{
using _statement_t = typename Policies::_statement_t;
using _statement_t = derived_statement_t<Policies>;
const _statement_t& _get_statement() const
{
@ -109,6 +109,7 @@ namespace sqlpp
constexpr auto dynamic_update(const Database&, Table 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) };
}
}

View File

@ -56,7 +56,7 @@ namespace sqlpp
template<typename Database, typename... Assignments>
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 _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_assignment_t<Assignment>::value, "invalid assignment argument in add()");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_lhs_t...>;
static_assert(not detail::is_element_of<typename Assignment::_lhs_t, _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");
using _assigned_columns = detail::make_type_set_t<lhs_t<Assignments>...>;
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value, "Must not assign value to column twice");
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()");
using ok = ::sqlpp::detail::all_t<
using ok = detail::all_t<
_is_dynamic::value,
is_assignment_t<Assignment>::value>;
@ -130,7 +130,7 @@ namespace sqlpp
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<>;
// Data
@ -165,7 +165,7 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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()
{
@ -173,7 +173,7 @@ namespace sqlpp
}
template<typename... Assignments>
auto set(Assignments... assignments)
auto set(Assignments... assignments) const
-> _new_statement_t<update_list_t<void, Assignments...>>
{
static_assert(sizeof...(Assignments), "at least one assignment expression required in set()");
@ -181,7 +181,7 @@ namespace sqlpp
}
template<typename... Assignments>
auto dynamic_set(Assignments... assignments)
auto dynamic_set(Assignments... assignments) const
-> _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");
@ -190,17 +190,17 @@ namespace sqlpp
private:
template<typename Database, typename... Assignments>
auto _set_impl(Assignments... assignments)
auto _set_impl(Assignments... assignments) const
-> _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(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment 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::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(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");
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>
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 _is_dynamic = is_database<Database>;
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
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_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
}
@ -128,7 +128,7 @@ namespace sqlpp
// NO USING YET
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<>;
// Data
@ -163,23 +163,23 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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() {}
template<typename... Args>
auto using_(Args... args)
auto using_(Args... args) const
-> _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>
auto dynamic_using(Args... args)
auto dynamic_using(Args... args) const
-> _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");
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>;
};

View File

@ -58,14 +58,14 @@ namespace sqlpp
template<typename Database, typename... Expressions>
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 _is_dynamic = is_database<Database>;
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(sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()");
static_assert(detail::none_t<is_assignment_t<Expressions>::value...>::value, "at least one argument is an assignment in where()");
static_assert(detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not valid expression in where()");
// Data
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(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
}
@ -141,7 +141,7 @@ namespace sqlpp
template<>
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<>;
// Data
@ -181,10 +181,10 @@ namespace sqlpp
};
// NO WHERE YET
template<bool Required>
template<bool WhereRequired>
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<>;
// Data
@ -220,26 +220,28 @@ namespace sqlpp
{
using _database_t = typename Policies::_database_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_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>
auto where(Args... args)
auto where(Args... args) const
-> _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>
auto dynamic_where(Args... args)
auto dynamic_where(Args... args) const
-> _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");
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
#include <string>
#include <sqlpp11/wrap_operand_fwd.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/basic_expression_operators.h>
namespace sqlpp
{
@ -38,9 +40,9 @@ namespace sqlpp
struct floating_point;
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 _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 _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 _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 _value_t = std::string;
@ -191,7 +193,7 @@ namespace sqlpp
}
};
template<typename T, typename Enable = void>
template<typename T, typename Enable>
struct wrap_operand
{
using type = T;
@ -221,11 +223,6 @@ namespace sqlpp
using type = text_operand;
};
// FIXME: Need to allow std::ref arguments
template<typename T>
using wrap_operand_t = typename wrap_operand<T>::type;
}
#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(' {', file=header)
print(' using _value_type = ' + NAMESPACE + '::no_value_t;', file=header)
print(' struct _name_t', file=header)
print(' {', 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)
function(test_constraint name pattern)
add_executable(
${name}
"${name}"
EXCLUDE_FROM_ALL
${name}.cpp
"${name}.cpp"
)
add_custom_command(OUTPUT ${name}.out
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
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp
add_custom_command(OUTPUT "${name}.out"
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
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${name}.cpp"
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})
endfunction(testconstraint)
add_dependencies(test_sqlpp_constraints "test_${name}")
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(require_insert "required column is missing")
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)
# Add headers to sources to enable file browsing in IDEs
include_directories(${CMAKE_BINARY_DIR}/tests)
add_executable(${arg} ${arg}.cpp ${sqlpp_headers} ${CMAKE_CURRENT_LIST_DIR}/Sample.h)
add_test(${arg} ${arg})
include_directories("${CMAKE_BINARY_DIR}/tests")
add_executable("${arg}" "${arg}.cpp" ${sqlpp_headers} "${CMAKE_CURRENT_LIST_DIR}/Sample.h")
add_test("${arg}" "${arg}")
endmacro ()
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:
#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
# )
# 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"
# VERBATIM)

View File

@ -50,15 +50,15 @@ int main()
using TI = decltype(t.alpha.in(1, 2, 3));
using TF = decltype(f.omega.in(1.0, 2.0, 3.0));
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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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 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"}))));
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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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 TF = decltype(f.omega.not_in(1.0, 2.0, 3.0));
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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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 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"}))));
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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_t<TT>::value, "type requirement");
static_assert(not sqlpp::is_text_t<TT>::value, "type requirement");
@ -124,7 +124,7 @@ int main()
// Test like
{
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(not sqlpp::is_numeric_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<TF, TTF>::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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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<TF, TTF>::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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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 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(not sqlpp::is_numeric_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(not sqlpp::is_numeric_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 TT = decltype(any(select(t.beta).from(t)));
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_numeric_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_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_numeric_t<TF>::value, "tFpe 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_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(not sqlpp::is_numeric_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 TT = decltype(some(select(t.beta).from(t)));
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_numeric_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(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_floating_point_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_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(not sqlpp::is_integral_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 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(not sqlpp::is_integral_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(not sqlpp::is_integral_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 TT = decltype(count(t.beta));
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_integral_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_integral_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_integral_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 TF = decltype(max(f.omega));
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_integral_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(not sqlpp::is_integral_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(sqlpp::is_text_t<TT>::value, "type requirement");
}
@ -306,15 +306,15 @@ int main()
using TI = decltype(min(t.alpha));
using TF = decltype(min(f.omega));
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_integral_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(not sqlpp::is_integral_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(sqlpp::is_text_t<TT>::value, "type requirement");
}
@ -323,11 +323,11 @@ int main()
{
using TI = decltype(sum(t.alpha));
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_integral_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(not sqlpp::is_integral_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 TF = decltype(sqlpp::value(1.5));
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(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(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(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");
}
@ -358,13 +358,13 @@ int main()
using TI = decltype(flatten(t.alpha, db));
using TF = decltype(flatten(f.omega, 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(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(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(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");
}
@ -382,13 +382,13 @@ int main()
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<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(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(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(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");
}
@ -398,20 +398,20 @@ int main()
using TI = decltype(sqlpp::verbatim<sqlpp::bigint>("42"));
using TF = decltype(sqlpp::verbatim<sqlpp::floating_point>("1.5"));
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(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(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(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");
}
// test verbatim_table
{
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(sqlpp::is_table_t<T>::value, "type requirement");
}
@ -419,7 +419,7 @@ int main()
// test verbatim_table alias
{
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(sqlpp::is_table_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();
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;

View File

@ -41,6 +41,12 @@ struct MockDbT: public sqlpp::connection
{
std::ostringstream _os;
_serializer_context_t() = default;
_serializer_context_t(const _serializer_context_t& rhs)
{
_os << rhs._os.str();
}
std::string str() const
{
return _os.str();
@ -159,8 +165,6 @@ struct MockDbT: public sqlpp::connection
template<typename PreparedInsert>
size_t run_prepared_insert(const PreparedInsert& x)
{
_serializer_context_t context;
::sqlpp::serialize(x, context);
return 0;
}
@ -175,8 +179,6 @@ struct MockDbT: public sqlpp::connection
template<typename PreparedSelect>
result_t run_prepared_select(PreparedSelect& x)
{
_serializer_context_t context;
::sqlpp::serialize(x, context);
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 T = sqlpp::make_parameter_list_t<Exp>;
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<typename sqlpp::value_type_of<decltype(t.beta)>::_parameter_t, 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.alpha)>>, decltype(npl.alpha)>::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<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
@ -96,9 +96,9 @@ int main()
using T = sqlpp::make_parameter_list_t<S>;
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<typename sqlpp::value_type_of<decltype(t.beta)>::_parameter_t, 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.alpha)>>, decltype(npl.alpha)>::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<sqlpp::parameter_value_t<sqlpp::value_type_of<decltype(t.gamma)>>, decltype(npl.gamma)>::value, "type requirement");
npl.alpha = 7;
auto 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");
// 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::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