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

Merge branch 'release/0.30'

Conflicts:
	CMakeLists.txt
	examples/CMakeLists.txt
	examples/select.cpp
	include/sqlpp11/interpret_tuple.h
	include/sqlpp11/type_traits.h
This commit is contained in:
rbock 2015-03-08 20:28:48 +01:00
commit 67b86a7554
195 changed files with 5248 additions and 1257 deletions

53
.clang-format Normal file
View File

@ -0,0 +1,53 @@
Language: Cpp
AccessModifierOffset: -2
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AlwaysBreakTemplateDeclarations: true
AlwaysBreakBeforeMultilineStrings: false
BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BinPackParameters: false
ColumnLimit: 160
ConstructorInitializerAllOnOneLineOrOnePerLine: true
DerivePointerAlignment: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: true
IndentWrappedFunctionNames: false
IndentFunctionDeclarationAfterType: false
MaxEmptyLinesToKeep: 1
KeepEmptyLinesAtTheStartOfBlocks: false
NamespaceIndentation: All
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
SpacesBeforeTrailingComments: 2
Cpp11BracedListStyle: true
Standard: Cpp11
IndentWidth: 2
TabWidth: 2
UseTab: Never
BreakBeforeBraces: Allman
SpacesInParentheses: false
SpacesInAngles: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: true
SpaceBeforeAssignmentOperators: true
ContinuationIndentWidth: 4
CommentPragmas: '^ IWYU pragma:'
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
SpaceBeforeParens: ControlStatements
DisableFormat: false

View File

@ -13,12 +13,20 @@ notifications:
on_failure: always on_failure: always
before_install: before_install:
# install boost 1.50 (headers only), travis currently offers 1.46 and 1.48
- wget http://sourceforge.net/projects/boost/files/boost/1.50.0/boost_1_50_0.tar.bz2/download -O /tmp/boost.tar.bz2
- mkdir -p temp
- cd temp
- tar jxf /tmp/boost.tar.bz2 boost_1_50_0/boost # extract headers only
- sudo mkdir -p /usr/local/include/
- sudo ln -s $PWD/boost_1_50_0/boost /usr/local/include
- cd ..
#install g++-4.8
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- sudo apt-get update - sudo apt-get update
- if [ "$CXX" = "g++" ]; then sudo apt-get install g++-4.8; fi - 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 - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
install: install:
- "mkdir -p $TRAVIS_BUILD_DIR/build/scripts" - "mkdir -p $TRAVIS_BUILD_DIR/build/scripts"
- "cd $TRAVIS_BUILD_DIR/build/scripts" - "cd $TRAVIS_BUILD_DIR/build/scripts"

View File

@ -1,4 +1,4 @@
# Copyright (c) 2013-2014, Roland Bock # Copyright (c) 2013-2015, Roland Bock
# All rights reserved. # All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without modification, # Redistribution and use in source and binary forms, with or without modification,
@ -36,7 +36,7 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}")
endif () endif ()
set(CMAKE_CXX_FLAGS "-Wconversion -Wpedantic ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-Wconversion -Wpedantic -Wshadow ${CMAKE_CXX_FLAGS}")
set(include_dir "${PROJECT_SOURCE_DIR}/include") set(include_dir "${PROJECT_SOURCE_DIR}/include")
file(GLOB_RECURSE sqlpp_headers "${include_dir}/*.h") file(GLOB_RECURSE sqlpp_headers "${include_dir}/*.h")

View File

@ -1,4 +1,4 @@
Copyright (c) 2013-2014, Roland Bock Copyright (c) 2013-2015, Roland Bock
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,9 +1,9 @@
macro (build arg) macro (build arg)
# Add headers to sources to enable file browsing in IDEs # Add headers to sources to enable file browsing in IDEs
include_directories("${CMAKE_SOURCE_DIR}/tests") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../tests")
add_executable("Sqlpp11Example${arg}" "${arg}.cpp" ${sqlpp_headers} "${CMAKE_SOURCE_DIR}/tests/MockDb.h" "${CMAKE_CURRENT_LIST_DIR}/Sample.h") add_executable("Sqlpp11Example${arg}" "${arg}.cpp" ${sqlpp_headers} "${CMAKE_CURRENT_SOURCE_DIR}/../tests/MockDb.h" "${CMAKE_CURRENT_LIST_DIR}/Sample.h")
add_test("${arg}" "${CMAKE_BINARY_DIR}/examples/Sqlpp11Example${arg}") add_test("${arg}" "Sqlpp11Example${arg}")
endmacro () endmacro ()
#build(sample) #build(sample)
@ -11,6 +11,13 @@ build(insert)
build(update) build(update)
build(remove) build(remove)
build(select) build(select)
find_package(Boost 1.50)
if(Boost_FOUND)
MESSAGE(${Boost_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS})
build(ppgen)
endif()
#find_package(PythonInterp REQUIRED) #find_package(PythonInterp REQUIRED)

View File

@ -3,6 +3,7 @@
#include <sqlpp11/table.h> #include <sqlpp11/table.h>
#include <sqlpp11/column_types.h> #include <sqlpp11/column_types.h>
#include <sqlpp11/char_sequence.h>
namespace test namespace test
{ {
@ -10,9 +11,10 @@ namespace test
{ {
struct Id struct Id
{ {
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "id"; } static constexpr const char _literal[] = "id";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -25,9 +27,10 @@ namespace test
}; };
struct Name struct Name
{ {
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "name"; } static constexpr const char _literal[] = "name";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -40,9 +43,10 @@ namespace test
}; };
struct Feature struct Feature
{ {
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "feature"; } static constexpr const char _literal[] = "feature";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -60,9 +64,10 @@ namespace test
TabPerson_::Name, TabPerson_::Name,
TabPerson_::Feature> TabPerson_::Feature>
{ {
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "tab_person"; } static constexpr const char _literal[] = "tab_person";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -76,9 +81,10 @@ namespace test
{ {
struct Id struct Id
{ {
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "id"; } static constexpr const char _literal[] = "id";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -91,9 +97,10 @@ namespace test
}; };
struct Name struct Name
{ {
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "name"; } static constexpr const char _literal[] = "name";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -106,9 +113,10 @@ namespace test
}; };
struct Fatal struct Fatal
{ {
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "fatal"; } static constexpr const char _literal[] = "fatal";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -126,9 +134,10 @@ namespace test
TabFeature_::Name, TabFeature_::Name,
TabFeature_::Fatal> TabFeature_::Fatal>
{ {
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "tab_feature"; } static constexpr const char _literal[] = "tab_feature";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Roland Bock * Copyright (c) 2014-2015 Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

99
examples/ppgen.cpp Normal file
View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com)
* 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 0 // syntax example
SQLPP_DECLARE_TABLE(
(table, \
SQLPP_DROP_IF_EXISTS \
,SQLPP_CREATE_IF_NOT_EXISTS \
,SQLPP_ENGINE("InnoDB") \
,SQLPP_CHARACTER_SET("utf-8") \
,SQLPP_COMMENT("table comments") \
)
,
(id, int, SQLPP_NOT_NULL, SQLPP_PRIMARY_KEY, SQLPP_AUTO_INCREMENT)
(name, varchar(64), SQLPP_NOT_NULL, SQLPP_INDEX("name_index"), SQLPP_DEFAULT("any name"))
(age, int, SQLPP_NOT_NULL, SQLPP_INDEX("age_index"), SQLPP_UNIQUE, SQLPP_COMMENT("some comments"))
)
#endif
#include <sqlpp11/sqlpp11.h>
#include <sqlpp11/ppgen.h>
#include "MockDb.h"
SQLPP_DECLARE_TABLE(
(tab_person)
,
(id , int , SQLPP_AUTO_INCREMENT)
(name , varchar(255), SQLPP_NOT_NULL )
(feature, int , SQLPP_NOT_NULL )
)
SQLPP_DECLARE_TABLE(
(tab_feature)
,
(id , int , SQLPP_AUTO_INCREMENT)
(name , varchar(255), SQLPP_NULL )
(fatal, bool , SQLPP_NOT_NULL )
)
int main() {
MockDb db;
tab_person::tab_person p;
tab_feature::tab_feature f;
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);
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Roland Bock * Copyright (c) 2014-2015 Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Roland Bock * Copyright (c) 2014-2015 Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Roland Bock * Copyright (c) 2014-2015 Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -34,6 +34,9 @@
#include "MockDb.h" #include "MockDb.h"
#include <sqlpp11/sqlpp11.h> #include <sqlpp11/sqlpp11.h>
static constexpr bool some_condition = true;
static constexpr bool some_other_condition = false;
SQLPP_ALIAS_PROVIDER(cheesecake) SQLPP_ALIAS_PROVIDER(cheesecake)
MockDb db; MockDb db;
@ -91,8 +94,8 @@ int main()
#if !0 #if 0
auto s = select(all_of(p)) auto s = select(p.id, p.name, f.id.as(cheesecake))
.from(p, f) .from(p, f)
.where(p.name == any(select(f.name) .where(p.name == any(select(f.name)
.from(f) .from(f)
@ -103,12 +106,32 @@ int main()
.limit(3).offset(7); .limit(3).offset(7);
auto x = s.as(sqlpp::alias::x); auto x = s.as(sqlpp::alias::x);
for (const auto& row : db(select(p.id, x.name) for (const auto& row : db(select(p.id, p.name, all_of(x).as(x))
.from(p.join(x).on(p.feature == x.feature)) .from(p.join(x).on(p.feature == x.cheesecake))
.where(true))) .where(true)))
{ {
int64_t id = row.id; int64_t id = row.id;
std::string name = row.name; std::string name = row.name;
std::string x_name = row.x.name;
int cheesecake = row.x.cheesecake;
}
#endif
#if !0
auto dysel = dynamic_select(db).dynamic_columns(p.name).from(p).dynamic_where();
if (some_condition)
dysel.selected_columns.add(p.feature);
if (some_other_condition)
dysel.where.add(p.id > 17);
for (const auto& row : db(dysel))
{
std::string name = row.name;
std::string feature = row.at("feature");
} }
#endif #endif
@ -129,7 +152,5 @@ int main()
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, Roland Bock * Copyright (c) 2014-2015 Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -36,12 +36,12 @@ namespace sqlpp
struct expression_alias_t struct expression_alias_t
{ {
using _traits = make_traits<value_type_of<Expression>, tag::is_selectable, tag::is_alias>; using _traits = make_traits<value_type_of<Expression>, tag::is_selectable, tag::is_alias>;
using _recursive_traits = make_recursive_traits<Expression>; using _nodes = detail::type_vector<Expression>;
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias"); static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");
static_assert(not is_alias_t<Expression>::value, "cannot create an alias of an alias"); static_assert(not is_alias_t<Expression>::value, "cannot create an alias of an alias");
using _name_t = typename AliasProvider::_name_t; using _alias_t = typename AliasProvider::_alias_t;
Expression _expression; Expression _expression;
}; };
@ -49,14 +49,14 @@ namespace sqlpp
template<typename Context, typename Expression, typename AliasProvider> template<typename Context, typename Expression, typename AliasProvider>
struct serializer_t<Context, expression_alias_t<Expression, AliasProvider>> struct serializer_t<Context, expression_alias_t<Expression, AliasProvider>>
{ {
using _serialize_check = serialize_check_of<Context, Expression>;
using T = expression_alias_t<Expression, AliasProvider>; using T = expression_alias_t<Expression, AliasProvider>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << '('; serialize_operand(t._expression, context);
serialize(t._expression, context); context << " AS ";
context << ") AS "; context << name_of<T>::char_ptr();
context << T::_name_t::_get_name();
return context; return context;
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,13 +28,15 @@
#define SQLPP_ALIAS_PROVIDER_H #define SQLPP_ALIAS_PROVIDER_H
#include <type_traits> #include <type_traits>
#include <sqlpp11/char_sequence.h>
#define SQLPP_ALIAS_PROVIDER(name) \ #define SQLPP_ALIAS_PROVIDER(name) \
struct name##_t\ struct name##_t\
{\ {\
struct _name_t\ struct _alias_t\
{\ {\
static constexpr const char* _get_name() { return #name; }\ static constexpr const char _literal[] = #name;\
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;\
template<typename T>\ template<typename T>\
struct _member_t\ struct _member_t\
{\ {\
@ -55,7 +57,7 @@ namespace sqlpp
}; };
template<typename T> template<typename T>
struct is_alias_provider_t<T, typename std::enable_if<std::is_class<typename T::_name_t::template _member_t<int>>::value, void>::type> struct is_alias_provider_t<T, typename std::enable_if<std::is_class<typename T::_alias_t::template _member_t<int>>::value, void>::type>
{ {
static constexpr bool value = true; static constexpr bool value = true;
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -51,14 +51,26 @@ namespace sqlpp
return {}; return {};
} }
struct assert_no_stand_alone_all_of_t
{
using type = std::false_type;
template<typename T = void>
static void _()
{
static_assert(wrong_t<T>::value, "all_of(table) seems to be used outside of select");
}
};
template<typename Context, typename Table> template<typename Context, typename Table>
struct serializer_t<Context, all_of_t<Table>> struct serializer_t<Context, all_of_t<Table>>
{ {
using _serialize_check = assert_no_stand_alone_all_of_t;
using T = all_of_t<Table>; using T = all_of_t<Table>;
static Context& _(const T& t, const Context&) static Context& _(const T& t, const Context&)
{ {
static_assert(wrong_t<serializer_t>::value, "all_of(table) does not seem to be used in select"); _serialize_check::_();
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,6 +28,7 @@
#define SQLPP_ANY_H #define SQLPP_ANY_H
#include <sqlpp11/boolean.h> #include <sqlpp11/boolean.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
@ -36,11 +37,12 @@ namespace sqlpp
struct any_t struct any_t
{ {
using _traits = make_traits<value_type_of<Select>, tag::is_multi_expression>; using _traits = make_traits<value_type_of<Select>, tag::is_multi_expression>;
using _recursive_traits = make_recursive_traits<Select>; using _nodes = detail::type_vector<Select>;
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "ANY"; } static constexpr const char _literal[] = "any_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -66,6 +68,7 @@ namespace sqlpp
template<typename Context, typename Select> template<typename Context, typename Select>
struct serializer_t<Context, any_t<Select>> struct serializer_t<Context, any_t<Select>>
{ {
using _serialize_check = serialize_check_of<Context, Select>;
using T = any_t<Select>; using T = any_t<Select>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -41,7 +41,7 @@ namespace sqlpp
struct assignment_t struct assignment_t
{ {
using _traits = make_traits<no_value_t, tag::is_assignment>; using _traits = make_traits<no_value_t, tag::is_assignment>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _nodes = detail::type_vector<Lhs, Rhs>;
using _lhs_t = Lhs; using _lhs_t = Lhs;
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>; using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
@ -66,13 +66,14 @@ namespace sqlpp
template<typename Context, typename Lhs, typename Rhs> template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, assignment_t<Lhs, Rhs>> struct serializer_t<Context, assignment_t<Lhs, Rhs>>
{ {
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
using T = assignment_t<Lhs, Rhs>; using T = assignment_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
serialize(simple_column(t._lhs), context); serialize(simple_column(t._lhs), context);
context << "="; context << "=";
serialize(t._rhs, context); serialize_operand(t._rhs, context);
return context; return context;
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,6 +28,7 @@
#define SQLPP_AVG_H #define SQLPP_AVG_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp namespace sqlpp
{ {
@ -37,14 +38,15 @@ namespace sqlpp
public alias_operators<avg_t<Flag, Expr>> public alias_operators<avg_t<Flag, Expr>>
{ {
using _traits = make_traits<floating_point, tag::is_expression, tag::is_selectable>; using _traits = make_traits<floating_point, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr, aggregate_function>; using _nodes = detail::type_vector<Expr, aggregate_function>;
static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "avg() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "avg() used with flag other than 'distinct'");
static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument"); static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument");
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "AVG"; } static constexpr const char _literal[] = "avg_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -70,6 +72,7 @@ namespace sqlpp
template<typename Context, typename Flag, typename Expr> template<typename Context, typename Flag, typename Expr>
struct serializer_t<Context, avg_t<Flag, Expr>> struct serializer_t<Context, avg_t<Flag, Expr>>
{ {
using _serialize_check = serialize_check_of<Context, Flag, Expr>;
using T = avg_t<Flag, Expr>; using T = avg_t<Flag, Expr>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -79,8 +82,12 @@ namespace sqlpp
{ {
serialize(Flag(), context); serialize(Flag(), context);
context << ' '; context << ' ';
serialize_operand(t._expr, context);
} }
else
{
serialize(t._expr, context); serialize(t._expr, context);
}
context << ")"; context << ")";
return context; return context;
} }

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -34,7 +34,7 @@
#include <sqlpp11/in_fwd.h> #include <sqlpp11/in_fwd.h>
#include <sqlpp11/is_null_fwd.h> #include <sqlpp11/is_null_fwd.h>
#include <sqlpp11/wrap_operand_fwd.h> #include <sqlpp11/wrap_operand_fwd.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
namespace sqlpp namespace sqlpp
{ {
@ -106,12 +106,12 @@ namespace sqlpp
return { *static_cast<const Expr*>(this), rhs{t} }; return { *static_cast<const Expr*>(this), rhs{t} };
} }
is_null_t<true, Expr> is_null() const is_null_t<Expr> is_null() const
{ {
return { *static_cast<const Expr*>(this) }; return { *static_cast<const Expr*>(this) };
} }
is_null_t<false, Expr> is_not_null() const is_not_null_t<Expr> is_not_null() const
{ {
return { *static_cast<const Expr*>(this) }; return { *static_cast<const Expr*>(this) };
} }
@ -128,16 +128,16 @@ namespace sqlpp
// Hint: use value_list wrapper for containers... // Hint: use value_list wrapper for containers...
template<typename... T> template<typename... T>
in_t<true, Expr, wrap_operand_t<T>...> in(T... t) const in_t<Expr, wrap_operand_t<T>...> in(T... t) const
{ {
static_assert(detail::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid"); static_assert(logic::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 Expr*>(this), wrap_operand_t<T>{t}... }; return { *static_cast<const Expr*>(this), wrap_operand_t<T>{t}... };
} }
template<typename... T> template<typename... T>
in_t<false, Expr, wrap_operand_t<T>...> not_in(T... t) const not_in_t<Expr, wrap_operand_t<T>...> not_in(T... t) const
{ {
static_assert(detail::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid"); static_assert(logic::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 Expr*>(this), wrap_operand_t<T>{t}... }; return { *static_cast<const Expr*>(this), wrap_operand_t<T>{t}... };
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -36,7 +36,7 @@ namespace sqlpp
struct boolean_expression_t: public expression_operators<boolean_expression_t<Database>, boolean> struct boolean_expression_t: public expression_operators<boolean_expression_t<Database>, boolean>
{ {
using _traits = make_traits<boolean, tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
template<typename Expr> template<typename Expr>
boolean_expression_t(Expr expr): boolean_expression_t(Expr expr):
@ -71,6 +71,7 @@ namespace sqlpp
template<typename Context, typename Database> template<typename Context, typename Database>
struct serializer_t<Context, boolean_expression_t<Database>> struct serializer_t<Context, boolean_expression_t<Database>>
{ {
using _serialize_check = consistent_t;
using T = boolean_expression_t<Database>; using T = boolean_expression_t<Database>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -52,21 +52,13 @@ namespace sqlpp
using _tags = detail::make_joined_set_t<detail::type_set<tag::is_column, tag::is_expression, tag::is_selectable>, 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 using _nodes = detail::type_vector<>;
{
using _parameters = std::tuple<>;
using _provided_tables = detail::type_set<>;
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<Table>; using _required_tables = detail::type_set<Table>;
using _extra_tables = detail::type_set<>; using _can_be_null = column_spec_can_be_null_t<ColumnSpec>;
using _tags = typename std::conditional<column_spec_can_be_null_t<ColumnSpec>::value,
detail::type_set<tag::can_be_null>,
detail::type_set<>>::type;
};
using _spec_t = ColumnSpec; using _spec_t = ColumnSpec;
using _table = Table; using _table = Table;
using _name_t = typename _spec_t::_name_t; using _alias_t = typename _spec_t::_alias_t;
template<typename T> template<typename T>
using _is_valid_operand = is_valid_operand<value_type_of<ColumnSpec>, T>; using _is_valid_operand = is_valid_operand<value_type_of<ColumnSpec>, T>;
@ -78,9 +70,11 @@ namespace sqlpp
column_t& operator=(column_t&&) = default; column_t& operator=(column_t&&) = default;
~column_t() = default; ~column_t() = default;
static constexpr const char* _get_name() template<typename T = _table>
auto table() const -> _table
{ {
return _name_t::_get_name(); static_assert(is_table_t<T>::value, "cannot call get_table for columns of a sub-selects or cte");
return _table{};
} }
template<typename alias_provider> template<typename alias_provider>
@ -115,11 +109,12 @@ namespace sqlpp
template<typename Context, typename... Args> template<typename Context, typename... Args>
struct serializer_t<Context, column_t<Args...>> struct serializer_t<Context, column_t<Args...>>
{ {
using _serialize_check = consistent_t;
using T = column_t<Args...>; using T = column_t<Args...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << T::_table::_name_t::_get_name() << '.' << T::_name_t::_get_name(); context << name_of<typename T::_table>::char_ptr() << '.' << name_of<T>::char_ptr();
return context; return context;
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,9 +28,10 @@
#define SQLPP_CONCAT_H #define SQLPP_CONCAT_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
namespace sqlpp namespace sqlpp
{ {
@ -41,13 +42,14 @@ namespace sqlpp
public alias_operators<concat_t<First, Args...>> public alias_operators<concat_t<First, Args...>>
{ {
using _traits = make_traits<value_type_of<First>, tag::is_expression, tag::is_selectable>; using _traits = make_traits<value_type_of<First>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<First, Args...>; using _nodes = detail::type_vector<First, Args...>;
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
static_assert(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(logic::all_t<is_text_t<First>::value, is_text_t<Args>::value...>::value, "at least one non-text argument detected in concat()");
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "CONCAT"; } static constexpr const char _literal[] = "concat_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -71,6 +73,7 @@ namespace sqlpp
template<typename Context, typename First, typename... Args> template<typename Context, typename First, typename... Args>
struct serializer_t<Context, concat_t<First, Args...>> struct serializer_t<Context, concat_t<First, Args...>>
{ {
using _serialize_check = serialize_check_of<Context, First, Args...>;
using T = concat_t<First, Args...>; using T = concat_t<First, Args...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -27,6 +27,7 @@
#ifndef SQLPP_COUNT_H #ifndef SQLPP_COUNT_H
#define SQLPP_COUNT_H #define SQLPP_COUNT_H
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/select_flags.h> #include <sqlpp11/select_flags.h>
#include <sqlpp11/integral.h> #include <sqlpp11/integral.h>
@ -38,23 +39,16 @@ namespace sqlpp
public alias_operators<count_t<Flag, Expr>> public alias_operators<count_t<Flag, Expr>>
{ {
using _traits = make_traits<integral, tag::is_expression, tag::is_selectable>; 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>>;
};
using _nodes = detail::type_vector<Expr, aggregate_function>;
using _can_be_null = std::false_type;
static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "count() used with flag other than 'distinct'"); static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "count() used with flag other than 'distinct'");
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "COUNT"; } static constexpr const char _literal[] = "count_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -80,6 +74,7 @@ namespace sqlpp
template<typename Context, typename Flag, typename Expr> template<typename Context, typename Flag, typename Expr>
struct serializer_t<Context, count_t<Flag, Expr>> struct serializer_t<Context, count_t<Flag, Expr>>
{ {
using _serialize_check = serialize_check_of<Context, Flag, Expr>;
using T = count_t<Flag, Expr>; using T = count_t<Flag, Expr>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -89,8 +84,12 @@ namespace sqlpp
{ {
serialize(Flag(), context); serialize(Flag(), context);
context << ' '; context << ' ';
serialize_operand(t._expr, context);
} }
else
{
serialize(t._expr, context); serialize(t._expr, context);
}
context << ")"; context << ")";
return context; return context;
} }
@ -99,6 +98,7 @@ namespace sqlpp
template<typename T> template<typename T>
auto count(T t) -> count_t<noop, wrap_operand_t<T>> auto count(T t) -> count_t<noop, wrap_operand_t<T>>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "count() cannot be used on an aggregate function");
static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
return { t }; return { t };
} }
@ -106,6 +106,7 @@ namespace sqlpp
template<typename T> template<typename T>
auto count(const distinct_t&, T t) -> count_t<distinct_t, wrap_operand_t<T>> auto count(const distinct_t&, T t) -> count_t<distinct_t, wrap_operand_t<T>>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "count() cannot be used on an aggregate function");
static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
return { t }; return { t };
} }

261
include/sqlpp11/cte.h Normal file
View File

@ -0,0 +1,261 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_CTE_H
#define SQLPP_CTE_H
#include <sqlpp11/table_ref.h>
#include <sqlpp11/select_flags.h>
#include <sqlpp11/result_row.h>
#include <sqlpp11/statement_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/expression.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h>
#include <sqlpp11/logic.h>
namespace sqlpp
{
template<typename Flag, typename Lhs, typename Rhs>
struct cte_union_t
{
using _nodes = detail::type_vector<>;
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Lhs>, required_ctes_of<Rhs>>;
using _parameters = detail::type_vector_cat_t<parameters_of<Lhs>, parameters_of<Rhs>>;
cte_union_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
cte_union_t(const cte_union_t&) = default;
cte_union_t(cte_union_t&&) = default;
cte_union_t& operator=(const cte_union_t&) = default;
cte_union_t& operator=(cte_union_t&&) = default;
~cte_union_t() = default;
Lhs _lhs;
Rhs _rhs;
};
// Interpreters
template<typename Context, typename Flag, typename Lhs, typename Rhs>
struct serializer_t<Context, cte_union_t<Flag, Lhs, Rhs>>
{
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
using T = cte_union_t<Flag, Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
serialize(t._lhs, context);
context << " UNION ";
serialize(Flag{}, context);
context << " ";
serialize(t._rhs, context);
return context;
}
};
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
struct cte_t;
template<typename AliasProvider>
struct cte_ref_t;
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
auto from_table(cte_t<AliasProvider, Statement, FieldSpecs...> t) -> cte_ref_t<AliasProvider>
{
return cte_ref_t<AliasProvider>{};
}
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
struct from_table_impl<cte_t<AliasProvider, Statement, FieldSpecs...>>
{
using type = cte_ref_t<AliasProvider>;
};
template<typename FieldSpec>
struct cte_column_spec_t
{
using _alias_t = typename FieldSpec::_alias_t;
using _traits = make_traits<value_type_of<FieldSpec>,
tag::must_not_insert,
tag::must_not_update,
tag_if<tag::can_be_null, column_spec_can_be_null_t<FieldSpec>::value>
>;
};
template<typename AliasProvider, typename Statement, typename ResultRow>
struct make_cte_impl
{
using type = void;
};
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
struct make_cte_impl<AliasProvider, Statement, result_row_t<void, FieldSpecs...>>
{
using type = cte_t<AliasProvider, Statement, FieldSpecs...>;
};
template<typename AliasProvider, typename Statement>
using make_cte_t = typename make_cte_impl<AliasProvider, Statement, get_result_row_t<Statement>>::type;
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
struct cte_t: public member_t<cte_column_spec_t<FieldSpecs>, column_t<AliasProvider, cte_column_spec_t<FieldSpecs>>>...
{
using _traits = make_traits<no_value_t, tag::is_cte, tag::is_table>; // FIXME: is table? really?
using _nodes = detail::type_vector<>;
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Statement>, detail::type_set<AliasProvider>>;
using _parameters = parameters_of<Statement>;
using _alias_t = typename AliasProvider::_alias_t;
constexpr static bool _is_recursive = detail::is_element_of<AliasProvider, required_ctes_of<Statement>>::value;
using _column_tuple_t = std::tuple<column_t<AliasProvider, cte_column_spec_t<FieldSpecs>>...>;
template<typename... T>
using _check = logic::all_t<is_statement_t<T>::value...>;
using _result_row_t = result_row_t<void, FieldSpecs...>;
template<typename Rhs>
auto union_distinct(Rhs rhs) const
-> typename std::conditional<_check<Rhs>::value, cte_t<AliasProvider, cte_union_t<distinct_t, Statement, Rhs>, FieldSpecs...>, bad_statement>::type
{
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
return _union_impl<void, distinct_t>(_check<Rhs>{}, rhs);
}
template<typename Rhs>
auto union_all(Rhs rhs) const
-> typename std::conditional<_check<Rhs>::value, cte_t<AliasProvider, cte_union_t<all_t, Statement, Rhs>, FieldSpecs...>, bad_statement>::type
{
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
return _union_impl<all_t>(_check<Rhs>{}, rhs);
}
private:
template<typename Flag, typename Rhs>
auto _union_impl(const std::false_type&, Rhs rhs) const
-> bad_statement;
template<typename Flag, typename Rhs>
auto _union_impl(const std::true_type&, Rhs rhs) const
-> cte_t<AliasProvider, cte_union_t<Flag, Statement, Rhs>, FieldSpecs...>
{
return cte_union_t<Flag, Statement, Rhs>{_statement, rhs};
}
public:
cte_t(Statement statement): _statement(statement){}
cte_t(const cte_t&) = default;
cte_t(cte_t&&) = default;
cte_t& operator=(const cte_t&) = default;
cte_t& operator=(cte_t&&) = default;
~cte_t() = default;
Statement _statement;
};
template<typename Context, typename AliasProvider, typename Statement, typename... ColumnSpecs>
struct serializer_t<Context, cte_t<AliasProvider, Statement, ColumnSpecs...>>
{
using _serialize_check = serialize_check_of<Context, Statement>;
using T = cte_t<AliasProvider, Statement, ColumnSpecs...>;
static Context& _(const T& t, Context& context)
{
context << name_of<T>::char_ptr() << " AS (";
serialize(t._statement, context);
context << ")";
return context;
}
};
// The cte_t is displayed as AliasProviderName except within the with:
// - the with needs the
// AliasProviderName AS (ColumnNames) (select/union)
// The result row of the select should not have dynamic parts
template<typename AliasProvider>
struct cte_ref_t
{
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_cte, tag::is_table>; // FIXME: is table? really?
using _nodes = detail::type_vector<>;
using _required_ctes = detail::make_type_set_t<AliasProvider>;
using _provided_tables = detail::type_set<AliasProvider>;
using _alias_t = typename AliasProvider::_alias_t;
template<typename Statement>
auto as(Statement statement)
-> make_cte_t<AliasProvider, Statement>
{
static_assert(required_tables_of<Statement>::size::value == 0, "common table expression must not use unknown tables");
static_assert(not detail::is_element_of<AliasProvider, required_ctes_of<Statement>>::value, "common table expression must not self-reference in the first part, use union_all/union_distinct for recursion");
static_assert(is_static_result_row_t<get_result_row_t<Statement>>::value, "ctes must not have dynamically added columns");
return { statement };
}
};
template<typename Context, typename AliasProvider>
struct serializer_t<Context, cte_ref_t<AliasProvider>>
{
using _serialize_check = consistent_t;
using T = cte_ref_t<AliasProvider>;
static Context& _(const T& t, Context& context)
{
context << name_of<T>::char_ptr();
return context;
}
};
template<typename AliasProvider>
auto cte(const AliasProvider&)
-> cte_ref_t<AliasProvider>
{
return {};
}
}
#endif

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_CUSTOM_QUERY_H
#define SQLPP_CUSTOM_QUERY_H
#include <sqlpp11/connection.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/hidden.h>
#include <sqlpp11/detail/get_first.h>
namespace sqlpp
{
template<typename Database, typename... Parts>
struct custom_query_t;
namespace detail
{
template<typename Db, typename... Parts>
struct custom_parts_t
{
using _custom_query_t = custom_query_t<Db, Parts...>;
using _result_type_provider = detail::get_first_if<is_return_value_t, noop, Parts...>;
using _result_methods_t = typename _result_type_provider::template _result_methods_t<_result_type_provider>;
};
}
template<typename Database, typename... Parts>
struct custom_query_t:
private detail::custom_parts_t<Database, Parts...>::_result_methods_t
{
using _methods_t = typename detail::custom_parts_t<Database, Parts...>::_result_methods_t;
using _traits = make_traits<no_value_t, tag::is_statement>;
using _nodes = detail::type_vector<Parts...>;
using _parameter_check = typename std::conditional<detail::type_vector_size<parameters_of<custom_query_t>>::value == 0,
consistent_t, assert_no_parameters_t>::type;
using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t,
_parameter_check>;
using _prepare_check = consistent_t;
custom_query_t(Parts... parts):
_parts(parts...)
{}
custom_query_t(std::tuple<Parts...> parts):
_parts(parts)
{}
custom_query_t(const custom_query_t&) = default;
custom_query_t(custom_query_t&&) = default;
custom_query_t& operator=(const custom_query_t&) = default;
custom_query_t& operator=(custom_query_t&&) = default;
~custom_query_t() = default;
template<typename Db>
auto _run(Db& db) const -> decltype(std::declval<_methods_t>()._run(db, *this))
{
_run_check::_();
return _methods_t::_run(db, *this);
}
template<typename Db>
auto _prepare(Db& db) const -> decltype(std::declval<_methods_t>()._prepare(db, *this))
{
_prepare_check::_();
return _methods_t::_prepare(db, *this);
}
static constexpr size_t _get_static_no_of_parameters()
{
return std::tuple_size<parameters_of<custom_query_t>>::value;
}
size_t _get_no_of_parameters() const
{
return _get_static_no_of_parameters();
}
template<typename Part>
auto with_result_type_of(Part part)
-> custom_query_t<Database, Part, Parts...>
{
return {tuple_cat(std::make_tuple(part), _parts)};
}
std::tuple<Parts...> _parts;
};
template<typename Context, typename Database, typename... Parts>
struct serializer_t<Context, custom_query_t<Database, Parts...>>
{
using _serialize_check = serialize_check_of<Context, Parts...>;
using T = custom_query_t<Database, Parts...>;
static Context& _(const T& t, Context& context)
{
interpret_tuple_without_braces(t._parts, " ", context);
return context;
}
};
template<typename... Parts>
auto custom_query(Parts... parts)
-> custom_query_t<void, wrap_operand_t<Parts>...>
{
static_assert(sizeof...(Parts) > 0, "custom query requires at least one argument");
return custom_query_t<void, wrap_operand_t<Parts>...>(parts...);
}
template<typename Database, typename... Parts>
auto dynamic_custom_query(const Database&, Parts... parts)
-> custom_query_t<Database, wrap_operand_t<Parts>...>
{
static_assert(sizeof...(Parts) > 0, "custom query requires at least one query argument");
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
return custom_query_t<Database, wrap_operand_t<Parts>...>(parts...);
}
}
#endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -34,7 +34,7 @@ namespace sqlpp
struct default_value_t struct default_value_t
{ {
using _traits = make_traits<no_value_t, tag::is_expression>; using _traits = make_traits<no_value_t, tag::is_expression>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
static constexpr bool _is_trivial() { return false; } static constexpr bool _is_trivial() { return false; }
}; };
@ -42,6 +42,7 @@ namespace sqlpp
template<typename Context> template<typename Context>
struct serializer_t<Context, default_value_t> struct serializer_t<Context, default_value_t>
{ {
using _serialize_check = consistent_t;
using Operand = default_value_t; using Operand = default_value_t;
static Context& _(const Operand& t, Context& context) static Context& _(const Operand& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -27,10 +27,9 @@
#ifndef SQLPP_DETAIL_TYPE_SET_H #ifndef SQLPP_DETAIL_TYPE_SET_H
#define SQLPP_DETAIL_TYPE_SET_H #define SQLPP_DETAIL_TYPE_SET_H
#include <tuple>
#include <type_traits> #include <type_traits>
#include <sqlpp11/wrong.h> #include <sqlpp11/wrong.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
namespace sqlpp namespace sqlpp
{ {
@ -40,6 +39,9 @@ namespace sqlpp
template<typename... T> template<typename... T>
struct make_type_set; struct make_type_set;
template<typename... T>
using make_type_set_t = typename make_type_set<T...>::type;
template<typename E, typename SET> template<typename E, typename SET>
struct is_element_of; struct is_element_of;
@ -50,7 +52,7 @@ namespace sqlpp
using size = std::integral_constant<size_t, sizeof...(Elements)>; using size = std::integral_constant<size_t, sizeof...(Elements)>;
using _is_type_set = std::true_type; using _is_type_set = std::true_type;
static_assert(std::is_same<type_set, typename make_type_set<Elements...>::type>::value, "use make_type_set to construct a set"); static_assert(std::is_same<type_set, make_type_set_t<Elements...>>::value, "use make_type_set to construct a typeset");
template<typename T> template<typename T>
struct insert struct insert
@ -79,7 +81,7 @@ namespace sqlpp
template<typename E, typename... Elements> template<typename E, typename... Elements>
struct is_element_of<E, type_set<Elements...>> struct is_element_of<E, type_set<Elements...>>
{ {
static constexpr bool value = any_t<std::is_same<E, Elements>::value...>::value; static constexpr bool value = ::sqlpp::logic::any_t<std::is_same<E, Elements>::value...>::value;
}; };
template<typename L, typename R> template<typename L, typename R>
@ -91,7 +93,7 @@ namespace sqlpp
template<typename... LElements, typename... RElements> template<typename... LElements, typename... RElements>
struct joined_set<type_set<LElements...>, type_set<RElements...>> struct joined_set<type_set<LElements...>, type_set<RElements...>>
{ {
using type = typename make_type_set<LElements..., RElements...>::type; using type = make_type_set_t<LElements..., RElements...>;
}; };
template<typename L, typename R> template<typename L, typename R>
@ -139,9 +141,6 @@ namespace sqlpp
using type = typename make_type_set<Rest...>::type::template insert<T>::type; using type = typename make_type_set<Rest...>::type::template insert<T>::type;
}; };
template<typename... T>
using make_type_set_t = typename make_type_set<T...>::type;
template<template<typename> class Predicate, typename... T> template<template<typename> class Predicate, typename... T>
struct make_type_set_if; struct make_type_set_if;
@ -168,8 +167,11 @@ namespace sqlpp
using type = typename make_type_set_if<InversePredicate, T...>::type; using type = typename make_type_set_if<InversePredicate, T...>::type;
}; };
template<template<typename> class Predicate, typename... T>
using make_type_set_if_not_t = typename make_type_set_if_not<Predicate, T...>::type;
template<typename... T> template<typename... T>
using has_duplicates = std::integral_constant<bool, make_type_set<T...>::type::size::value != sizeof...(T)>; using has_duplicates = std::integral_constant<bool, make_type_set_t<T...>::size::value != sizeof...(T)>;
template<typename... T> template<typename... T>
struct make_joined_set struct make_joined_set
@ -205,7 +207,7 @@ namespace sqlpp
{ {
template<typename E> template<typename E>
using is_subtrahend = is_element_of<E, type_set<Subtrahends...>>; using is_subtrahend = is_element_of<E, type_set<Subtrahends...>>;
using type = typename make_type_set_if_not<is_subtrahend, Minuends...>::type; using type = make_type_set_if_not_t<is_subtrahend, Minuends...>;
}; };
template<typename Minuend, typename Subtrahend> template<typename Minuend, typename Subtrahend>
@ -221,8 +223,8 @@ namespace sqlpp
struct make_intersect_set<type_set<LhsElements...>, type_set<RhsElements...>> struct make_intersect_set<type_set<LhsElements...>, type_set<RhsElements...>>
{ {
template<typename E> template<typename E>
using is_in_both = all_t<is_element_of<E, type_set<LhsElements...>>::value, is_element_of<E, type_set<RhsElements...>>::value>; using is_in_both = ::sqlpp::logic::all_t<is_element_of<E, type_set<LhsElements...>>::value, is_element_of<E, type_set<RhsElements...>>::value>;
using type = typename make_type_set_if<is_in_both, LhsElements...>::type; using type = make_type_set_if_t<is_in_both, LhsElements...>;
}; };
template<typename Lhs, typename Rhs> template<typename Lhs, typename Rhs>
@ -238,7 +240,7 @@ namespace sqlpp
template<template<typename> class Transformation, typename... E> template<template<typename> class Transformation, typename... E>
struct transform_set<Transformation, type_set<E...>> struct transform_set<Transformation, type_set<E...>>
{ {
using type = typename make_type_set<Transformation<E>...>::type; using type = make_type_set_t<Transformation<E>...>;
}; };
template<template<typename> class Transformation, typename T> template<template<typename> class Transformation, typename T>

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_DETAIL_TYPE_VECTOR_H
#define SQLPP_DETAIL_TYPE_VECTOR_H
#include <sqlpp11/wrong.h>
namespace sqlpp
{
namespace detail
{
template<typename... T>
struct type_vector
{};
template<typename...T>
struct type_vector_cat_impl
{
static_assert(wrong_t<type_vector_cat_impl>::value, "type_vector_cat must be called with type_vector arguments");
};
template<>
struct type_vector_cat_impl<>
{
using type = type_vector<>;
};
template<typename... T>
struct type_vector_cat_impl<type_vector<T...>>
{
using type = type_vector<T...>;
};
template<typename... L, typename... R>
struct type_vector_cat_impl<type_vector<L...>, type_vector<R...>>
{
using type = type_vector<L..., R...>;
};
template<typename... L, typename... Rest>
struct type_vector_cat_impl<type_vector<L...>, Rest...>
{
using type = typename type_vector_cat_impl<type_vector<L...>, typename type_vector_cat_impl<Rest...>::type>::type;
};
template<typename... T>
using type_vector_cat_t = typename type_vector_cat_impl<T...>::type;
template<typename T>
struct type_vector_size
{
static_assert(wrong_t<type_vector_size>::value, "type_vector_size needs to be called with a type_vector argument");
};
template<typename... T>
struct type_vector_size<type_vector<T...>>
{
static constexpr std::size_t value = sizeof...(T);
};
}
}
#endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -40,7 +40,7 @@ namespace sqlpp
static_assert(is_database<Db>::value, "Db parameter of eval has to be a database connection"); 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(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"); 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 _name_type = alias::a_t::_alias_t;
using _value_type = value_type_of<Expr>; using _value_type = value_type_of<Expr>;
using _field_spec = field_spec_t<_name_type, _value_type, true, false>; using _field_spec = field_spec_t<_name_type, _value_type, true, false>;
using type = result_field_t<_value_type, Db, _field_spec>; using type = result_field_t<_value_type, Db, _field_spec>;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -27,6 +27,7 @@
#ifndef SQLPP_EXISTS_H #ifndef SQLPP_EXISTS_H
#define SQLPP_EXISTS_H #define SQLPP_EXISTS_H
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/boolean.h> #include <sqlpp11/boolean.h>
namespace sqlpp namespace sqlpp
@ -37,13 +38,14 @@ namespace sqlpp
public alias_operators<exists_t<Select>> public alias_operators<exists_t<Select>>
{ {
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>; using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Select>; using _nodes = detail::type_vector<Select>;
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument"); static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "EXISTS"; } static constexpr const char _literal[] = "exists_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -69,6 +71,7 @@ namespace sqlpp
template<typename Context, typename Select> template<typename Context, typename Select>
struct serializer_t<Context, exists_t<Select>> struct serializer_t<Context, exists_t<Select>>
{ {
using _serialize_check = serialize_check_of<Context, Select>;
using T = exists_t<Select>; using T = exists_t<Select>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -44,7 +44,7 @@ namespace sqlpp
public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>> public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>
{ {
using _traits = make_traits<boolean, tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _nodes = detail::type_vector<Lhs, Rhs>;
using _lhs_t = Lhs; using _lhs_t = Lhs;
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>; using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
@ -66,12 +66,13 @@ namespace sqlpp
template<typename Context, typename Lhs, typename Rhs> template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, equal_to_t<Lhs, Rhs>> struct serializer_t<Context, equal_to_t<Lhs, Rhs>>
{ {
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
using T = equal_to_t<Lhs, Rhs>; using T = equal_to_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "("; context << "(";
serialize(t._lhs, context); serialize_operand(t._lhs, context);
if (t._rhs._is_null()) if (t._rhs._is_null())
{ {
context << " IS NULL"; context << " IS NULL";
@ -79,7 +80,7 @@ namespace sqlpp
else else
{ {
context << "="; context << "=";
serialize(t._rhs, context); serialize_operand(t._rhs, context);
} }
context << ")"; context << ")";
return context; return context;
@ -92,7 +93,7 @@ namespace sqlpp
public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>> public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>
{ {
using _traits = make_traits<boolean, tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _nodes = detail::type_vector<Lhs, Rhs>;
using _lhs_t = Lhs; using _lhs_t = Lhs;
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>; using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
@ -114,12 +115,13 @@ namespace sqlpp
template<typename Context, typename Lhs, typename Rhs> template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, not_equal_to_t<Lhs, Rhs>> struct serializer_t<Context, not_equal_to_t<Lhs, Rhs>>
{ {
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
using T = not_equal_to_t<Lhs, Rhs>; using T = not_equal_to_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "("; context << "(";
serialize(t._lhs, context); serialize_operand(t._lhs, context);
if (t._rhs._is_null()) if (t._rhs._is_null())
{ {
context << " IS NOT NULL"; context << " IS NOT NULL";
@ -127,7 +129,7 @@ namespace sqlpp
else else
{ {
context << "!="; context << "!=";
serialize(t._rhs, context); serialize_operand(t._rhs, context);
} }
context << ")"; context << ")";
return context; return context;
@ -140,7 +142,7 @@ namespace sqlpp
public alias_operators<unary_expression_t<op::logical_not, Rhs>> public alias_operators<unary_expression_t<op::logical_not, Rhs>>
{ {
using _traits = make_traits<boolean, tag::is_expression>; using _traits = make_traits<boolean, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Rhs>; using _nodes = detail::type_vector<Rhs>;
unary_expression_t(Rhs rhs): unary_expression_t(Rhs rhs):
_rhs(rhs) _rhs(rhs)
@ -158,6 +160,7 @@ namespace sqlpp
template<typename Context, typename Rhs> template<typename Context, typename Rhs>
struct serializer_t<Context, logical_not_t<Rhs>> struct serializer_t<Context, logical_not_t<Rhs>>
{ {
using _serialize_check = serialize_check_of<Context, Rhs>;
using T = logical_not_t<Rhs>; using T = logical_not_t<Rhs>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -165,13 +168,13 @@ namespace sqlpp
context << "("; context << "(";
if (trivial_value_is_null_t<Rhs>::value) if (trivial_value_is_null_t<Rhs>::value)
{ {
serialize(t._rhs, context); serialize_operand(t._rhs, context);
context << " IS NULL "; context << " IS NULL ";
} }
else else
{ {
context << "NOT "; context << "NOT ";
serialize(t._rhs, context); serialize_operand(t._rhs, context);
} }
context << ")"; context << ")";
@ -185,7 +188,7 @@ namespace sqlpp
public alias_operators<binary_expression_t<Lhs, O, Rhs>> public alias_operators<binary_expression_t<Lhs, O, Rhs>>
{ {
using _traits = make_traits<value_type_of<O>, tag::is_expression>; using _traits = make_traits<value_type_of<O>, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>; using _nodes = detail::type_vector<Lhs, Rhs>;
binary_expression_t(Lhs lhs, Rhs rhs): binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs), _lhs(lhs),
@ -205,14 +208,15 @@ namespace sqlpp
template<typename Context, typename Lhs, typename O, typename Rhs> template<typename Context, typename Lhs, typename O, typename Rhs>
struct serializer_t<Context, binary_expression_t<Lhs, O, Rhs>> struct serializer_t<Context, binary_expression_t<Lhs, O, Rhs>>
{ {
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
using T = binary_expression_t<Lhs, O, Rhs>; using T = binary_expression_t<Lhs, O, Rhs>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "("; context << "(";
serialize(t._lhs, context); serialize_operand(t._lhs, context);
context << O::_name; context << O::_name;
serialize(t._rhs, context); serialize_operand(t._rhs, context);
context << ")"; context << ")";
return context; return context;
} }
@ -224,7 +228,7 @@ namespace sqlpp
public alias_operators<unary_expression_t<O, Rhs>> public alias_operators<unary_expression_t<O, Rhs>>
{ {
using _traits = make_traits<value_type_of<O>, tag::is_expression>; using _traits = make_traits<value_type_of<O>, tag::is_expression>;
using _recursive_traits = make_recursive_traits<Rhs>; using _nodes = detail::type_vector<Rhs>;
unary_expression_t(Rhs rhs): unary_expression_t(Rhs rhs):
_rhs(rhs) _rhs(rhs)
@ -242,13 +246,14 @@ namespace sqlpp
template<typename Context, typename O, typename Rhs> template<typename Context, typename O, typename Rhs>
struct serializer_t<Context, unary_expression_t<O, Rhs>> struct serializer_t<Context, unary_expression_t<O, Rhs>>
{ {
using _serialize_check = serialize_check_of<Context, Rhs>;
using T = unary_expression_t<O, Rhs>; using T = unary_expression_t<O, Rhs>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "("; context << "(";
context << O::_name; context << O::_name;
serialize(t._rhs, context); serialize_operand(t._rhs, context);
context << ")"; context << ")";
return context; return context;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,7 +28,7 @@
#define SQLPP_EXTRA_TABLES_H #define SQLPP_EXTRA_TABLES_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
#include <sqlpp11/policy_update.h> #include <sqlpp11/policy_update.h>
namespace sqlpp namespace sqlpp
@ -52,21 +52,9 @@ namespace sqlpp
struct extra_tables_t struct extra_tables_t
{ {
using _traits = make_traits<no_value_t, tag::is_extra_tables>; using _traits = make_traits<no_value_t, tag::is_extra_tables>;
struct _recursive_traits using _nodes = detail::type_vector<>;
{ using _required_ctes = detail::make_joined_set_t<required_ctes_of<Tables>...>;
using _parameters = std::tuple<>;
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 _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 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 // Data
using _data_t = extra_tables_data_t<Tables...>; using _data_t = extra_tables_data_t<Tables...>;
@ -78,9 +66,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = extra_tables_data_t<Tables...>; using _data_t = extra_tables_data_t<Tables...>;
@ -93,13 +81,8 @@ namespace sqlpp
{ {
return t.extra_tables; return t.extra_tables;
} }
};
// Additional methods for the statement using _consistency_check = consistent_t;
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
}; };
}; };
@ -107,7 +90,7 @@ namespace sqlpp
struct no_extra_tables_t struct no_extra_tables_t
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = no_data_t; using _data_t = no_data_t;
@ -119,9 +102,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = no_data_t; using _data_t = no_data_t;
@ -134,21 +117,42 @@ namespace sqlpp
{ {
return t.no_extra_tables; return t.no_extra_tables;
} }
};
template<typename Policies> template<typename Check, typename T>
struct _methods_t using _new_statement_t = new_statement_t<Check::value, Policies, no_extra_tables_t, T>;
template<typename... T>
using _check = logic::all_t<is_table_t<T>::value...>;
using _consistency_check = consistent_t;
template<typename... Tables>
auto extra_tables(Tables... tables) const
-> _new_statement_t<_check<Tables...>, extra_tables_t<Tables...>>
{ {
template<typename T> static_assert(_check<Tables...>::value, "at least one argument is not a table or join in extra_tables()");
using _new_statement_t = new_statement<Policies, no_extra_tables_t, T>;
static void _check_consistency() {} return _extra_tables_impl<void>(_check<Tables...>{}, tables...);
}
template<typename... Args> private:
auto extra_tables(Args...) const template<typename Database, typename... Tables>
-> _new_statement_t<extra_tables_t<Args...>> auto _extra_tables_impl(const std::false_type&, Tables... tables) const
-> bad_statement;
template<typename Database, typename... Tables>
auto _extra_tables_impl(const std::true_type&, Tables...) const
-> _new_statement_t<std::true_type, extra_tables_t<Tables...>>
{ {
return { static_cast<const derived_statement_t<Policies>&>(*this), extra_tables_data_t<Args...>{} }; static_assert(required_tables_of<extra_tables_t<Tables...>>::size::value == 0, "at least one table depends on another table in extra_tables()");
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
using _unique_table_names = detail::transform_set_t<name_of, _unique_tables>;
static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in extra_tables()");
static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in extra_tables()");
return { static_cast<const derived_statement_t<Policies>&>(*this), extra_tables_data_t<Tables...>{} };
} }
}; };
}; };
@ -157,6 +161,7 @@ namespace sqlpp
template<typename Context, typename Database, typename... Tables> template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, extra_tables_data_t<Database, Tables...>> struct serializer_t<Context, extra_tables_data_t<Database, Tables...>>
{ {
using _serialize_check = serialize_check_of<Context, Tables...>;
using T = extra_tables_data_t<Database, Tables...>; using T = extra_tables_data_t<Database, Tables...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -38,9 +38,9 @@ namespace sqlpp
tag_if<tag::can_be_null, CanBeNull>, tag_if<tag::can_be_null, CanBeNull>,
tag_if<tag::null_is_trivial_value, NullIsTrivialValue> tag_if<tag::null_is_trivial_value, NullIsTrivialValue>
>; >;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
using _name_t = NameType; using _alias_t = NameType;
}; };
template<typename AliasProvider, typename FieldSpecTuple> template<typename AliasProvider, typename FieldSpecTuple>
@ -56,9 +56,9 @@ namespace sqlpp
static constexpr bool _can_be_null = can_be_null_t<NamedExpr>::value; static constexpr bool _can_be_null = can_be_null_t<NamedExpr>::value;
static constexpr bool _depends_on_outer_table = detail::make_intersect_set_t<required_tables_of<NamedExpr>, typename Select::_used_outer_tables>::size::value > 0; static constexpr bool _depends_on_outer_table = detail::make_intersect_set_t<required_tables_of<NamedExpr>, typename Select::_used_outer_tables>::size::value > 0;
using type = field_spec_t<typename NamedExpr::_name_t, using type = field_spec_t<typename NamedExpr::_alias_t,
value_type_of<NamedExpr>, value_type_of<NamedExpr>,
detail::any_t<_can_be_null, _depends_on_outer_table>::value, logic::any_t<_can_be_null, _depends_on_outer_table>::value,
null_is_trivial_value_t<NamedExpr>::value>; null_is_trivial_value_t<NamedExpr>::value>;
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -27,11 +27,12 @@
#ifndef SQLPP_FROM_H #ifndef SQLPP_FROM_H
#define SQLPP_FROM_H #define SQLPP_FROM_H
#include <sqlpp11/table_ref.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/no_data.h> #include <sqlpp11/no_data.h>
#include <sqlpp11/interpretable_list.h> #include <sqlpp11/interpretable_list.h>
#include <sqlpp11/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
#include <sqlpp11/detail/sum.h> #include <sqlpp11/detail/sum.h>
#include <sqlpp11/policy_update.h> #include <sqlpp11/policy_update.h>
@ -60,7 +61,7 @@ namespace sqlpp
struct from_t struct from_t
{ {
using _traits = make_traits<no_value_t, tag::is_from>; using _traits = make_traits<no_value_t, tag::is_from>;
using _recursive_traits = make_recursive_traits<Tables...>; using _nodes = detail::type_vector<Tables...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
// Data // Data
@ -77,9 +78,11 @@ namespace sqlpp
static_assert(is_table_t<Table>::value, "invalid table argument in from::add()"); static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
using _known_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table using _known_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table
using _known_table_names = detail::transform_set_t<name_of, _known_tables>; using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
static_assert(not detail::is_element_of<typename Table::_name_t, _known_table_names>::value, "Must not use the same table name twice in from()"); static_assert(not detail::is_element_of<typename Table::_alias_t, _known_table_names>::value, "Must not use the same table name twice in from()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Table>;
_serialize_check::_();
using ok = detail::all_t<_is_dynamic::value, is_table_t<Table>::value>; using ok = logic::all_t<_is_dynamic::value, is_table_t<Table>::value, _serialize_check::type::value>;
_add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
} }
@ -88,7 +91,7 @@ namespace sqlpp
template<typename Table> template<typename Table>
void _add_impl(Table table, const std::true_type&) void _add_impl(Table table, const std::true_type&)
{ {
return _data._dynamic_tables.emplace_back(table); return _data._dynamic_tables.emplace_back(from_table(table));
} }
template<typename Table> template<typename Table>
@ -98,9 +101,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = from_data_t<Database, Tables...>; using _data_t = from_data_t<Database, Tables...>;
@ -113,20 +116,16 @@ namespace sqlpp
{ {
return t.from; return t.from;
} }
};
// Additional methods for the statement // FIXME: We might want to check if we have too many tables define in the FROM
template<typename Policies> using _consistency_check = consistent_t;
struct _methods_t
{
static void _check_consistency() {}
}; };
}; };
struct no_from_t struct no_from_t
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = no_data_t; using _data_t = no_data_t;
@ -138,9 +137,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = no_data_t; using _data_t = no_data_t;
@ -153,41 +152,45 @@ namespace sqlpp
{ {
return t.no_from; return t.no_from;
} }
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = new_statement<Policies, no_from_t, T>;
static void _check_consistency() {} template<typename... T>
using _check = logic::all_t<is_table_t<T>::value...>;
template<typename Check, typename T>
using _new_statement_t = new_statement_t<Check::value, Policies, no_from_t, T>;
using _consistency_check = consistent_t;
template<typename... Tables> template<typename... Tables>
auto from(Tables... tables) const auto from(Tables... tables) const
-> _new_statement_t<from_t<void, Tables...>> -> _new_statement_t<_check<Tables...>, from_t<void, from_table_t<Tables>...>>
{ {
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
static_assert(sizeof...(Tables), "at least one table or join argument required in from()"); static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
return _from_impl<void>(tables...); return _from_impl<void>(_check<Tables...>{}, tables...);
} }
template<typename... Tables> template<typename... Tables>
auto dynamic_from(Tables... tables) const auto dynamic_from(Tables... tables) const
-> _new_statement_t<from_t<_database_t, Tables...>> -> _new_statement_t<_check<Tables...>, from_t<_database_t, from_table_t<Tables>...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
return _from_impl<_database_t>(tables...); static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
return _from_impl<_database_t>(_check<Tables...>{}, tables...);
} }
private: private:
template<typename Database, typename... Tables> template<typename Database, typename... Tables>
auto _from_impl(Tables... tables) const auto _from_impl(const std::false_type&, Tables... tables) const
-> _new_statement_t<from_t<Database, Tables...>> -> bad_statement;
template<typename Database, typename... Tables>
auto _from_impl(const std::true_type&, Tables... tables) const
-> _new_statement_t<std::true_type, from_t<Database, from_table_t<Tables>...>>
{ {
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 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...); static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>; using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
@ -195,7 +198,7 @@ namespace sqlpp
static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()"); static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()");
static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()"); static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()");
return { static_cast<const derived_statement_t<Policies>&>(*this), from_data_t<Database, Tables...>{tables...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), from_data_t<Database, from_table_t<Tables>...>{from_table(tables)...} };
} }
}; };
@ -205,6 +208,7 @@ namespace sqlpp
template<typename Context, typename Database, typename... Tables> template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, from_data_t<Database, Tables...>> struct serializer_t<Context, from_data_t<Database, Tables...>>
{ {
using _serialize_check = serialize_check_of<Context, Tables...>;
using T = from_data_t<Database, Tables...>; using T = from_data_t<Database, Tables...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -220,6 +224,11 @@ namespace sqlpp
} }
}; };
template<typename... T>
auto from(T&&... t) -> decltype(statement_t<void, no_from_t>().from(std::forward<T>(t)...))
{
return statement_t<void, no_from_t>().from(std::forward<T>(t)...);
}
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -31,7 +31,9 @@
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/column_types.h> #include <sqlpp11/column_types.h>
#include <sqlpp11/in.h> #include <sqlpp11/in.h>
#include <sqlpp11/not_in.h>
#include <sqlpp11/is_null.h> #include <sqlpp11/is_null.h>
#include <sqlpp11/is_not_null.h>
#include <sqlpp11/value_type.h> #include <sqlpp11/value_type.h>
#include <sqlpp11/exists.h> #include <sqlpp11/exists.h>
#include <sqlpp11/any.h> #include <sqlpp11/any.h>
@ -80,7 +82,7 @@ namespace sqlpp
struct value_list_t // to be used in .in() method struct value_list_t // to be used in .in() method
{ {
using _traits = make_traits<value_type_t<typename Container::value_type>, tag::is_expression>; using _traits = make_traits<value_type_t<typename Container::value_type>, tag::is_expression>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
using _container_t = Container; using _container_t = Container;
@ -100,10 +102,16 @@ namespace sqlpp
template<typename Context, typename Container> template<typename Context, typename Container>
struct serializer_t<Context, value_list_t<Container>> struct serializer_t<Context, value_list_t<Container>>
{ {
using _serialize_check = serialize_check_of<Context, wrap_operand_t<typename Container::value_type>>;
using T = value_list_t<Container>; using T = value_list_t<Container>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
if (t._container.size() == 1)
{
return serialize(value(*begin(t._container)), context);
}
bool first = true; bool first = true;
for (const auto& entry: t._container) for (const auto& entry: t._container)
{ {
@ -112,7 +120,7 @@ namespace sqlpp
else else
context << ','; context << ',';
serialize(value(entry), context); serialize_operand(value(entry), context);
} }
return context; return context;
} }
@ -128,7 +136,7 @@ namespace sqlpp
template<typename T> template<typename T>
constexpr const char* get_sql_name(const T&) constexpr const char* get_sql_name(const T&)
{ {
return T::_name_t::_get_name(); return name_of<T>::char_ptr();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -33,7 +33,7 @@
#include <sqlpp11/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h> #include <sqlpp11/interpretable_list.h>
#include <sqlpp11/policy_update.h> #include <sqlpp11/policy_update.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
namespace sqlpp namespace sqlpp
{ {
@ -55,21 +55,26 @@ namespace sqlpp
interpretable_list_t<Database> _dynamic_expressions; interpretable_list_t<Database> _dynamic_expressions;
}; };
struct assert_no_unknown_tables_in_group_by_t
{
using type = std::false_type;
template<typename T = void>
static void _()
{
static_assert(wrong_t<T>::value, "at least one group-by expression requires a table which is otherwise not known in the statement");
}
};
// GROUP BY // GROUP BY
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct group_by_t struct group_by_t
{ {
using _traits = make_traits<no_value_t, tag::is_group_by>; using _traits = make_traits<no_value_t, tag::is_group_by>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _nodes = detail::type_vector<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
static_assert(detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()");
// Data // Data
using _data_t = group_by_data_t<Database, Expressions...>; using _data_t = group_by_data_t<Database, Expressions...>;
@ -89,8 +94,10 @@ namespace sqlpp
static_assert(_is_dynamic::value, "add() must not be called for static group_by"); static_assert(_is_dynamic::value, "add() must not be called for static group_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in group_by::add()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in group_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in group_by::add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in group_by::add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
_serialize_check::_();
using ok = detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expression>::value, _serialize_check::type::value>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
} }
@ -108,9 +115,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = group_by_data_t<Database, Expressions...>; using _data_t = group_by_data_t<Database, Expressions...>;
@ -123,12 +130,10 @@ namespace sqlpp
{ {
return t.group_by; return t.group_by;
} }
};
template<typename Policies> using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<group_by_t>::value,
struct _methods_t consistent_t,
{ assert_no_unknown_tables_in_group_by_t>::type;
static void _check_consistency() {}
}; };
}; };
@ -136,7 +141,7 @@ namespace sqlpp
struct no_group_by_t struct no_group_by_t
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = no_data_t; using _data_t = no_data_t;
@ -148,9 +153,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = no_data_t; using _data_t = no_data_t;
@ -163,30 +168,49 @@ namespace sqlpp
{ {
return t.no_group_by; return t.no_group_by;
} }
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = new_statement<Policies, no_group_by_t, T>;
static void _check_consistency() {} template<typename... T>
using _check = logic::all_t<is_expression_t<T>::value...>;
template<typename... Args> template<typename Check, typename T>
auto group_by(Args... args) const using _new_statement_t = new_statement_t<Check::value, Policies, no_group_by_t, T>;
-> _new_statement_t<group_by_t<void, Args...>>
using _consistency_check = consistent_t;
template<typename... Expressions>
auto group_by(Expressions... expressions) const
-> _new_statement_t<_check<Expressions...>, group_by_t<void, Expressions...>>
{ {
return { static_cast<const derived_statement_t<Policies>&>(*this), group_by_data_t<void, Args...>{args...} }; static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in group_by()");
return _group_by_impl<void>(_check<Expressions...>{}, expressions...);
} }
template<typename... Args> template<typename... Expressions>
auto dynamic_group_by(Args... args) const auto dynamic_group_by(Expressions... expressions) const
-> _new_statement_t<group_by_t<_database_t, Args...>> -> _new_statement_t<_check<Expressions...>, group_by_t<_database_t, Expressions...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement");
return { static_cast<const derived_statement_t<Policies>&>(*this), group_by_data_t<_database_t, Args...>{args...} }; static_assert(_check<Expressions...>::value, "at least one argument is not an expression in group_by()");
return _group_by_impl<_database_t>(_check<Expressions...>{}, expressions...);
}
private:
template<typename Database, typename... Expressions>
auto _group_by_impl(const std::false_type&, Expressions... expressions) const
-> bad_statement;
template<typename Database, typename... Expressions>
auto _group_by_impl(const std::true_type&, Expressions... expressions) const
-> _new_statement_t<std::true_type, group_by_t<_database_t, Expressions...>>
{
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
return { static_cast<const derived_statement_t<Policies>&>(*this), group_by_data_t<Database, Expressions...>{expressions...} };
} }
}; };
}; };
@ -195,6 +219,7 @@ namespace sqlpp
template<typename Context, typename Database, typename... Expressions> template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, group_by_data_t<Database, Expressions...>> struct serializer_t<Context, group_by_data_t<Database, Expressions...>>
{ {
using _serialize_check = serialize_check_of<Context, Expressions...>;
using T = group_by_data_t<Database, Expressions...>; using T = group_by_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -32,7 +32,7 @@
#include <sqlpp11/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h> #include <sqlpp11/interpretable_list.h>
#include <sqlpp11/policy_update.h> #include <sqlpp11/policy_update.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
namespace sqlpp namespace sqlpp
{ {
@ -54,18 +54,26 @@ namespace sqlpp
interpretable_list_t<Database> _dynamic_expressions; interpretable_list_t<Database> _dynamic_expressions;
}; };
struct assert_no_unknown_tables_in_having_t
{
using type = std::false_type;
template<typename T = void>
static void _()
{
static_assert(wrong_t<T>::value, "at least one having-expression requires a table which is otherwise not known in the statement");
}
};
// HAVING // HAVING
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct having_t struct having_t
{ {
using _traits = make_traits<no_value_t, tag::is_having>; using _traits = make_traits<no_value_t, tag::is_having>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _nodes = detail::type_vector<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()");
static_assert(detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()");
// Data // Data
using _data_t = having_data_t<Database, Expressions...>; using _data_t = having_data_t<Database, Expressions...>;
@ -85,8 +93,10 @@ namespace sqlpp
static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having"); static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()"); static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in having::add()"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in having::add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
_serialize_check::_();
using ok = detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expression>::value, _serialize_check::type::value>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
} }
@ -105,9 +115,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = having_data_t<Database, Expressions...>; using _data_t = having_data_t<Database, Expressions...>;
@ -120,13 +130,10 @@ namespace sqlpp
{ {
return t.having; return t.having;
} }
};
// Additional methods for the statement using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<having_t>::value,
template<typename Policies> consistent_t,
struct _methods_t assert_no_unknown_tables_in_having_t>::type;
{
static void _check_consistency() {}
}; };
}; };
@ -134,7 +141,7 @@ namespace sqlpp
struct no_having_t struct no_having_t
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = no_data_t; using _data_t = no_data_t;
@ -146,9 +153,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = no_data_t; using _data_t = no_data_t;
@ -161,31 +168,48 @@ namespace sqlpp
{ {
return t.no_having; return t.no_having;
} }
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = new_statement<Policies, no_having_t, T>;
static void _check_consistency() {} template<typename... T>
using _check = logic::all_t<is_expression_t<T>::value...>;
template<typename... Args> template<typename Check, typename T>
auto having(Args... args) const using _new_statement_t = new_statement_t<Check::value, Policies, no_having_t, T>;
-> _new_statement_t<having_t<void, Args...>>
using _consistency_check = consistent_t;
template<typename... Expressions>
auto having(Expressions... expressions) const
-> _new_statement_t<_check<Expressions...>, having_t<void, Expressions...>>
{ {
return { static_cast<const derived_statement_t<Policies>&>(*this), having_data_t<void, Args...>{args...} }; static_assert(_check<Expressions...>::value, "at least one argument is not an expression in having()");
static_assert(sizeof...(Expressions), "at least one expression argument required in having()");
return _having_impl<void>(_check<Expressions...>{}, expressions...);
} }
template<typename... Args> template<typename... Expressions>
auto dynamic_having(Args... args) const auto dynamic_having(Expressions... expressions) const
-> _new_statement_t<having_t<_database_t, Args...>> -> _new_statement_t<_check<Expressions...>, having_t<_database_t, Expressions...>>
{ {
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in having()");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement");
return { static_cast<const derived_statement_t<Policies>&>(*this), having_data_t<_database_t, Args...>{args...} }; return _having_impl<_database_t>(_check<Expressions...>{}, expressions...);
} }
private:
template<typename Database, typename... Expressions>
auto _having_impl(const std::false_type&, Expressions... expressions) const
-> bad_statement;
template<typename Database, typename... Expressions>
auto _having_impl(const std::true_type&, Expressions... expressions) const
-> _new_statement_t<std::true_type, having_t<Database, Expressions...>>
{
return { static_cast<const derived_statement_t<Policies>&>(*this), having_data_t<_database_t, Expressions...>{expressions...} };
}
}; };
}; };
@ -193,6 +217,7 @@ namespace sqlpp
template<typename Context, typename Database, typename... Expressions> template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, having_data_t<Database, Expressions...>> struct serializer_t<Context, having_data_t<Database, Expressions...>>
{ {
using _serialize_check = serialize_check_of<Context, Expressions...>;
using T = having_data_t<Database, Expressions...>; using T = having_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

66
include/sqlpp11/hidden.h Normal file
View File

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

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,26 +28,27 @@
#define SQLPP_IN_H #define SQLPP_IN_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/boolean.h> #include <sqlpp11/boolean.h>
#include <sqlpp11/in_fwd.h> #include <sqlpp11/in_fwd.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
{ {
template<bool NotInverted, typename Operand, typename... Args> template<typename Operand, typename... Args>
struct in_t: struct in_t:
public expression_operators<in_t<NotInverted, Operand, Args...>, boolean>, public expression_operators<in_t<Operand, Args...>, boolean>,
public alias_operators<in_t<NotInverted, Operand, Args...>> public alias_operators<in_t<Operand, Args...>>
{ {
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>; using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand, Args...>; using _nodes = detail::type_vector<Operand, Args...>;
static constexpr bool _inverted = not NotInverted;
static_assert(sizeof...(Args) > 0, "in() requires at least one argument"); static_assert(sizeof...(Args) > 0, "in() requires at least one argument");
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; } static constexpr const char _literal[] = "in_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -70,18 +71,18 @@ namespace sqlpp
std::tuple<Args...> _args; std::tuple<Args...> _args;
}; };
template<typename Context, bool NotInverted, typename Operand, typename... Args> template<typename Context, typename Operand, typename... Args>
struct serializer_t<Context, in_t<NotInverted, Operand, Args...>> struct serializer_t<Context, in_t<Operand, Args...>>
{ {
using T = in_t<NotInverted, Operand, Args...>; using _serialize_check = serialize_check_of<Context, Args...>;
using T = in_t<Operand, Args...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
serialize(t._operand, context); serialize(t._operand, context);
context << (t._inverted ? " NOT IN(" : " IN("); context << " IN(";
if (sizeof...(Args) == 1) 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 serialize(std::get<0>(t._args), context);
// see https://github.com/rbock/sqlpp11/issues/18
else else
interpret_tuple(t._args, ',', context); interpret_tuple(t._args, ',', context);
context << ')'; context << ')';

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -29,8 +29,10 @@
namespace sqlpp namespace sqlpp
{ {
template<bool NotInverted, typename Operand, typename... Args> template<typename Operand, typename... Args>
struct in_t; struct in_t;
template<typename Operand, typename... Args>
struct not_in_t;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -44,33 +44,44 @@ namespace sqlpp
struct insert_t: public statement_name_t<insert_name_t> struct insert_t: public statement_name_t<insert_name_t>
{ {
using _traits = make_traits<no_value_t, tag::is_return_value>; using _traits = make_traits<no_value_t, tag::is_return_value>;
struct _name_t {}; struct _alias_t {};
template<typename Policies> template<typename Statement>
struct _result_methods_t struct _result_methods_t
{ {
using _statement_t = derived_statement_t<Policies>; using _statement_t = Statement;
const _statement_t& _get_statement() const const _statement_t& _get_statement() const
{ {
return static_cast<const _statement_t&>(*this); return static_cast<const _statement_t&>(*this);
} }
// Execute
template<typename Db, typename Composite>
auto _run(Db& db, const Composite& composite) const
-> decltype(db.insert(composite))
{
return db.insert(composite);
}
template<typename Db> template<typename Db>
auto _run(Db& db) const -> decltype(db.insert(this->_get_statement())) auto _run(Db& db) const -> decltype(db.insert(this->_get_statement()))
{ {
_statement_t::_check_consistency();
static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
return db.insert(_get_statement()); return db.insert(_get_statement());
} }
// Prepare
template<typename Db, typename Composite>
auto _prepare(Db& db, const Composite& composite) const
-> prepared_insert_t<Db, Composite>
{
return {{}, db.prepare_insert(composite)};
}
template<typename Db> template<typename Db>
auto _prepare(Db& db) const auto _prepare(Db& db) const
-> prepared_insert_t<Db, _statement_t> -> prepared_insert_t<Db, _statement_t>
{ {
_statement_t::_check_consistency();
return {{}, db.prepare_insert(_get_statement())}; return {{}, db.prepare_insert(_get_statement())};
} }
}; };
@ -79,6 +90,7 @@ namespace sqlpp
template<typename Context> template<typename Context>
struct serializer_t<Context, insert_name_t> struct serializer_t<Context, insert_name_t>
{ {
using _serialize_check = consistent_t;
using T = insert_name_t; using T = insert_name_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -50,7 +50,7 @@ namespace sqlpp
struct type struct type
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
}; };
}; };
} }
@ -103,6 +103,7 @@ namespace sqlpp
template<typename Context, typename ValueType> template<typename Context, typename ValueType>
struct serializer_t<Context, insert_value_t<ValueType>> struct serializer_t<Context, insert_value_t<ValueType>>
{ {
using _serialize_check = serialize_check_of<Context, ValueType>;
using T = insert_value_t<ValueType>; using T = insert_value_t<ValueType>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -115,7 +116,7 @@ namespace sqlpp
else if (t._is_default) else if (t._is_default)
context << "DEFAULT"; context << "DEFAULT";
else else
serialize(t._value, context); serialize_operand(t._value, context);
return context; return context;
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,7 +28,7 @@
#define SQLPP_INSERT_VALUE_LIST_H #define SQLPP_INSERT_VALUE_LIST_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
#include <sqlpp11/assignment.h> #include <sqlpp11/assignment.h>
#include <sqlpp11/interpretable_list.h> #include <sqlpp11/interpretable_list.h>
#include <sqlpp11/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
@ -41,20 +41,20 @@ namespace sqlpp
{ {
namespace detail namespace detail
{ {
template<typename... Args> template<typename... Columns>
struct first_arg_impl struct have_all_required_columns
{ {
static_assert(wrong_t<first_arg_impl>::value, "At least one argument required"); static constexpr bool value = false;
}; };
template<typename T, typename... Args> template<typename First, typename... Columns>
struct first_arg_impl<T, Args...> struct have_all_required_columns<First, Columns...>
{ {
using type = T; using _table = typename First::_table;
using required_columns = typename _table::_required_insert_columns;
using set_columns = detail::make_type_set_t<First, Columns...>;
static constexpr bool value = detail::is_subset_of<required_columns, set_columns>::value;
}; };
template<typename... Args>
using first_arg_t = typename first_arg_impl<Args...>::type;
} }
struct insert_default_values_data_t struct insert_default_values_data_t
@ -64,7 +64,7 @@ namespace sqlpp
struct insert_default_values_t struct insert_default_values_t
{ {
using _traits = make_traits<no_value_t>; using _traits = make_traits<no_value_t>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = insert_default_values_data_t; using _data_t = insert_default_values_data_t;
@ -76,9 +76,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = insert_default_values_data_t; using _data_t = insert_default_values_data_t;
@ -91,12 +91,8 @@ namespace sqlpp
{ {
return t.default_values; return t.default_values;
} }
};
template<typename Policies> using _consistency_check = consistent_t;
struct _methods_t
{
static void _check_consistency() {}
}; };
}; };
@ -122,11 +118,22 @@ namespace sqlpp
interpretable_list_t<Database> _dynamic_values; interpretable_list_t<Database> _dynamic_values;
}; };
struct assert_no_unknown_tables_in_insert_assignments_t
{
using type = std::false_type;
template<typename T = void>
static void _()
{
static_assert(wrong_t<T>::value, "at least one insert assignment requires a table which is otherwise not known in the statement");
}
};
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
struct insert_list_t struct insert_list_t
{ {
using _traits = make_traits<no_value_t, tag::is_insert_list>; using _traits = make_traits<no_value_t, tag::is_insert_list>;
using _recursive_traits = make_recursive_traits<lhs_t<Assignments>..., rhs_t<Assignments>...>; using _nodes = detail::type_vector<lhs_t<Assignments>..., rhs_t<Assignments>...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
@ -157,10 +164,13 @@ namespace sqlpp
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value, "Must not assign value to column twice"); static_assert(not 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 must_not_insert_t<lhs_t<Assignment>>::value, "add() argument must not be used in insert");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table"); static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Assignment>;
_serialize_check::_();
using ok = detail::all_t< using ok = logic::all_t<
_is_dynamic::value, _is_dynamic::value,
is_assignment_t<Assignment>::value>; is_assignment_t<Assignment>::value,
_serialize_check::type::value>;
_add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
} }
@ -179,9 +189,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = insert_list_data_t<Database, Assignments...>; using _data_t = insert_list_data_t<Database, Assignments...>;
@ -194,13 +204,10 @@ namespace sqlpp
{ {
return t.insert_list; return t.insert_list;
} }
};
// Additional methods for the statement using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<insert_list_t>::value,
template<typename Policies> consistent_t,
struct _methods_t assert_no_unknown_tables_in_insert_assignments_t>::type;
{
static void _check_consistency() {}
}; };
}; };
@ -223,11 +230,22 @@ namespace sqlpp
std::vector<_value_tuple_t> _insert_values; std::vector<_value_tuple_t> _insert_values;
}; };
struct assert_no_unknown_tables_in_column_list_t
{
using type = std::false_type;
template<typename T = void>
static void _()
{
static_assert(wrong_t<T>::value, "at least one column requires a table which is otherwise not known in the statement");
}
};
template<typename... Columns> template<typename... Columns>
struct column_list_t struct column_list_t
{ {
using _traits = make_traits<no_value_t, tag::is_column_list>; using _traits = make_traits<no_value_t, tag::is_column_list>;
using _recursive_traits = make_recursive_traits<Columns...>; using _nodes = detail::type_vector<Columns...>;
using _value_tuple_t = typename column_list_data_t<Columns...>::_value_tuple_t; using _value_tuple_t = typename column_list_data_t<Columns...>::_value_tuple_t;
@ -242,13 +260,13 @@ namespace sqlpp
template<typename... Assignments> template<typename... Assignments>
void add(Assignments... assignments) void add(Assignments... assignments)
{ {
static_assert(detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments"); static_assert(logic::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 _arg_value_tuple = std::tuple<insert_value_t<lhs_t<Assignments>>...>;
using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>; using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>;
static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments"); static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments");
using ok = detail::all_t< using ok = logic::all_t<
detail::all_t<is_assignment_t<Assignments>::value...>::value, logic::all_t<is_assignment_t<Assignments>::value...>::value,
_args_correct::value>; _args_correct::value>;
_add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert _add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
@ -267,9 +285,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = column_list_data_t<Columns...>; using _data_t = column_list_data_t<Columns...>;
@ -282,21 +300,29 @@ namespace sqlpp
{ {
return t.values; return t.values;
} }
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<column_list_t>::value,
consistent_t,
assert_no_unknown_tables_in_column_list_t>::type;
};
}; };
// Additional methods for the statement struct assert_insert_values_t
template<typename Policies>
struct _methods_t
{ {
static void _check_consistency() {} using type = std::false_type;
};
template<typename T = void>
static void _()
{
static_assert(wrong_t<T>::value, "insert values required, e.g. set(...) or default_values()");
}
}; };
// NO INSERT COLUMNS/VALUES YET // NO INSERT COLUMNS/VALUES YET
struct no_insert_value_list_t struct no_insert_value_list_t
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = no_data_t; using _data_t = no_data_t;
@ -308,9 +334,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = no_data_t; using _data_t = no_data_t;
@ -323,78 +349,90 @@ namespace sqlpp
{ {
return t.no_insert_values; return t.no_insert_values;
} }
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = new_statement<Policies, no_insert_value_list_t, T>;
static void _check_consistency() template<typename... T>
{ using _column_check = logic::all_t<is_column_t<T>::value...>;
static_assert(wrong_t<_methods_t>::value, "insert values required, e.g. set(...) or default_values()");
} template<typename... T>
using _assignment_check = logic::all_t<is_assignment_t<T>::value...>;
template<typename Check, typename T>
using _new_statement_t = new_statement_t<Check::value, Policies, no_insert_value_list_t, T>;
using _consistency_check = assert_insert_values_t;
auto default_values() const auto default_values() const
-> _new_statement_t<insert_default_values_t> -> _new_statement_t<std::true_type, insert_default_values_t>
{ {
return { static_cast<const derived_statement_t<Policies>&>(*this), insert_default_values_data_t{} }; return { static_cast<const derived_statement_t<Policies>&>(*this), insert_default_values_data_t{} };
} }
template<typename... Columns> template<typename... Columns>
auto columns(Columns... columns) const auto columns(Columns... columns) const
-> _new_statement_t<column_list_t<Columns...>> -> _new_statement_t<_column_check<Columns...>, column_list_t<Columns...>>
{ {
static_assert(logic::all_t<is_column_t<Columns>::value...>::value, "at least one argument is not a column in columns()");
static_assert(sizeof...(Columns), "at least one column required in columns()"); static_assert(sizeof...(Columns), "at least one column required in columns()");
static_assert(not 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; return _columns_impl(_column_check<Columns...>{}, columns...);
using required_columns = typename _table::_required_insert_columns;
using set_columns = detail::make_type_set_t<Columns...>;
static_assert(detail::is_subset_of<required_columns, set_columns>::value, "At least one required column is missing in columns()");
return { static_cast<const derived_statement_t<Policies>&>(*this), column_list_data_t<Columns...>{columns...} };
} }
template<typename... Assignments> template<typename... Assignments>
auto set(Assignments... assignments) const auto set(Assignments... assignments) const
-> _new_statement_t<insert_list_t<void, Assignments...>> -> _new_statement_t<_assignment_check<Assignments...>, insert_list_t<void, Assignments...>>
{ {
static_assert(_assignment_check<Assignments...>::value, "at least one argument is not an assignment in set()");
static_assert(sizeof...(Assignments), "at least one assignment expression required in set()"); static_assert(sizeof...(Assignments), "at least one assignment expression required in set()");
static_assert(detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()");
using _table = typename lhs_t<detail::first_arg_t<Assignments...>>::_table; return _set_impl<void>(_assignment_check<Assignments...>{}, assignments...);
using required_columns = typename _table::_required_insert_columns;
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> template<typename... Assignments>
auto dynamic_set(Assignments... assignments) const auto dynamic_set(Assignments... assignments) const
-> _new_statement_t<insert_list_t<_database_t, Assignments...>> -> _new_statement_t<_assignment_check<Assignments...>, insert_list_t<_database_t, Assignments...>>
{ {
static_assert(_assignment_check<Assignments...>::value, "at least one argument is not an assignment in set()");
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement");
static_assert(detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()");
return _set_impl<_database_t>(assignments...); return _set_impl<_database_t>(_assignment_check<Assignments...>{}, assignments...);
} }
private: private:
template<typename... Columns>
auto _columns_impl(const std::false_type&, Columns... columns) const
-> bad_statement;
template<typename... Columns>
auto _columns_impl(const std::true_type&, Columns... columns) const
-> _new_statement_t<std::true_type, column_list_t<Columns...>>
{
static_assert(not detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected in columns()");
static_assert(logic::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");
static_assert(detail::have_all_required_columns<Columns...>::value, "At least one required column is missing in columns()");
return { static_cast<const derived_statement_t<Policies>&>(*this), column_list_data_t<Columns...>{columns...} };
}
template<typename Database, typename... Assignments> template<typename Database, typename... Assignments>
auto _set_impl(Assignments... assignments) const auto _set_impl(const std::false_type&, Assignments... assignments) const
-> _new_statement_t<insert_list_t<Database, Assignments...>> -> bad_statement;
template<typename Database, typename... Assignments>
auto _set_impl(const std::true_type&, Assignments... assignments) const
-> _new_statement_t<std::true_type, insert_list_t<Database, Assignments...>>
{ {
static_assert(not detail::has_duplicates<lhs_t<Assignments>...>::value, "at least one duplicate column detected 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()"); static_assert(logic::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 = detail::make_joined_set_t<required_tables_of<lhs_t<Assignments>>...>; using _column_required_tables = detail::make_joined_set_t<required_tables_of<lhs_t<Assignments>>...>;
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from several tables"); static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from several tables");
static_assert(not std::is_same<_database_t, void>::value or detail::have_all_required_columns<lhs_t<Assignments>...>::value, "At least one required column is missing in set()");
return { static_cast<const derived_statement_t<Policies>&>(*this), insert_list_data_t<Database, Assignments...>{assignments...} }; return { static_cast<const derived_statement_t<Policies>&>(*this), insert_list_data_t<Database, Assignments...>{assignments...} };
} }
}; };
@ -404,6 +442,7 @@ namespace sqlpp
template<typename Context> template<typename Context>
struct serializer_t<Context, insert_default_values_data_t> struct serializer_t<Context, insert_default_values_data_t>
{ {
using _serialize_check = consistent_t;
using T = insert_default_values_data_t; using T = insert_default_values_data_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -416,6 +455,7 @@ namespace sqlpp
template<typename Context, typename... Columns> template<typename Context, typename... Columns>
struct serializer_t<Context, column_list_data_t<Columns...>> struct serializer_t<Context, column_list_data_t<Columns...>>
{ {
using _serialize_check = serialize_check_of<Context, Columns...>;
using T = column_list_data_t<Columns...>; using T = column_list_data_t<Columns...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -443,6 +483,7 @@ namespace sqlpp
template<typename Context, typename Database, typename... Assignments> template<typename Context, typename Database, typename... Assignments>
struct serializer_t<Context, insert_list_data_t<Database, Assignments...>> struct serializer_t<Context, insert_list_data_t<Database, Assignments...>>
{ {
using _serialize_check = serialize_check_of<Context, Assignments...>;
using T = insert_list_data_t<Database, Assignments...>; using T = insert_list_data_t<Database, Assignments...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -34,20 +34,19 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Element, typename Separator, typename Context> template<typename Element, typename Separator, typename Context, typename UseBraces>
static void interpret_tuple_element(const Element& element, const Separator& separator, Context& context, size_t index) static void interpret_tuple_element(const Element& element, const Separator& separator, Context& context, const UseBraces&, size_t index)
{ {
if (index) if (index)
context << separator; context << separator;
if (requires_braces_t<Element>::value) if (UseBraces::value)
context << "("; serialize_operand(element, context);
else
serialize(element, context); serialize(element, context);
if (requires_braces_t<Element>::value)
context << ")";
} }
template<typename Tuple, typename Separator, typename Context, size_t... Is> template<typename Tuple, typename Separator, typename Context, typename UseBraces, size_t... Is>
auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const detail::index_sequence<Is...>&) auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const UseBraces& useBraces, const detail::index_sequence<Is...>&)
-> Context& -> Context&
{ {
// Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4. // Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4.
@ -57,7 +56,7 @@ namespace sqlpp
using swallow = int[]; using swallow = int[];
(void) swallow{ (void) swallow{
0, //workaround against -Wpedantic GCC warning "zero-size array 'int [0]'" 0, //workaround against -Wpedantic GCC warning "zero-size array 'int [0]'"
(interpret_tuple_element(std::get<Is>(t), separator, context, Is), 0)...}; (interpret_tuple_element(std::get<Is>(t), separator, context, useBraces, Is), 0)...};
return context; return context;
} }
@ -65,7 +64,14 @@ namespace sqlpp
auto interpret_tuple(const Tuple& t, const Separator& separator, Context& context) auto interpret_tuple(const Tuple& t, const Separator& separator, Context& context)
-> Context& -> Context&
{ {
return interpret_tuple_impl(t, separator, context, detail::make_index_sequence<std::tuple_size<Tuple>::value>{}); return interpret_tuple_impl(t, separator, context, std::true_type{}, detail::make_index_sequence<std::tuple_size<Tuple>::value>{});
}
template<typename Tuple, typename Separator, typename Context>
auto interpret_tuple_without_braces(const Tuple& t, const Separator& separator, Context& context)
-> Context&
{
return interpret_tuple_impl(t, separator, context, std::false_type{}, detail::make_index_sequence<std::tuple_size<Tuple>::value>{});
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -43,6 +43,7 @@ namespace sqlpp
template<typename T> template<typename T>
interpretable_t(T t): interpretable_t(T t):
_requires_braces(requires_braces_t<T>::value),
_impl(std::make_shared<_impl_t<T>>(t)) _impl(std::make_shared<_impl_t<T>>(t))
{} {}
@ -71,6 +72,8 @@ namespace sqlpp
return _impl->interpret(context); return _impl->interpret(context);
} }
bool _requires_braces;
private: private:
struct _impl_base struct _impl_base
{ {
@ -114,11 +117,20 @@ namespace sqlpp
template<typename Context, typename Database> template<typename Context, typename Database>
struct serializer_t<Context, interpretable_t<Database>> struct serializer_t<Context, interpretable_t<Database>>
{ {
using _serialize_check = consistent_t;
using T = interpretable_t<Database>; using T = interpretable_t<Database>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
if (t._requires_braces)
{
context << '(';
t.serialize(context); t.serialize(context);
context << ')';
}
else
t.serialize(context);
return context; return context;
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -27,6 +27,7 @@
#ifndef SQLPP_INTO_H #ifndef SQLPP_INTO_H
#define SQLPP_INTO_H #define SQLPP_INTO_H
#include <sqlpp11/statement_fwd.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/no_value.h> #include <sqlpp11/no_value.h>
#include <sqlpp11/no_data.h> #include <sqlpp11/no_data.h>
@ -58,14 +59,11 @@ namespace sqlpp
struct into_t struct into_t
{ {
using _traits = make_traits<no_value_t, tag::is_into>; using _traits = make_traits<no_value_t, tag::is_into>;
using _recursive_traits = make_recursive_traits<Table>; using _nodes = detail::type_vector<Table>;
static_assert(is_table_t<Table>::value, "argument has to be a table");
static_assert(required_tables_of<Table>::size::value == 0, "table depends on another table");
using _data_t = into_data_t<Database, Table>; using _data_t = into_data_t<Database, Table>;
struct _name_t {}; struct _alias_t {};
// Member implementation with data and methods // Member implementation with data and methods
template <typename Policies> template <typename Policies>
@ -74,9 +72,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = into_data_t<Database, Table>; using _data_t = into_data_t<Database, Table>;
@ -89,22 +87,28 @@ namespace sqlpp
{ {
return t.into; return t.into;
} }
using _consistency_check = consistent_t;
}; };
// Additional methods for the statement };
template<typename Policies>
struct _methods_t struct assert_into_t
{ {
static void _check_consistency() {} using type = std::false_type;
};
template<typename T = void>
static void _()
{
static_assert(wrong_t<T>::value, "into() required");
}
}; };
// NO INTO YET // NO INTO YET
struct no_into_t struct no_into_t
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = no_data_t; using _data_t = no_data_t;
@ -116,9 +120,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = no_data_t; using _data_t = no_data_t;
@ -131,25 +135,37 @@ namespace sqlpp
{ {
return t.no_into; return t.no_into;
} }
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = new_statement<Policies, no_into_t, T>;
static void _check_consistency() template<typename T>
using _check = logic::all_t<is_table_t<T>::value>;
template<typename Check, typename T>
using _new_statement_t = new_statement_t<Check::value, Policies, no_into_t, T>;
using _consistency_check = assert_into_t;
template<typename Table>
auto into(Table table) const
-> _new_statement_t<_check<Table>, into_t<void, Table>>
{ {
static_assert(wrong_t<_methods_t>::value, "into() required"); static_assert(_check<Table>::value, "argument is not a table in into()");
return _into_impl<void>(_check<Table>{}, table);
} }
template<typename... Args> private:
auto into(Args... args) const template<typename Database, typename Table>
-> _new_statement_t<into_t<void, Args...>> auto _into_impl(const std::false_type&, Table table) const
-> bad_statement;
template<typename Database, typename Table>
auto _into_impl(const std::true_type&, Table table) const
-> _new_statement_t<std::true_type, into_t<Database, Table>>
{ {
return { static_cast<const derived_statement_t<Policies>&>(*this), into_data_t<void, Args...>{args...} }; static_assert(required_tables_of<into_t<Database, Table>>::size::value == 0, "argument depends on another table in into()");
return { static_cast<const derived_statement_t<Policies>&>(*this), into_data_t<Database, Table>{table} };
} }
}; };
}; };
@ -158,6 +174,7 @@ namespace sqlpp
template<typename Context, typename Database, typename Table> template<typename Context, typename Database, typename Table>
struct serializer_t<Context, into_data_t<Database, Table>> struct serializer_t<Context, into_data_t<Database, Table>>
{ {
using _serialize_check = serialize_check_of<Context, Table>;
using T = into_data_t<Database, Table>; using T = into_data_t<Database, Table>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -168,6 +185,11 @@ namespace sqlpp
} }
}; };
template<typename T>
auto into(T&& t) -> decltype(statement_t<void, no_into_t>().into(std::forward<T>(t)))
{
return statement_t<void, no_into_t>().into(std::forward<T>(t));
}
} }
#endif #endif

View File

@ -0,0 +1,85 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_IS_NOT_NULL_H
#define SQLPP_IS_NOT_NULL_H
#include <sqlpp11/boolean.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
template<typename Operand>
struct is_not_null_t:
public expression_operators<is_not_null_t<Operand>, boolean>,
public alias_operators<is_not_null_t<Operand>>
{
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _nodes = detail::type_vector<Operand>;
struct _alias_t
{
static constexpr const char _literal[] = "is_not_null_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
T is_not_null;
};
};
is_not_null_t(Operand operand):
_operand(operand)
{}
is_not_null_t(const is_not_null_t&) = default;
is_not_null_t(is_not_null_t&&) = default;
is_not_null_t& operator=(const is_not_null_t&) = default;
is_not_null_t& operator=(is_not_null_t&&) = default;
~is_not_null_t() = default;
Operand _operand;
};
template<typename Context, typename Operand>
struct serializer_t<Context, is_not_null_t<Operand>>
{
using _serialize_check = serialize_check_of<Context, Operand>;
using T = is_not_null_t<Operand>;
static Context& _(const T& t, Context& context)
{
serialize_operand(t._operand, context);
context << " IS NOT NULL";
return context;
}
};
}
#endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -29,27 +29,27 @@
#include <sqlpp11/boolean.h> #include <sqlpp11/boolean.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
{ {
template<bool NotInverted, typename Operand> template<typename Operand>
struct is_null_t: struct is_null_t:
public expression_operators<is_null_t<NotInverted, Operand>, boolean>, public expression_operators<is_null_t<Operand>, boolean>,
public alias_operators<is_null_t<NotInverted, Operand>> public alias_operators<is_null_t<Operand>>
{ {
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>; using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand>; using _nodes = detail::type_vector<Operand>;
static constexpr bool _inverted = not NotInverted; struct _alias_t
struct _name_t
{ {
static constexpr const char* _get_name() { return _inverted ? "IS NOT NULL" : "IS NULL"; } static constexpr const char _literal[] = "is_nnull_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
T in; T is_null;
}; };
}; };
@ -66,15 +66,16 @@ namespace sqlpp
Operand _operand; Operand _operand;
}; };
template<typename Context, bool NotInverted, typename Operand> template<typename Context, typename Operand>
struct serializer_t<Context, is_null_t<NotInverted, Operand>> struct serializer_t<Context, is_null_t<Operand>>
{ {
using T = is_null_t<NotInverted, Operand>; using _serialize_check = serialize_check_of<Context, Operand>;
using T = is_null_t<Operand>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
serialize(t._operand, context); serialize_operand(t._operand, context);
context << (t._inverted ? " IS NOT NULL" : " IS NULL"); context << " IS NULL";
return context; return context;
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -29,8 +29,10 @@
namespace sqlpp namespace sqlpp
{ {
template<bool NotInverted, typename Operand> template<typename Operand>
struct is_null_t; struct is_null_t;
template<typename Operand>
struct is_not_null_t;
} }
#endif #endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -66,16 +66,8 @@ namespace sqlpp
struct join_t struct join_t
{ {
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>; using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
struct _recursive_traits using _nodes = detail::type_vector<Lhs, Rhs>;
{ using _can_be_null = std::false_type;
using _required_tables = detail::make_joined_set_t<required_tables_of<Lhs>, required_tables_of<Rhs>>;
using _provided_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
using _provided_outer_tables = typename JoinType::template _provided_outer_tables<Lhs, Rhs>;
using _extra_tables = detail::make_joined_set_t<extra_tables_of<Lhs>, extra_tables_of<Rhs>>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Lhs>, parameters_of<Rhs>>;
using _tags = detail::type_set<>;
};
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join"); static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table"); static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
@ -84,7 +76,7 @@ namespace sqlpp
static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value, "joined tables must not be identical"); static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value, "joined tables must not be identical");
static_assert(_recursive_traits::_required_tables::size::value == 0, "joined tables must not depend on other tables"); static_assert(required_tables_of<join_t>::size::value == 0, "joined tables must not depend on other tables");
template<typename OnT> template<typename OnT>
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>; using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
@ -94,7 +86,7 @@ namespace sqlpp
-> set_on_t<on_t<void, Expr...>> -> set_on_t<on_t<void, Expr...>>
{ {
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()"); static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
static_assert(detail::all_t<is_expression_t<Expr>::value...>::value, "at least one argument is not an expression in on()"); static_assert(logic::all_t<is_expression_t<Expr>::value...>::value, "at least one argument is not an expression in on()");
return { _lhs, return { _lhs,
_rhs, _rhs,
@ -145,6 +137,7 @@ namespace sqlpp
template<typename Context, typename JoinType, typename Lhs, typename Rhs, typename On> template<typename Context, typename JoinType, typename Lhs, typename Rhs, typename On>
struct serializer_t<Context, join_t<JoinType, Lhs, Rhs, On>> struct serializer_t<Context, join_t<JoinType, Lhs, Rhs, On>>
{ {
using _serialize_check = serialize_check_of<Context, Lhs, Rhs, On>;
using T = join_t<JoinType, Lhs, Rhs, On>; using T = join_t<JoinType, Lhs, Rhs, On>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -29,6 +29,7 @@
#include <sqlpp11/boolean.h> #include <sqlpp11/boolean.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
@ -39,11 +40,12 @@ namespace sqlpp
public alias_operators<like_t<Operand, Pattern>> public alias_operators<like_t<Operand, Pattern>>
{ {
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>; using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Operand, Pattern>; using _nodes = detail::type_vector<Operand, Pattern>;
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "LIKE"; } static constexpr const char _literal[] = "like_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -71,11 +73,12 @@ namespace sqlpp
template<typename Context, typename Operand, typename Pattern> template<typename Context, typename Operand, typename Pattern>
struct serializer_t<Context, like_t<Operand, Pattern>> struct serializer_t<Context, like_t<Operand, Pattern>>
{ {
using _serialize_check = serialize_check_of<Context, Operand, Pattern>;
using T = like_t<Operand, Pattern>; using T = like_t<Operand, Pattern>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
serialize(t._operand, context); serialize_operand(t._operand, context);
context << " LIKE("; context << " LIKE(";
serialize(t._pattern, context); serialize(t._pattern, context);
context << ")"; context << ")";

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -55,9 +55,7 @@ namespace sqlpp
struct limit_t struct limit_t
{ {
using _traits = make_traits<no_value_t, tag::is_limit>; using _traits = make_traits<no_value_t, tag::is_limit>;
using _recursive_traits = make_recursive_traits<Limit>; using _nodes = detail::type_vector<Limit>;
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
// Data // Data
using _data_t = limit_data_t<Limit>; using _data_t = limit_data_t<Limit>;
@ -69,9 +67,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = limit_data_t<Limit>; using _data_t = limit_data_t<Limit>;
@ -84,12 +82,8 @@ namespace sqlpp
{ {
return t.limit; return t.limit;
} }
};
template<typename Policies> using _consistency_check = consistent_t;
struct _methods_t
{
static void _check_consistency() {}
}; };
}; };
@ -124,7 +118,7 @@ namespace sqlpp
struct dynamic_limit_t struct dynamic_limit_t
{ {
using _traits = make_traits<no_value_t, tag::is_limit>; using _traits = make_traits<no_value_t, tag::is_limit>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = dynamic_limit_data_t<Database>; using _data_t = dynamic_limit_data_t<Database>;
@ -138,6 +132,7 @@ namespace sqlpp
{ {
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL // FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
using arg_t = wrap_operand_t<Limit>; using arg_t = wrap_operand_t<Limit>;
static_assert(is_integral_t<arg_t>::value, "limit requires an integral value or integral parameter");
_data._value = arg_t{value}; _data._value = arg_t{value};
_data._initialized = true; _data._initialized = true;
} }
@ -145,9 +140,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = dynamic_limit_data_t<Database>; using _data_t = dynamic_limit_data_t<Database>;
@ -160,20 +155,15 @@ namespace sqlpp
{ {
return t.limit; return t.limit;
} }
};
// Additional methods for the statement using _consistency_check = consistent_t;
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
}; };
}; };
struct no_limit_t struct no_limit_t
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = no_data_t; using _data_t = no_data_t;
@ -185,9 +175,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = no_data_t; using _data_t = no_data_t;
@ -200,30 +190,43 @@ namespace sqlpp
{ {
return t.no_limit; return t.no_limit;
} }
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = new_statement<Policies, no_limit_t, T>;
static void _check_consistency() {} template<typename T>
using _check = is_integral_t<wrap_operand_t<T>>;
template<typename Check, typename T>
using _new_statement_t = new_statement_t<Check::value, Policies, no_limit_t, T>;
using _consistency_check = consistent_t;
template<typename Arg> template<typename Arg>
auto limit(Arg arg) const auto limit(Arg arg) const
-> _new_statement_t<limit_t<wrap_operand_t<Arg>>> -> _new_statement_t<_check<Arg>, limit_t<wrap_operand_t<Arg>>>
{ {
return { static_cast<const derived_statement_t<Policies>&>(*this), limit_data_t<wrap_operand_t<Arg>>{{arg}} }; static_assert(_check<Arg>::value, "limit requires an integral value or integral parameter");
return _limit_impl(_check<Arg>{}, wrap_operand_t<Arg>{arg});
} }
auto dynamic_limit() const auto dynamic_limit() const
-> _new_statement_t<dynamic_limit_t<_database_t>> -> _new_statement_t<std::true_type, 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<const derived_statement_t<Policies>&>(*this), dynamic_limit_data_t<_database_t>{} }; return { static_cast<const derived_statement_t<Policies>&>(*this), dynamic_limit_data_t<_database_t>{} };
} }
private:
template<typename Arg>
auto _limit_impl(const std::false_type&, Arg arg) const
-> bad_statement;
template<typename Arg>
auto _limit_impl(const std::true_type&, Arg arg) const
-> _new_statement_t<std::true_type, limit_t<Arg>>
{
return { static_cast<const derived_statement_t<Policies>&>(*this), limit_data_t<Arg>{arg} };
}
}; };
}; };
@ -231,6 +234,7 @@ namespace sqlpp
template<typename Context, typename Database> template<typename Context, typename Database>
struct serializer_t<Context, dynamic_limit_data_t<Database>> struct serializer_t<Context, dynamic_limit_data_t<Database>>
{ {
using _serialize_check = consistent_t;
using T = dynamic_limit_data_t<Database>; using T = dynamic_limit_data_t<Database>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -247,12 +251,13 @@ namespace sqlpp
template<typename Context, typename Limit> template<typename Context, typename Limit>
struct serializer_t<Context, limit_data_t<Limit>> struct serializer_t<Context, limit_data_t<Limit>>
{ {
using _serialize_check = serialize_check_of<Context, Limit>;
using T = limit_data_t<Limit>; using T = limit_data_t<Limit>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << " LIMIT "; context << " LIMIT ";
serialize(t._value, context); serialize_operand(t._value, context);
return context; return context;
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -32,7 +32,7 @@
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace logic
{ {
template<bool... B> template<bool... B>
struct logic_helper; struct logic_helper;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,6 +28,7 @@
#define SQLPP_MAX_H #define SQLPP_MAX_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp namespace sqlpp
{ {
@ -37,11 +38,12 @@ namespace sqlpp
public alias_operators<max_t<Expr>> public alias_operators<max_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>; using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr, aggregate_function>; using _nodes = detail::type_vector<Expr, aggregate_function>;
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "MAX"; } static constexpr const char _literal[] = "max_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -67,6 +69,7 @@ namespace sqlpp
template<typename Context, typename Expr> template<typename Context, typename Expr>
struct serializer_t<Context, max_t<Expr>> struct serializer_t<Context, max_t<Expr>>
{ {
using _serialize_check = serialize_check_of<Context, Expr>;
using T = max_t<Expr>; using T = max_t<Expr>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -81,6 +84,7 @@ namespace sqlpp
template<typename T> template<typename T>
auto max(T t) -> max_t<wrap_operand_t<T>> auto max(T t) -> max_t<wrap_operand_t<T>>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "max() cannot be used on an aggregate function");
static_assert(is_expression_t<wrap_operand_t<T>>::value, "max() requires an expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "max() requires an expression as argument");
return { t }; return { t };
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,6 +28,7 @@
#define SQLPP_MIN_H #define SQLPP_MIN_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp namespace sqlpp
{ {
@ -37,11 +38,12 @@ namespace sqlpp
public alias_operators<min_t<Expr>> public alias_operators<min_t<Expr>>
{ {
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>; using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Expr, aggregate_function>; using _nodes = detail::type_vector<Expr, aggregate_function>;
struct _name_t struct _alias_t
{ {
static constexpr const char* _get_name() { return "MIN"; } static constexpr const char _literal[] = "min_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T> template<typename T>
struct _member_t struct _member_t
{ {
@ -67,6 +69,7 @@ namespace sqlpp
template<typename Context, typename Expr> template<typename Context, typename Expr>
struct serializer_t<Context, min_t<Expr>> struct serializer_t<Context, min_t<Expr>>
{ {
using _serialize_check = serialize_check_of<Context, Expr>;
using T = min_t<Expr>; using T = min_t<Expr>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
@ -81,6 +84,7 @@ namespace sqlpp
template<typename T> template<typename T>
auto min(T t) -> min_t<wrap_operand_t<T>> auto min(T t) -> min_t<wrap_operand_t<T>>
{ {
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "min() cannot be used on an aggregate function");
static_assert(is_expression_t<wrap_operand_t<T>>::value, "min() requires an expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "min() requires an expression as argument");
return { t }; return { t };
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,7 +28,7 @@
#define SQLPP_MULTI_COLUMN_H #define SQLPP_MULTI_COLUMN_H
#include <sqlpp11/no_value.h> #include <sqlpp11/no_value.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
#include <sqlpp11/detail/copy_tuple_args.h> #include <sqlpp11/detail/copy_tuple_args.h>
@ -42,9 +42,9 @@ namespace sqlpp
struct multi_column_t struct multi_column_t
{ {
using _traits = make_traits<no_value_t>; using _traits = make_traits<no_value_t>;
using _recursive_traits = make_recursive_traits<Columns...>; using _nodes = detail::type_vector<Columns...>;
static_assert(detail::all_t<is_selectable_t<Columns>::value...>::value, "multi_column parameters need to be named expressions"); static_assert(logic::all_t<is_selectable_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
multi_column_t(std::tuple<Columns...> columns): multi_column_t(std::tuple<Columns...> columns):
_columns(columns) _columns(columns)
@ -73,11 +73,11 @@ namespace sqlpp
struct multi_column_alias_t struct multi_column_alias_t
{ {
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_multi_column, tag::is_selectable>; using _traits = make_traits<no_value_t, tag::is_alias, tag::is_multi_column, tag::is_selectable>;
using _recursive_traits = make_recursive_traits<Columns...>; using _nodes = detail::type_vector<Columns...>;
static_assert(detail::all_t<is_selectable_t<Columns>::value...>::value, "multi_column parameters need to be named expressions"); static_assert(logic::all_t<is_selectable_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
using _name_t = typename AliasProvider::_name_t; using _alias_t = typename AliasProvider::_alias_t;
multi_column_alias_t(multi_column_t<void, Columns...> multi_column): multi_column_alias_t(multi_column_t<void, Columns...> multi_column):
_columns(multi_column._columns) _columns(multi_column._columns)
@ -103,6 +103,7 @@ namespace sqlpp
template<typename Context, typename... Columns> template<typename Context, typename... Columns>
struct serializer_t<Context, multi_column_t<void, Columns...>> struct serializer_t<Context, multi_column_t<void, Columns...>>
{ {
using _serialize_check = serialize_check_of<Context, Columns...>;
using T = multi_column_t<void, Columns...>; using T = multi_column_t<void, Columns...>;
static void _(const T& t, Context& context) static void _(const T& t, Context& context)
@ -114,6 +115,7 @@ namespace sqlpp
template<typename Context, typename AliasProvider, typename... Columns> template<typename Context, typename AliasProvider, typename... Columns>
struct serializer_t<Context, multi_column_alias_t<AliasProvider, Columns...>> struct serializer_t<Context, multi_column_alias_t<AliasProvider, Columns...>>
{ {
using _serialize_check = serialize_check_of<Context, Columns...>;
using T = multi_column_alias_t<AliasProvider, Columns...>; using T = multi_column_alias_t<AliasProvider, Columns...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -30,6 +30,7 @@
#include <memory> #include <memory>
#include <sqlpp11/serializer_context.h> #include <sqlpp11/serializer_context.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/char_sequence.h>
namespace sqlpp namespace sqlpp
{ {
@ -41,6 +42,7 @@ namespace sqlpp
template<typename T> template<typename T>
named_interpretable_t(T t): named_interpretable_t(T t):
_requires_braces(requires_braces_t<T>::value),
_impl(std::make_shared<_impl_t<T>>(t)) _impl(std::make_shared<_impl_t<T>>(t))
{} {}
@ -74,6 +76,8 @@ namespace sqlpp
return _impl->_get_name(); return _impl->_get_name();
} }
bool _requires_braces;
private: private:
struct _impl_base struct _impl_base
{ {
@ -111,7 +115,7 @@ namespace sqlpp
std::string _get_name() const std::string _get_name() const
{ {
return T::_name_t::_get_name(); return name_of<T>::char_ptr();
} }
T _t; T _t;
@ -123,11 +127,20 @@ namespace sqlpp
template<typename Context, typename Database> template<typename Context, typename Database>
struct serializer_t<Context, named_interpretable_t<Database>> struct serializer_t<Context, named_interpretable_t<Database>>
{ {
using _serialize_check = consistent_t;
using T = named_interpretable_t<Database>; using T = named_interpretable_t<Database>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
if (t._requires_braces)
{
context << '(';
t.serialize(context); t.serialize(context);
context << ')';
}
else
t.serialize(context);
return context; return context;
} }
}; };

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -37,6 +37,7 @@ namespace sqlpp
template<typename Context> template<typename Context>
struct serializer_t<Context, no_data_t> struct serializer_t<Context, no_data_t>
{ {
using _serialize_check = consistent_t;
using T = no_data_t; using T = no_data_t;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -30,24 +30,61 @@
#include <type_traits> #include <type_traits>
#include <sqlpp11/no_value.h> #include <sqlpp11/no_value.h>
#include <sqlpp11/serializer.h> #include <sqlpp11/serializer.h>
#include <sqlpp11/prepared_execute.h>
namespace sqlpp namespace sqlpp
{ {
struct noop struct noop
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
struct _name_t {}; struct _alias_t {};
template<typename Policies> template<typename Statement>
struct _result_methods_t struct _result_methods_t
{}; {
using _statement_t = Statement;
const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
// Execute
template<typename Db, typename Composite>
auto _run(Db& db, const Composite& composite) const -> void
{
return db.execute(composite);
}
template<typename Db>
auto _run(Db& db) const -> void
{
return db.execute(_get_statement());
}
// Prepare
template<typename Db, typename Composite>
auto _prepare(Db& db, const Composite& composite) const
-> prepared_execute_t<Db, Composite>
{
return {{}, db.prepare_execute(composite)};
}
template<typename Db>
auto _prepare(Db& db) const
-> prepared_execute_t<Db, _statement_t>
{
return {{}, db.prepare_execute(_get_statement())};
}
};
}; };
template<typename Context> template<typename Context>
struct serializer_t<Context, noop> struct serializer_t<Context, noop>
{ {
using _serialize_check = consistent_t;
using T = noop; using T = noop;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,

95
include/sqlpp11/not_in.h Normal file
View File

@ -0,0 +1,95 @@
/*
* Copyright (c) 2013-2015, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_NOT_IN_H
#define SQLPP_NOT_IN_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/char_sequence.h>
#include <sqlpp11/boolean.h>
#include <sqlpp11/in_fwd.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
template<typename Operand, typename... Args>
struct not_in_t:
public expression_operators<not_in_t<Operand, Args...>, boolean>,
public alias_operators<not_in_t<Operand, Args...>>
{
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
using _nodes = detail::type_vector<Operand, Args...>;
static_assert(sizeof...(Args) > 0, "not_in() requires at least one argument");
struct _alias_t
{
static constexpr const char _literal[] = "not_in_";
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
template<typename T>
struct _member_t
{
T not_in;
};
};
not_in_t(Operand operand, Args... args):
_operand(operand),
_args(args...)
{}
not_in_t(const not_in_t&) = default;
not_in_t(not_in_t&&) = default;
not_in_t& operator=(const not_in_t&) = default;
not_in_t& operator=(not_in_t&&) = default;
~not_in_t() = default;
Operand _operand;
std::tuple<Args...> _args;
};
template<typename Context, typename Operand, typename... Args>
struct serializer_t<Context, not_in_t<Operand, Args...>>
{
using _serialize_check = serialize_check_of<Context, Args...>;
using T = not_in_t<Operand, Args...>;
static Context& _(const T& t, Context& context)
{
serialize_operand(t._operand, context);
context << " NOT IN(";
if (sizeof...(Args) == 1)
serialize(std::get<0>(t._args), context);
else
interpret_tuple(t._args, ',', context);
context << ')';
return context;
}
};
}
#endif

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -34,12 +34,13 @@ namespace sqlpp
struct null_t struct null_t
{ {
using _traits = make_traits<no_value_t, tag::is_expression, tag::is_sql_null>; using _traits = make_traits<no_value_t, tag::is_expression, tag::is_sql_null>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
}; };
template<typename Context> template<typename Context>
struct serializer_t<Context, null_t> struct serializer_t<Context, null_t>
{ {
using _serialize_check = consistent_t;
using Operand = null_t; using Operand = null_t;
static Context& _(const Operand& t, Context& context) static Context& _(const Operand& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -55,7 +55,7 @@ namespace sqlpp
struct offset_t struct offset_t
{ {
using _traits = make_traits<no_value_t, tag::is_offset>; using _traits = make_traits<no_value_t, tag::is_offset>;
using _recursive_traits = make_recursive_traits<Offset>; using _nodes = detail::type_vector<Offset>;
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter"); static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
@ -69,9 +69,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = offset_data_t<Offset>; using _data_t = offset_data_t<Offset>;
@ -84,12 +84,8 @@ namespace sqlpp
{ {
return t.offset; return t.offset;
} }
};
template<typename Policies> using _consistency_check = consistent_t;
struct _methods_t
{
static void _check_consistency() {}
}; };
}; };
@ -124,7 +120,7 @@ namespace sqlpp
struct dynamic_offset_t struct dynamic_offset_t
{ {
using _traits = make_traits<no_value_t, tag::is_offset>; using _traits = make_traits<no_value_t, tag::is_offset>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = dynamic_offset_data_t<Database>; using _data_t = dynamic_offset_data_t<Database>;
@ -138,6 +134,7 @@ namespace sqlpp
{ {
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL // FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = wrap_operand_t<Offset>; using arg_t = wrap_operand_t<Offset>;
static_assert(is_integral_t<arg_t>::value, "offset requires an integral value or integral parameter");
_data._value = arg_t{value}; _data._value = arg_t{value};
_data._initialized = true; _data._initialized = true;
} }
@ -145,9 +142,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = dynamic_offset_data_t<Database>; using _data_t = dynamic_offset_data_t<Database>;
@ -160,12 +157,8 @@ namespace sqlpp
{ {
return t.offset; return t.offset;
} }
};
template<typename Policies> using _consistency_check = consistent_t;
struct _methods_t
{
static void _check_consistency() {}
template<typename Offset> template<typename Offset>
void set_offset(Offset value) void set_offset(Offset value)
@ -184,7 +177,7 @@ namespace sqlpp
struct no_offset_t struct no_offset_t
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = no_data_t; using _data_t = no_data_t;
@ -196,9 +189,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = no_data_t; using _data_t = no_data_t;
@ -211,30 +204,44 @@ namespace sqlpp
{ {
return t.no_offset; return t.no_offset;
} }
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = new_statement<Policies, no_offset_t, T>;
static void _check_consistency() {} template<typename T>
using _check = is_integral_t<wrap_operand_t<T>>;
template<typename Check, typename T>
using _new_statement_t = new_statement_t<Check::value, Policies, no_offset_t, T>;
using _consistency_check = consistent_t;
template<typename Arg> template<typename Arg>
auto offset(Arg arg) const auto offset(Arg arg) const
-> _new_statement_t<offset_t<wrap_operand_t<Arg>>> -> _new_statement_t<_check<Arg>, offset_t<wrap_operand_t<Arg>>>
{ {
return { static_cast<const derived_statement_t<Policies>&>(*this), offset_data_t<wrap_operand_t<Arg>>{{arg}} }; static_assert(_check<Arg>::value, "offset requires an integral value or integral parameter");
return _offset_impl(_check<Arg>{}, wrap_operand_t<Arg>{arg});
} }
auto dynamic_offset() const auto dynamic_offset() const
-> _new_statement_t<dynamic_offset_t<_database_t>> -> _new_statement_t<std::true_type, dynamic_offset_t<_database_t>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement");
return { static_cast<const derived_statement_t<Policies>&>(*this), dynamic_offset_data_t<_database_t>{} }; return { static_cast<const derived_statement_t<Policies>&>(*this), dynamic_offset_data_t<_database_t>{} };
} }
private:
template<typename Arg>
auto _offset_impl(const std::false_type&, Arg arg) const
-> bad_statement;
template<typename Arg>
auto _offset_impl(const std::true_type&, Arg arg) const
-> _new_statement_t<std::true_type, offset_t<Arg>>
{
return { static_cast<const derived_statement_t<Policies>&>(*this), offset_data_t<Arg>{arg} };
}
}; };
}; };
@ -242,12 +249,13 @@ namespace sqlpp
template<typename Context, typename Offset> template<typename Context, typename Offset>
struct serializer_t<Context, offset_data_t<Offset>> struct serializer_t<Context, offset_data_t<Offset>>
{ {
using _serialize_check = serialize_check_of<Context, Offset>;
using T = offset_data_t<Offset>; using T = offset_data_t<Offset>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << " OFFSET "; context << " OFFSET ";
serialize(t._value, context); serialize_operand(t._value, context);
return context; return context;
} }
}; };
@ -255,6 +263,7 @@ namespace sqlpp
template<typename Context, typename Database> template<typename Context, typename Database>
struct serializer_t<Context, dynamic_offset_data_t<Database>> struct serializer_t<Context, dynamic_offset_data_t<Database>>
{ {
using _serialize_check = consistent_t;
using T = dynamic_offset_data_t<Database>; using T = dynamic_offset_data_t<Database>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -30,43 +30,61 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h> #include <sqlpp11/interpretable_list.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Database, typename... Expr> template<typename Database, typename... Expressions>
struct on_t struct on_t
{ {
using _traits = make_traits<no_value_t, tag::is_on>; using _traits = make_traits<no_value_t, tag::is_on>;
using _recursive_traits = make_recursive_traits<Expr...>; using _nodes = detail::type_vector<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()"); static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in on()");
template<typename E> template<typename Expr>
void add(E expr) void add(Expr expr)
{ {
static_assert(is_expression_t<E>::value, "invalid expression argument in add_on()"); static_assert(_is_dynamic::value, "on::add() must not be called for static on()");
_dynamic_expressions.emplace_back(expr); static_assert(is_expression_t<Expr>::value, "invalid expression argument in on::add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expr>;
_serialize_check::_();
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expr>::value, _serialize_check::type::value>;
_add_impl(expr, ok()); // dispatch to prevent compile messages after the static_assert
} }
std::tuple<Expr...> _expressions; private:
template<typename Expr>
void _add_impl(Expr expr, const std::true_type&)
{
return _dynamic_expressions.emplace_back(expr);
}
template<typename Expr>
void _add_impl(Expr expr, const std::false_type&);
public:
std::tuple<Expressions...> _expressions;
interpretable_list_t<Database> _dynamic_expressions; interpretable_list_t<Database> _dynamic_expressions;
}; };
template<typename Context, typename Database, typename... Expr> template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, on_t<Database, Expr...>> struct serializer_t<Context, on_t<Database, Expressions...>>
{ {
using T = on_t<Database, Expr...>; using _serialize_check = serialize_check_of<Context, Expressions...>;
using T = on_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty()) if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context; return context;
context << " ON "; context << " ON ";
interpret_tuple(t._expressions, " AND ", context); interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty()) if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << " AND "; context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context); interpret_list(t._dynamic_expressions, " AND ", context);
return context; return context;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -32,7 +32,7 @@
#include <sqlpp11/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable.h> #include <sqlpp11/interpretable.h>
#include <sqlpp11/policy_update.h> #include <sqlpp11/policy_update.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/logic.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
@ -55,21 +55,26 @@ namespace sqlpp
interpretable_list_t<Database> _dynamic_expressions; interpretable_list_t<Database> _dynamic_expressions;
}; };
struct assert_no_unknown_tables_in_order_by_t
{
using type = std::false_type;
template<typename T = void>
static void _()
{
static_assert(wrong_t<T>::value, "at least one order-by expression requires a table which is otherwise not known in the statement");
}
};
// ORDER BY // ORDER BY
template<typename Database, typename... Expressions> template<typename Database, typename... Expressions>
struct order_by_t struct order_by_t
{ {
using _traits = make_traits<no_value_t, tag::is_order_by>; using _traits = make_traits<no_value_t, tag::is_order_by>;
using _recursive_traits = make_recursive_traits<Expressions...>; using _nodes = detail::type_vector<Expressions...>;
using _is_dynamic = is_database<Database>; using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()");
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
static_assert(detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in order_by()");
// Data // Data
using _data_t = order_by_data_t<Database, Expressions...>; using _data_t = order_by_data_t<Database, Expressions...>;
@ -87,10 +92,12 @@ namespace sqlpp
void add(Expression expression) void add(Expression expression)
{ {
static_assert(_is_dynamic::value, "add() must not be called for static order_by"); static_assert(_is_dynamic::value, "add() must not be called for static order_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in order_by::add()"); static_assert(is_sort_order_t<Expression>::value, "invalid expression argument in order_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in order_by::add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in order_by::add()");
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
_serialize_check::_();
using ok = detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>; using ok = logic::all_t<_is_dynamic::value, is_sort_order_t<Expression>::value, _serialize_check::type::value>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
} }
@ -108,9 +115,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = order_by_data_t<Database, Expressions...>; using _data_t = order_by_data_t<Database, Expressions...>;
@ -123,12 +130,10 @@ namespace sqlpp
{ {
return t.order_by; return t.order_by;
} }
};
template<typename Policies> using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<order_by_t>::value,
struct _methods_t consistent_t,
{ assert_no_unknown_tables_in_order_by_t>::type;
static void _check_consistency() {}
}; };
}; };
@ -136,7 +141,7 @@ namespace sqlpp
struct no_order_by_t struct no_order_by_t
{ {
using _traits = make_traits<no_value_t, tag::is_noop>; using _traits = make_traits<no_value_t, tag::is_noop>;
using _recursive_traits = make_recursive_traits<>; using _nodes = detail::type_vector<>;
// Data // Data
using _data_t = no_data_t; using _data_t = no_data_t;
@ -148,9 +153,9 @@ namespace sqlpp
_data_t _data; _data_t _data;
}; };
// Member template for adding the named member to a statement // Base template to be inherited by the statement
template<typename Policies> template<typename Policies>
struct _member_t struct _base_t
{ {
using _data_t = no_data_t; using _data_t = no_data_t;
@ -163,30 +168,49 @@ namespace sqlpp
{ {
return t.no_order_by; return t.no_order_by;
} }
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t; using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = new_statement<Policies, no_order_by_t, T>;
static void _check_consistency() {} template<typename... T>
using _check = logic::all_t<is_sort_order_t<T>::value...>;
template<typename... Args> template<typename Check, typename T>
auto order_by(Args... args) const using _new_statement_t = new_statement_t<Check::value, Policies, no_order_by_t, T>;
-> _new_statement_t<order_by_t<void, Args...>>
using _consistency_check = consistent_t;
template<typename... Expressions>
auto order_by(Expressions... expressions) const
-> _new_statement_t<_check<Expressions...>, order_by_t<void, Expressions...>>
{ {
return { static_cast<const derived_statement_t<Policies>&>(*this), order_by_data_t<void, Args...>{args...} }; static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()");
static_assert(_check<Expressions...>::value, "at least one argument is not a sort order in order_by()");
return _order_by_impl<void>(_check<Expressions...>{}, expressions...);
} }
template<typename... Args> template<typename... Expressions>
auto dynamic_order_by(Args... args) const auto dynamic_order_by(Expressions... expressions) const
-> _new_statement_t<order_by_t<_database_t, Args...>> -> _new_statement_t<_check<Expressions...>, order_by_t<_database_t, Expressions...>>
{ {
static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement");
return { static_cast<const derived_statement_t<Policies>&>(*this), order_by_data_t<_database_t, Args...>{args...} }; static_assert(_check<Expressions...>::value, "at least one argument is not a sort order in order_by()");
return _order_by_impl<_database_t>(_check<Expressions...>{}, expressions...);
}
private:
template<typename Database, typename... Expressions>
auto _order_by_impl(const std::false_type&, Expressions... expressions) const
-> bad_statement;
template<typename Database, typename... Expressions>
auto _order_by_impl(const std::true_type&, Expressions... expressions) const
-> _new_statement_t<std::true_type, order_by_t<_database_t, Expressions...>>
{
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
return { static_cast<const derived_statement_t<Policies>&>(*this), order_by_data_t<Database, Expressions...>{expressions...} };
} }
}; };
}; };
@ -195,6 +219,7 @@ namespace sqlpp
template<typename Context, typename Database, typename... Expressions> template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, order_by_data_t<Database, Expressions...>> struct serializer_t<Context, order_by_data_t<Database, Expressions...>>
{ {
using _serialize_check = serialize_check_of<Context, Expressions...>;
using T = order_by_data_t<Database, Expressions...>; using T = order_by_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -38,15 +38,10 @@ namespace sqlpp
public expression_operators<parameter_t<ValueType, NameType>, ValueType> public expression_operators<parameter_t<ValueType, NameType>, ValueType>
{ {
using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>; using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>;
struct _recursive_traits
{ using _nodes = detail::type_vector<>;
using _parameters = std::tuple<parameter_t>; using _parameters = detail::type_vector<parameter_t>;
using _provided_tables = detail::type_set<>; using _can_be_null = std::true_type;
using _provided_outer_tables = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
using _tags = detail::type_set<tag::can_be_null>;
};
using _instance_t = member_t<NameType, parameter_value_t<ValueType>>; using _instance_t = member_t<NameType, parameter_value_t<ValueType>>;
@ -63,6 +58,7 @@ namespace sqlpp
template<typename Context, typename ValueType, typename NameType> template<typename Context, typename ValueType, typename NameType>
struct serializer_t<Context, parameter_t<ValueType, NameType>> struct serializer_t<Context, parameter_t<ValueType, NameType>>
{ {
using _serialize_check = consistent_t;
using T = parameter_t<ValueType, NameType>; using T = parameter_t<ValueType, NameType>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -37,11 +37,11 @@ namespace sqlpp
template<typename T> template<typename T>
struct parameter_list_t struct parameter_list_t
{ {
static_assert(wrong_t<parameter_list_t>::value, "Template parameter for parameter_list_t has to be a tuple"); static_assert(wrong_t<parameter_list_t>::value, "Template parameter for parameter_list_t has to be a type_vector");
}; };
template<typename... Parameter> template<typename... Parameter>
struct parameter_list_t<std::tuple<Parameter...>>: public Parameter::_instance_t... struct parameter_list_t<detail::type_vector<Parameter...>>: public Parameter::_instance_t...
{ {
using _member_tuple_t = std::tuple<typename Parameter::_instance_t...>; using _member_tuple_t = std::tuple<typename Parameter::_instance_t...>;
using size = std::integral_constant<std::size_t, sizeof...(Parameter)>; using size = std::integral_constant<std::size_t, sizeof...(Parameter)>;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2014, Roland Bock * Copyright (c) 2013-2015, Roland Bock
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modification, * Redistribution and use in source and binary forms, with or without modification,
@ -28,6 +28,7 @@
#define SQLPP_POLICY_UPDATE_H #define SQLPP_POLICY_UPDATE_H
#include <sqlpp11/wrong.h> #include <sqlpp11/wrong.h>
#include <sqlpp11/bad_statement.h>
namespace sqlpp namespace sqlpp
{ {
@ -53,6 +54,21 @@ namespace sqlpp
template<typename Policies, typename Needle, typename Replacement> template<typename Policies, typename Needle, typename Replacement>
using new_statement = typename Policies::template _new_statement_t<Needle, Replacement>; using new_statement = typename Policies::template _new_statement_t<Needle, Replacement>;
template<bool, typename Policies, typename Needle, typename Replacement>
struct new_statement_impl
{
using type = typename Policies::template _new_statement_t<Needle, Replacement>;
};
template<typename Policies, typename Needle, typename Replacement>
struct new_statement_impl<false, Policies, Needle, Replacement>
{
using type = bad_statement;
};
template<bool Check, typename Policies, typename Needle, typename Replacement>
using new_statement_t = typename new_statement_impl<Check, Policies, Needle, Replacement>::type;
} }
#endif #endif

206
include/sqlpp11/ppgen.h Normal file
View File

@ -0,0 +1,206 @@
/*
* Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com)
* 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__ppgen_h
#define _sqlpp__ppgen_h
#include <boost/preprocessor/config/config.hpp>
// enable the Clang support
#if defined(__clang__) && !BOOST_PP_VARIADICS
# undef BOOST_PP_VARIADICS
# define BOOST_PP_VARIADICS 1
#endif // defined(__clang__)
// tools
#include <sqlpp11/ppgen/tools/wrap_seq.h>
#include <sqlpp11/ppgen/tools/tuple_pop_front.h>
// table props
#include <sqlpp11/ppgen/tblops/engine.h>
#include <sqlpp11/ppgen/tblops/character_set.h>
// col props
#include <sqlpp11/ppgen/colops/auto_increment.h>
#include <sqlpp11/ppgen/colops/blob.h>
#include <sqlpp11/ppgen/colops/bool.h>
#include <sqlpp11/ppgen/colops/comment.h>
#include <sqlpp11/ppgen/colops/datetime.h>
#include <sqlpp11/ppgen/colops/default.h>
#include <sqlpp11/ppgen/colops/floating_point.h>
#include <sqlpp11/ppgen/colops/index.h>
#include <sqlpp11/ppgen/colops/integer.h>
#include <sqlpp11/ppgen/colops/not_null.h>
#include <sqlpp11/ppgen/colops/null.h>
#include <sqlpp11/ppgen/colops/primary_key.h>
#include <sqlpp11/ppgen/colops/text.h>
#include <sqlpp11/ppgen/colops/timestamp.h>
#include <sqlpp11/ppgen/colops/unique.h>
#include <sqlpp11/ppgen/colops/varchar.h>
// boost.preprocessor
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/facilities/expand.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/comparison/less.hpp>
#include <boost/preprocessor/arithmetic/add.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/for_each_i.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/tuple/elem.hpp>
#include <boost/preprocessor/tuple/size.hpp>
#include <boost/preprocessor/tuple/to_seq.hpp>
/***************************************************************************/
// tools
#define SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \
BOOST_PP_TUPLE_ELEM(0, BOOST_PP_EXPAND table)
#define SQLPP_DECLARE_TABLE_GET_TABLE_PROPS(table) \
SQLPP_BOOST_PP_TUPLE_POP_FRONT(BOOST_PP_EXPAND table)
#define SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(col) \
BOOST_PP_TUPLE_ELEM(0, col)
#define SQLPP_DECLARE_TABLE_ENUM_COLUMNS(unused, table, elem) \
,table::SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem)
/***************************************************************************/
// columns
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_AUX(unused, size, idx, elem) \
BOOST_PP_CAT( \
SQLPP_DECLARE_COLUMN_GEN_TRAITS_ \
,BOOST_PP_CAT(SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_, elem) \
)(elem) \
BOOST_PP_COMMA_IF(BOOST_PP_LESS(BOOST_PP_ADD(idx, 1), size))
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS(props) \
BOOST_PP_SEQ_FOR_EACH_I( \
SQLPP_DECLARE_COLUMN_GEN_TRAITS_AUX \
,BOOST_PP_TUPLE_SIZE(props) \
,BOOST_PP_TUPLE_TO_SEQ(props) \
)
#define SQLPP_DECLARE_COLUMN(unused, data, elem) \
struct SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem) { \
struct _alias_t { \
static constexpr const char _literal[] = \
BOOST_PP_STRINGIZE(SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem)); \
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>; \
\
template<typename T> \
struct _member_t { \
T SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); \
\
T& operator()() { return SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); } \
const T& operator()() const { return SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); } \
}; /* struct _member_t */ \
}; /* struct _alias_t */ \
\
using _traits = sqlpp::make_traits< \
SQLPP_DECLARE_COLUMN_GEN_TRAITS(SQLPP_BOOST_PP_TUPLE_POP_FRONT(elem)) \
>; \
\
}; /* struct SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem) */
/***************************************************************************/
// table props
#define SQLPP_DECLARE_TABLE_GEN_PROPS_AUX(unused1, unused2, elem) \
BOOST_PP_CAT( \
SQLPP_DECLARE_TABLE_GEN_ \
,BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_PROC_LAZY_, elem) \
)(elem)
#define SQLPP_DECLARE_TABLE_GEN_PROPS(table) \
BOOST_PP_SEQ_FOR_EACH( \
SQLPP_DECLARE_TABLE_GEN_PROPS_AUX \
,~ \
,BOOST_PP_TUPLE_TO_SEQ(SQLPP_BOOST_PP_TUPLE_POP_FRONT(table)) \
)
/***************************************************************************/
// main
#define SQLPP_DECLARE_TABLE_IMPL(table, cols) \
namespace SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) { \
namespace BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) { \
BOOST_PP_SEQ_FOR_EACH( \
SQLPP_DECLARE_COLUMN \
,~ \
,cols \
) \
} /* namespace BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) */ \
\
struct SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \
: sqlpp::table_t< \
SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \
BOOST_PP_SEQ_FOR_EACH( \
SQLPP_DECLARE_TABLE_ENUM_COLUMNS \
,BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) \
,cols \
) \
> \
{ \
BOOST_PP_IF( \
BOOST_PP_LESS(BOOST_PP_TUPLE_SIZE(table), 2) \
,BOOST_PP_TUPLE_EAT() \
,SQLPP_DECLARE_TABLE_GEN_PROPS \
)(BOOST_PP_EXPAND table) \
\
struct _alias_t { \
static constexpr const char _literal[] = \
BOOST_PP_STRINGIZE(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table)); \
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>; \
\
template<typename T> \
struct _member_t { \
T SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); \
\
T& operator()() { return SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); } \
const T& operator()() const { return SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); } \
\
}; /* struct _member_t */ \
\
}; /* struct _alias_t */ \
\
}; /* struct SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) */ \
\
}
/***************************************************************************/
#define SQLPP_DECLARE_TABLE(table, cols) \
SQLPP_DECLARE_TABLE_IMPL( \
BOOST_PP_CAT(SQLPP_WRAP_SEQUENCE_X table, 0) \
,BOOST_PP_CAT(SQLPP_WRAP_SEQUENCE_X cols, 0) \
)
/***************************************************************************/
#endif // _sqlpp__ppgen_h

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com)
* 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__ppgen__colops__auto_increment_h
#define _sqlpp__ppgen__colops__auto_increment_h
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_AUTO_INCREMENT \
PROC_SQLPP_AUTO_INCREMENT
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_AUTO_INCREMENT(...) \
sqlpp::tag::must_not_update
#endif // _sqlpp__ppgen__colops__auto_increment_h

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com)
* 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__ppgen__colops__blob_h
#define _sqlpp__ppgen__colops__blob_h
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_tinyblob \
PROC_tinyblob
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_tinyblob(...) \
sqlpp::blob
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_blob \
PROC_blob
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_blob(...) \
sqlpp::blob
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_mediumblob \
PROC_mediumblob
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_mediumblob(...) \
sqlpp::blob
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_longblob \
PROC_longblob
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_longblob(...) \
sqlpp::blob
#endif // _sqlpp__ppgen__colops__blob_h

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com)
* 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__ppgen__colops__bool_h
#define _sqlpp__ppgen__colops__bool_h
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_bool \
PROC_bool
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_bool(...) \
sqlpp::boolean
#endif // _sqlpp__ppgen__colops__bool_h

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com)
* 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__ppgen__colops__comment_h
#define _sqlpp__ppgen__colops__comment_h
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_SQLPP_COMMENT(str) \
PROC_SQLPP_COMMENT
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_SQLPP_COMMENT(str) \
[COMMENT is not implemented]
#endif // _sqlpp__ppgen__colops__comment_h

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2014-2015, niXman (i dot nixman dog gmail dot com)
* 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__ppgen__colops__datetime_h
#define _sqlpp__ppgen__colops__datetime_h
#define SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_datetime \
PROC_datetime
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_PROC_datetime(...) \
[datetime is not implemented]
#endif // _sqlpp__ppgen__colops__datetime_h

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