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

Merge branch 'feature/vendor_neutrality' into develop

This commit is contained in:
rbock 2014-01-19 19:53:17 +01:00
commit 83afe20923
91 changed files with 3640 additions and 2784 deletions

View File

@ -30,75 +30,39 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
namespace sqlpp namespace sqlpp
{ {
namespace alias
{
#define SQLPP_ALIAS_PROVIDER_GENERATOR(name) \
struct name##_t\
{\
struct _name_t\
{\
static constexpr const char* _get_name() { return #name; }\
template<typename T>\
struct _member_t\
{\
T name;\
T& operator()() { return name; }\
const T& operator()() const { return name; }\
};\
};\
};\
constexpr name##_t name = {};
SQLPP_ALIAS_PROVIDER_GENERATOR(a);
SQLPP_ALIAS_PROVIDER_GENERATOR(b);
SQLPP_ALIAS_PROVIDER_GENERATOR(c);
SQLPP_ALIAS_PROVIDER_GENERATOR(d);
SQLPP_ALIAS_PROVIDER_GENERATOR(e);
SQLPP_ALIAS_PROVIDER_GENERATOR(f);
SQLPP_ALIAS_PROVIDER_GENERATOR(g);
SQLPP_ALIAS_PROVIDER_GENERATOR(h);
SQLPP_ALIAS_PROVIDER_GENERATOR(i);
SQLPP_ALIAS_PROVIDER_GENERATOR(j);
SQLPP_ALIAS_PROVIDER_GENERATOR(k);
SQLPP_ALIAS_PROVIDER_GENERATOR(l);
SQLPP_ALIAS_PROVIDER_GENERATOR(m);
SQLPP_ALIAS_PROVIDER_GENERATOR(n);
SQLPP_ALIAS_PROVIDER_GENERATOR(o);
SQLPP_ALIAS_PROVIDER_GENERATOR(p);
SQLPP_ALIAS_PROVIDER_GENERATOR(q);
SQLPP_ALIAS_PROVIDER_GENERATOR(s);
SQLPP_ALIAS_PROVIDER_GENERATOR(t);
SQLPP_ALIAS_PROVIDER_GENERATOR(u);
SQLPP_ALIAS_PROVIDER_GENERATOR(v);
SQLPP_ALIAS_PROVIDER_GENERATOR(w);
SQLPP_ALIAS_PROVIDER_GENERATOR(x);
SQLPP_ALIAS_PROVIDER_GENERATOR(y);
SQLPP_ALIAS_PROVIDER_GENERATOR(z);
SQLPP_ALIAS_PROVIDER_GENERATOR(left);
SQLPP_ALIAS_PROVIDER_GENERATOR(right);
};
template<typename Expression, typename AliasProvider> template<typename Expression, typename AliasProvider>
struct expression_alias_t struct expression_alias_t
{
struct _value_type: Expression::_value_type
{ {
using _is_expression = std::false_type; struct _value_type: Expression::_value_type
using _is_named_expression = std::true_type; {
using _is_alias = std::true_type; using _is_expression = std::false_type;
using _is_named_expression = std::true_type;
using _is_alias = std::true_type;
};
using _name_t = typename AliasProvider::_name_t;
Expression _expression;
}; };
using _name_t = typename AliasProvider::_name_t; namespace vendor
{
template<typename Db> template<typename Context, typename Expression, typename AliasProvider>
void serialize(std::ostream& os, Db& db) const struct interpreter_t<Context, expression_alias_t<Expression, AliasProvider>>
{ {
os << "("; _expression.serialize(os, db); os << ") AS " << _name_t::_get_name(); using T = expression_alias_t<Expression, AliasProvider>;
}
Expression _expression; static Context& _(const T& t, Context& context)
}; {
context << '(';
interpret(t._expression, context);
context << ") AS ";
context << T::_name_t::_get_name();
return context;
}
};
}
} }
#endif #endif

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_ALIAS_PROVIDER_H
#define SQLPP_ALIAS_PROVIDER_H
#define SQLPP_ALIAS_PROVIDER(name) \
struct name##_t\
{\
struct _name_t\
{\
static constexpr const char* _get_name() { return #name; }\
template<typename T>\
struct _member_t\
{\
T name;\
T& operator()() { return name; }\
const T& operator()() const { return name; }\
};\
};\
};\
constexpr name##_t name = {};
namespace sqlpp
{
namespace alias
{
SQLPP_ALIAS_PROVIDER(a);
SQLPP_ALIAS_PROVIDER(b);
SQLPP_ALIAS_PROVIDER(c);
SQLPP_ALIAS_PROVIDER(d);
SQLPP_ALIAS_PROVIDER(e);
SQLPP_ALIAS_PROVIDER(f);
SQLPP_ALIAS_PROVIDER(g);
SQLPP_ALIAS_PROVIDER(h);
SQLPP_ALIAS_PROVIDER(i);
SQLPP_ALIAS_PROVIDER(j);
SQLPP_ALIAS_PROVIDER(k);
SQLPP_ALIAS_PROVIDER(l);
SQLPP_ALIAS_PROVIDER(m);
SQLPP_ALIAS_PROVIDER(n);
SQLPP_ALIAS_PROVIDER(o);
SQLPP_ALIAS_PROVIDER(p);
SQLPP_ALIAS_PROVIDER(q);
SQLPP_ALIAS_PROVIDER(s);
SQLPP_ALIAS_PROVIDER(t);
SQLPP_ALIAS_PROVIDER(u);
SQLPP_ALIAS_PROVIDER(v);
SQLPP_ALIAS_PROVIDER(w);
SQLPP_ALIAS_PROVIDER(x);
SQLPP_ALIAS_PROVIDER(y);
SQLPP_ALIAS_PROVIDER(z);
SQLPP_ALIAS_PROVIDER(left);
SQLPP_ALIAS_PROVIDER(right);
}
}
#endif

View File

@ -32,7 +32,7 @@
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Select> template<typename Select>
struct any_t: public boolean::template operators<any_t<Select>> struct any_t: public boolean::template operators<any_t<Select>>
@ -71,26 +71,33 @@ namespace sqlpp
any_t& operator=(any_t&&) = default; any_t& operator=(any_t&&) = default;
~any_t() = default; ~any_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_any, "any() not supported by current database");
os << "ANY(";
_select.serialize(os, db);
os << ")";
}
private:
Select _select; Select _select;
}; };
} }
template<typename T> namespace vendor
auto any(T&& t) -> typename detail::any_t<typename operand_t<T, is_select_t>::type>
{ {
return { std::forward<T>(t) }; template<typename Context, typename Select>
} struct interpreter_t<Context, vendor::any_t<Select>>
{
using T = vendor::any_t<Select>;
static Context& _(const T& t, Context& context)
{
context << "ANY(";
interpret(t._select, context);
context << ")";
return context;
}
};
template<typename T>
auto any(T&& t) -> typename vendor::any_t<typename operand_t<T, is_select_t>::type>
{
return { std::forward<T>(t) };
}
}
} }
#endif #endif

View File

@ -1,86 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_ASSIGNMENT_LIST_H
#define SQLPP_ASSIGNMENT_LIST_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/detail/serialize_tuple.h>
#include <sqlpp11/detail/serializable_list.h>
namespace sqlpp
{
template<typename Database, template<typename> class ProhibitPredicate, typename... Assignments>
struct assignment_list_t
{
using _is_assignment_list = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Assignments...>;
// check for at least one order expression
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment expression required in set()");
// check for duplicate assignments
static_assert(not detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
// check for invalid assignments
using _assignment_set = typename detail::make_set_if<is_assignment_t, Assignments...>::type;
static_assert(_assignment_set::size::value == sizeof...(Assignments), "at least one argument is not an assignment in set()");
// check for prohibited assignments
using _prohibited_assignment_set = typename detail::make_set_if<ProhibitPredicate, typename Assignments::column_type...>::type;
static_assert(_prohibited_assignment_set::size::value == 0, "at least one assignment is prohibited by its column definition in set()");
template<typename Assignment>
void add(Assignment&& assignment)
{
static_assert(is_assignment_t<typename std::decay<Assignment>::type>::value, "set() arguments require to be assigments");
static_assert(not ProhibitPredicate<typename std::decay<Assignment>::type::column_type>::value, "set() argument must not be updated");
_dynamic_assignments.emplace_back(std::forward<Assignment>(assignment));
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << " SET ";
detail::serialize_tuple(os, db, _assignments, ',');
_dynamic_assignments.serialize(os, db, sizeof...(Assignments) == 0);
}
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_assignments, index);
return index;
}
_parameter_tuple_t _assignments;
typename detail::serializable_list<Database> _dynamic_assignments;
};
}
#endif

View File

@ -32,7 +32,7 @@
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Expr> template<typename Expr>
struct avg_t: public floating_point::template operators<avg_t<Expr>> struct avg_t: public floating_point::template operators<avg_t<Expr>>
@ -70,26 +70,33 @@ namespace sqlpp
avg_t& operator=(avg_t&&) = default; avg_t& operator=(avg_t&&) = default;
~avg_t() = default; ~avg_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_avg, "avg() not supported by current database");
os << "AVG(";
_expr.serialize(os, db);
os << ")";
}
private:
Expr _expr; Expr _expr;
}; };
} }
template<typename T> namespace vendor
auto avg(T&& t) -> typename detail::avg_t<typename operand_t<T, is_value_t>::type>
{ {
return { std::forward<T>(t) }; template<typename Context, typename Expr>
struct interpreter_t<Context, vendor::avg_t<Expr>>
{
using T = vendor::avg_t<Expr>;
static Context& _(const T& t, Context& context)
{
context << "AVG(";
interpret(t._expr, context);
context << ")";
return context;
}
};
} }
template<typename T>
auto avg(T&& t) -> typename vendor::avg_t<typename operand_t<T, is_value_t>::type>
{
return { std::forward<T>(t) };
}
} }
#endif #endif

View File

@ -27,11 +27,11 @@
#ifndef SQLPP_DETAIL_BASIC_OPERATORS_H #ifndef SQLPP_DETAIL_BASIC_OPERATORS_H
#define SQLPP_DETAIL_BASIC_OPERATORS_H #define SQLPP_DETAIL_BASIC_OPERATORS_H
#include <sqlpp11/expression.h>
#include <sqlpp11/alias.h> #include <sqlpp11/alias.h>
#include <sqlpp11/sort_order.h> #include <sqlpp11/sort_order.h>
#include <sqlpp11/in.h> #include <sqlpp11/vendor/expression_fwd.h>
#include <sqlpp11/is_null.h> #include <sqlpp11/vendor/in_fwd.h>
#include <sqlpp11/vendor/is_null_fwd.h>
namespace sqlpp namespace sqlpp
{ {
@ -39,84 +39,60 @@ namespace sqlpp
namespace detail namespace detail
{ {
struct boolean; struct boolean;
}
// operators // basic operators
struct lt_ template<typename Base, template<typename> class Constraint>
{ struct basic_operators
using _value_type = boolean;
static constexpr const char* _name = "<";
};
struct le_
{
using _value_type = boolean;
static constexpr const char* _name = "<=";
};
struct ge_
{
using _value_type = boolean;
static constexpr const char* _name = ">=";
};
struct gt_
{
using _value_type = boolean;
static constexpr const char* _name = ">";
};
// basic operators
template<typename Base, template<typename> class Constraint>
struct basic_operators
{ {
template<typename T> template<typename T>
equal_t<Base, typename Constraint<T>::type> operator==(T&& t) const vendor::equal_t<Base, typename Constraint<T>::type> operator==(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
not_equal_t<Base, typename Constraint<T>::type> operator!=(T&& t) const vendor::not_equal_t<Base, typename Constraint<T>::type> operator!=(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, lt_, typename Constraint<T>::type> operator<(T&& t) const vendor::less_than_t<Base, typename Constraint<T>::type> operator<(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, le_, typename Constraint<T>::type> operator<=(T&& t) const vendor::less_equal_t<Base, typename Constraint<T>::type> operator<=(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, ge_, typename Constraint<T>::type> operator>=(T&& t) const vendor::greater_than_t<Base, typename Constraint<T>::type> operator>(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, gt_, typename Constraint<T>::type> operator>(T&& t) const vendor::greater_equal_t<Base, typename Constraint<T>::type> operator>=(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
is_null_t<true, boolean, Base> is_null() const vendor::is_null_t<true, Base> is_null() const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with is_null()"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with is_null()");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
is_null_t<false, boolean, Base> is_not_null() const vendor::is_null_t<false, Base> is_not_null() const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with is_not_null()"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with is_not_null()");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
@ -136,17 +112,17 @@ 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, boolean, Base, typename Constraint<T>::type...> in(T&&... t) const vendor::in_t<true, Base, typename Constraint<T>::type...> in(T&&... t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with in()"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used with in()");
return { *static_cast<const Base*>(this), std::forward<T>(t)... }; return { *static_cast<const Base*>(this), {std::forward<T>(t)}... };
} }
template<typename... T> template<typename... T>
in_t<false, boolean, Base, typename Constraint<T>::type...> not_in(T&&... t) const vendor::in_t<false, Base, typename Constraint<T>::type...> not_in(T&&... t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot with be used with not_in()"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot with be used with not_in()");
return { *static_cast<const Base*>(this), std::forward<T>(t)... }; return { *static_cast<const Base*>(this), {std::forward<T>(t)}... };
} }
template<typename alias_provider> template<typename alias_provider>
@ -155,10 +131,7 @@ namespace sqlpp
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot have a name"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot have a name");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
constexpr bool _is_trivial() const { return false; }
}; };
}
} }
#endif #endif

View File

@ -28,7 +28,8 @@
#define SQLPP_BOOLEAN_H #define SQLPP_BOOLEAN_H
#include <cstdlib> #include <cstdlib>
#include <sqlpp11/detail/basic_operators.h> #include <ostream>
#include <sqlpp11/basic_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
@ -37,18 +38,6 @@ namespace sqlpp
// boolean operators // boolean operators
namespace detail namespace detail
{ {
struct or_
{
using _value_type = boolean;
static constexpr const char* _name = "OR";
};
struct and_
{
using _value_type = boolean;
static constexpr const char* _name = "AND";
};
// boolean value type // boolean value type
struct boolean struct boolean
{ {
@ -62,27 +51,20 @@ namespace sqlpp
{ {
using _value_type = boolean; using _value_type = boolean;
_parameter_t(const std::true_type&): _parameter_t():
_trivial_value_is_null(true),
_value(false), _value(false),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(true)
{}
_parameter_t(const std::false_type&):
_trivial_value_is_null(false),
_value(false),
_is_null(_trivial_value_is_null and _is_trivial())
{} {}
_parameter_t(const _cpp_value_type& value): _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = (_trivial_value_is_null and _is_trivial()); _is_null = (false);
return *this; return *this;
} }
@ -93,14 +75,6 @@ namespace sqlpp
return *this; return *this;
} }
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << value();
}
bool _is_trivial() const { return value() == false; }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
@ -120,7 +94,6 @@ namespace sqlpp
} }
private: private:
bool _trivial_value_is_null;
signed char _value; signed char _value;
bool _is_null; bool _is_null;
}; };
@ -158,14 +131,6 @@ namespace sqlpp
_value = 0; _value = 0;
} }
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << value();
}
bool _is_trivial() const { return value() == false; }
bool is_null() const bool is_null() const
{ {
if (not _is_valid) if (not _is_valid)
@ -201,20 +166,20 @@ namespace sqlpp
struct operators: public basic_operators<Base, _constraint> struct operators: public basic_operators<Base, _constraint>
{ {
template<typename T> template<typename T>
binary_expression_t<Base, and_, typename _constraint<T>::type> operator and(T&& t) const vendor::logical_and_t<Base, typename _constraint<T>::type> operator and(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, or_, typename _constraint<T>::type> operator or(T&& t) const vendor::logical_or_t<Base, typename _constraint<T>::type> operator or(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
not_t<Base> operator not() const vendor::logical_not_t<Base> operator not() const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be as operand for operator not"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be as operand for operator not");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };

View File

@ -27,13 +27,13 @@
#ifndef SQLPP_COLUMN_H #ifndef SQLPP_COLUMN_H
#define SQLPP_COLUMN_H #define SQLPP_COLUMN_H
#include <ostream>
#include <sqlpp11/expression.h>
#include <sqlpp11/alias.h> #include <sqlpp11/alias.h>
#include <sqlpp11/column_fwd.h> #include <sqlpp11/column_fwd.h>
#include <sqlpp11/detail/wrong.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/sort_order.h> #include <sqlpp11/sort_order.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/detail/wrong.h>
namespace sqlpp namespace sqlpp
{ {
@ -58,17 +58,10 @@ namespace sqlpp
column_t& operator=(column_t&&) = default; column_t& operator=(column_t&&) = default;
~column_t() = default; ~column_t() = default;
template<typename Db> static constexpr const char* _get_name()
void serialize(std::ostream& os, Db& db) const {
{ return _name_t::_get_name();
os << Table::_name_t::_get_name() << '.' << _name_t::_get_name(); }
}
template<typename Db>
void serialize_name(std::ostream& os, Db& db) const
{
os << _name_t::_get_name();
}
template<typename alias_provider> template<typename alias_provider>
expression_alias_t<column_t, typename std::decay<alias_provider>::type> as(alias_provider&&) const expression_alias_t<column_t, typename std::decay<alias_provider>::type> as(alias_provider&&) const
@ -79,12 +72,27 @@ namespace sqlpp
template<typename T> template<typename T>
auto operator =(T&& t) const auto operator =(T&& t) const
-> typename std::enable_if<not std::is_same<column_t, typename std::decay<T>::type>::value, -> typename std::enable_if<not std::is_same<column_t, typename std::decay<T>::type>::value,
assignment_t<column_t, typename _value_type::template _constraint<T>::type>>::type vendor::assignment_t<column_t, typename _value_type::template _constraint<T>::type>>::type
{ {
return { *this, std::forward<T>(t) }; return { *this, {std::forward<T>(t)} };
} }
}; };
namespace vendor
{
template<typename Context, typename... Args>
struct interpreter_t<Context, column_t<Args...>>
{
using T = column_t<Args...>;
static Context& _(const T& t, Context& context)
{
context << T::_table::_name_t::_get_name() << '.' << T::_name_t::_get_name();
return context;
}
};
}
} }
#endif #endif

View File

@ -32,14 +32,14 @@
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Expr> template<typename Expr>
struct count_t: public integral::template operators<count_t<Expr>> struct count_t: public sqlpp::detail::integral::template operators<count_t<Expr>>
{ {
static_assert(is_value_t<Expr>::value, "count() requires a sql value as argument"); static_assert(is_value_t<Expr>::value, "count() requires a sql value as argument");
struct _value_type: public integral struct _value_type: public sqlpp::detail::integral
{ {
using _is_named_expression = std::true_type; using _is_named_expression = std::true_type;
}; };
@ -70,26 +70,33 @@ namespace sqlpp
count_t& operator=(count_t&&) = default; count_t& operator=(count_t&&) = default;
~count_t() = default; ~count_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_count, "count() not supported by current database");
os << "COUNT(";
_expr.serialize(os, db);
os << ")";
}
private:
Expr _expr; Expr _expr;
}; };
} }
template<typename T> namespace vendor
auto count(T&& t) -> typename detail::count_t<typename operand_t<T, is_value_t>::type>
{ {
return { std::forward<T>(t) }; template<typename Context, typename Expr>
struct interpreter_t<Context, vendor::count_t<Expr>>
{
using T = vendor::count_t<Expr>;
static Context& _(const T& t, Context& context)
{
context << "COUNT(";
interpret(t._expr, context);
context << ")";
return context;
}
};
} }
template<typename T>
auto count(T&& t) -> typename vendor::count_t<typename operand_t<T, is_value_t>::type>
{
return { std::forward<T>(t) };
}
} }
#endif #endif

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_DETAIL_SERIALIZE_TUPLE_H
#define SQLPP_DETAIL_SERIALIZE_TUPLE_H
#include <tuple>
#include <ostream>
#include <sqlpp11/type_traits.h>
namespace sqlpp
{
namespace detail
{
template<std::size_t begin, std::size_t index, std::size_t end>
struct tuple_serializer_impl
{
template<typename Db, typename Tuple, typename Separator>
static void serialize(std::ostream& os, Db& db, const Tuple& flags_and_columns, const Separator& separator)
{
if (index > begin)
os << separator;
const auto& entry = std::get<index>(flags_and_columns);
using entry_type = typename std::tuple_element<index, Tuple>::type;
if (requires_braces_t<entry_type>::value)
os << "(";
entry.serialize(os, db);
if (requires_braces_t<entry_type>::value)
os << ")";
tuple_serializer_impl<begin, index + 1, end>::serialize(os, db, flags_and_columns, separator);
}
};
template<std::size_t begin, std::size_t end>
struct tuple_serializer_impl<begin, end, end>
{
template<typename Db, typename Tuple, typename Separator>
static void serialize(std::ostream& os, Db& db, const Tuple& flags_and_columns, const Separator& separator)
{
}
};
template<typename Db, typename Tuple, typename Separator>
static void serialize_tuple(std::ostream& os, Db& db, const Tuple& flags_and_columns, const Separator& separator)
{
tuple_serializer_impl<0, 0, std::tuple_size<Tuple>::value>::serialize(os, db, flags_and_columns, separator);
}
}
}
#endif

View File

@ -27,12 +27,11 @@
#ifndef SQLPP_EXISTS_H #ifndef SQLPP_EXISTS_H
#define SQLPP_EXISTS_H #define SQLPP_EXISTS_H
#include <sstream>
#include <sqlpp11/boolean.h> #include <sqlpp11/boolean.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Select> template<typename Select>
struct exists_t: public boolean::template operators<exists_t<Select>> struct exists_t: public boolean::template operators<exists_t<Select>>
@ -70,26 +69,34 @@ namespace sqlpp
exists_t& operator=(exists_t&&) = default; exists_t& operator=(exists_t&&) = default;
~exists_t() = default; ~exists_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_exists, "exists() not supported by current database");
os << "EXISTS(";
_select.serialize(os, db);
os << ")";
}
private:
Select _select; Select _select;
}; };
} }
template<typename T> namespace vendor
auto exists(T&& t) -> typename detail::exists_t<typename operand_t<T, is_select_t>::type>
{ {
return { std::forward<T>(t) }; template<typename Context, typename Select>
struct interpreter_t<Context, vendor::exists_t<Select>>
{
using T = vendor::exists_t<Select>;
static Context& _(const T& t, Context& context)
{
context << "EXISTS(";
interpret(t._select, context);
context << ")";
return context;
}
};
} }
template<typename T>
auto exists(T&& t) -> typename vendor::exists_t<typename operand_t<T, is_select_t>::type>
{
return { std::forward<T>(t) };
}
} }
#endif #endif

View File

@ -1,251 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EXPRESSION_H
#define SQLPP_EXPRESSION_H
#include <sqlpp11/detail/wrap_operand.h>
#include <sqlpp11/detail/serialize_tuple.h>
#include <sqlpp11/alias.h>
#include <sqlpp11/noop.h>
#include <sqlpp11/parameter_list.h> // FIXME: a forward for set_parameter_index would be nice here
namespace sqlpp
{
template<typename Lhs, typename Rhs>
struct assignment_t
{
using _is_assignment = std::true_type;
using column_type = Lhs;
using value_type = Rhs;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_lhs, index);
index = set_parameter_index(_rhs, index);
return index;
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
_lhs.serialize_name(os, db);
if (trivial_value_is_null_t<Lhs>::value and _rhs._is_trivial())
{
os << "=NULL";
}
else
{
os << "=";
_rhs.serialize(os, db);
}
}
Lhs _lhs;
Rhs _rhs;
};
template<typename Lhs, typename Rhs, typename ValueType = detail::boolean>
struct equal_t: public ValueType::template operators<equal_t<Lhs, Rhs>>
{
using _value_type = ValueType;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_lhs, index);
return set_parameter_index(_rhs, index);
}
template<typename L, typename R>
equal_t(L&& l, R&& r):
_lhs(std::forward<L>(l)),
_rhs(std::forward<R>(r))
{}
equal_t(const equal_t&) = default;
equal_t(equal_t&&) = default;
equal_t& operator=(const equal_t&) = default;
equal_t& operator=(equal_t&&) = default;
~equal_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << "(";
_lhs.serialize(os, db);
if (trivial_value_is_null_t<Lhs>::value and _rhs._is_trivial())
{
os << " IS NULL";
}
else
{
os << "=";
_rhs.serialize(os, db);
}
os << ")";
}
private:
Lhs _lhs;
Rhs _rhs;
};
template<typename Lhs, typename Rhs, typename ValueType = detail::boolean>
struct not_equal_t: public ValueType::template operators<not_equal_t<Lhs, Rhs>>
{
using _value_type = ValueType;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_lhs, index);
return set_parameter_index(_rhs, index);
}
template<typename L, typename R>
not_equal_t(L&& l, R&& r):
_lhs(std::forward<L>(l)),
_rhs(std::forward<R>(r))
{}
not_equal_t(const not_equal_t&) = default;
not_equal_t(not_equal_t&&) = default;
not_equal_t& operator=(const not_equal_t&) = default;
not_equal_t& operator=(not_equal_t&&) = default;
~not_equal_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << "(";
_lhs.serialize(os, db);
if (trivial_value_is_null_t<Lhs>::value and _rhs._is_trivial())
{
os << " IS NOT NULL";
}
else
{
os << "!=";
_rhs.serialize(os, db);
}
os << ")";
}
private:
Lhs _lhs;
Rhs _rhs;
};
template<typename Lhs, typename ValueType = detail::boolean>
struct not_t: public ValueType::template operators<not_t<Lhs>>
{
using _value_type = ValueType;
using _parameter_tuple_t = std::tuple<Lhs>;
size_t _set_parameter_index(size_t index)
{
return set_parameter_index(_lhs, index);
}
not_t(Lhs l):
_lhs(l)
{}
not_t(const not_t&) = default;
not_t(not_t&&) = default;
not_t& operator=(const not_t&) = default;
not_t& operator=(not_t&&) = default;
~not_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << "(";
if (trivial_value_is_null_t<Lhs>::value and _lhs._is_trivial())
{
_lhs.serialize(os, db);
os << " IS NULL";
}
else
{
os << "NOT";
_lhs.serialize(os, db);
}
os << ")";
}
private:
Lhs _lhs;
};
template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t: public O::_value_type::template operators<binary_expression_t<Lhs, O, Rhs>>
{
using _value_type = typename O::_value_type;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_lhs, index);
return set_parameter_index(_rhs, index);
}
binary_expression_t(Lhs&& l, Rhs&& r):
_lhs(std::move(l)),
_rhs(std::move(r))
{}
binary_expression_t(const Lhs& l, const Rhs& r):
_lhs(l),
_rhs(r)
{}
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << "(";
_lhs.serialize(os, db);
os << O::_name;
_rhs.serialize(os, db);
os << ")";
}
private:
Lhs _lhs;
Rhs _rhs;
};
}
#endif

View File

@ -28,9 +28,8 @@
#define SQLPP_FLOATING_POINT_H #define SQLPP_FLOATING_POINT_H
#include <cstdlib> #include <cstdlib>
#include <sqlpp11/detail/basic_operators.h> #include <sqlpp11/basic_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/char_result_row.h> // FIXME: Need to update floating_point
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
namespace sqlpp namespace sqlpp
@ -52,27 +51,20 @@ namespace sqlpp
{ {
using _value_type = integral; using _value_type = integral;
_parameter_t(const std::true_type&): _parameter_t():
_trivial_value_is_null(true),
_value(0), _value(0),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(true)
{}
_parameter_t(const std::false_type&):
_trivial_value_is_null(false),
_value(0),
_is_null(_trivial_value_is_null and _is_trivial())
{} {}
_parameter_t(const _cpp_value_type& value): _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = (_trivial_value_is_null and _is_trivial()); _is_null = false;
return *this; return *this;
} }
@ -83,14 +75,6 @@ namespace sqlpp
return *this; return *this;
} }
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << value();
}
bool _is_trivial() const { return value() == 0; }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
@ -110,7 +94,6 @@ namespace sqlpp
} }
private: private:
bool _trivial_value_is_null;
_cpp_value_type _value; _cpp_value_type _value;
bool _is_null; bool _is_null;
}; };
@ -150,14 +133,6 @@ namespace sqlpp
_value = 0; _value = 0;
} }
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << value();
}
bool _is_trivial() const { return value() == 0; }
bool is_null() const bool is_null() const
{ {
if (not _is_valid) if (not _is_valid)
@ -186,30 +161,6 @@ namespace sqlpp
_cpp_value_type _value; _cpp_value_type _value;
}; };
struct plus_
{
using _value_type = floating_point;
static constexpr const char* _name = "+";
};
struct minus_
{
using _value_type = floating_point;
static constexpr const char* _name = "-";
};
struct multiplies_
{
using _value_type = floating_point;
static constexpr const char* _name = "*";
};
struct divides_
{
using _value_type = floating_point;
static constexpr const char* _name = "/";
};
template<typename T> template<typename T>
using _constraint = operand_t<T, is_numeric_t>; using _constraint = operand_t<T, is_numeric_t>;
@ -217,33 +168,45 @@ namespace sqlpp
struct operators: public basic_operators<Base, _constraint> struct operators: public basic_operators<Base, _constraint>
{ {
template<typename T> template<typename T>
binary_expression_t<Base, plus_, typename _constraint<T>::type> operator +(T&& t) const vendor::plus_t<Base, floating_point, typename _constraint<T>::type> operator +(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, minus_, typename _constraint<T>::type> operator -(T&& t) const vendor::minus_t<Base, floating_point, typename _constraint<T>::type> operator -(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, multiplies_, typename _constraint<T>::type> operator *(T&& t) const vendor::multiplies_t<Base, floating_point, typename _constraint<T>::type> operator *(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, divides_, typename _constraint<T>::type> operator /(T&& t) const vendor::divides_t<Base, typename _constraint<T>::type> operator /(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
vendor::unary_plus_t<floating_point, Base> operator +() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) };
}
vendor::unary_minus_t<floating_point, Base> operator -() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) };
}
template<typename T> template<typename T>
auto operator +=(T&& t) const -> decltype(std::declval<Base>() = std::declval<Base>() + std::forward<T>(t)) auto operator +=(T&& t) const -> decltype(std::declval<Base>() = std::declval<Base>() + std::forward<T>(t))
{ {

View File

@ -1,79 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_FROM_H
#define SQLPP_FROM_H
#include <ostream>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/serializable_list.h>
#include <sqlpp11/detail/serialize_tuple.h>
namespace sqlpp
{
template<typename Database, typename... TableOrJoin>
struct from_t
{
using _is_from = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
// ensure one argument at least
static_assert(_is_dynamic::value or sizeof...(TableOrJoin), "at least one table or join argument required in from()");
// check for duplicate arguments
static_assert(not detail::has_duplicates<TableOrJoin...>::value, "at least one duplicate argument detected in from()");
// check for invalid arguments
using _valid_expressions = typename detail::make_set_if<is_table_t, TableOrJoin...>::type;
static_assert(_valid_expressions::size::value == sizeof...(TableOrJoin), "at least one argument is not a table or join in from()");
// FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance
template<typename Table>
void add(Table&& table)
{
static_assert(is_table_t<typename std::decay<Table>::type>::value, "from arguments require to be tables or joins");
_dynamic_tables.emplace_back(std::forward<Table>(table));
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
if (sizeof...(TableOrJoin) == 0 and _dynamic_tables.empty())
return;
os << " FROM ";
detail::serialize_tuple(os, db, _tables, ',');
_dynamic_tables.serialize(os, db, sizeof...(TableOrJoin) == 0);
}
std::tuple<TableOrJoin...> _tables;
detail::serializable_list<Database> _dynamic_tables;
};
}
#endif

View File

@ -27,11 +27,11 @@
#ifndef SQLPP_FUNCTIONS_H #ifndef SQLPP_FUNCTIONS_H
#define SQLPP_FUNCTIONS_H #define SQLPP_FUNCTIONS_H
#include <sstream>
#include <sqlpp11/parameter.h> #include <sqlpp11/parameter.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/column_types.h> #include <sqlpp11/column_types.h>
#include <sqlpp11/vendor/in.h>
#include <sqlpp11/vendor/is_null.h>
#include <sqlpp11/exists.h> #include <sqlpp11/exists.h>
#include <sqlpp11/any.h> #include <sqlpp11/any.h>
#include <sqlpp11/some.h> #include <sqlpp11/some.h>
@ -40,7 +40,7 @@
#include <sqlpp11/max.h> #include <sqlpp11/max.h>
#include <sqlpp11/avg.h> #include <sqlpp11/avg.h>
#include <sqlpp11/sum.h> #include <sqlpp11/sum.h>
#include <sqlpp11/verbatim_table.h> #include <sqlpp11/verbatim_table.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim
namespace sqlpp namespace sqlpp
{ {
@ -51,17 +51,11 @@ namespace sqlpp
return { std::forward<T>(t) }; return { std::forward<T>(t) };
} }
template<typename ValueType> template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim
struct verbatim_t: public ValueType::template operators<verbatim_t<ValueType>> struct verbatim_t: public ValueType::template operators<verbatim_t<ValueType>>
{ {
using _value_type = ValueType; using _value_type = ValueType;
template<typename Db>
void serialize(std::ostream& os, const Db& db) const
{
os << _verbatim;
}
verbatim_t(const std::string& verbatim): _verbatim(verbatim) {} verbatim_t(const std::string& verbatim): _verbatim(verbatim) {}
verbatim_t(std::string&& verbatim): _verbatim(std::forward<std::string>(verbatim)) {} verbatim_t(std::string&& verbatim): _verbatim(std::forward<std::string>(verbatim)) {}
verbatim_t(const verbatim_t&) = default; verbatim_t(const verbatim_t&) = default;
@ -73,52 +67,76 @@ namespace sqlpp
std::string _verbatim; std::string _verbatim;
}; };
namespace vendor
{
template<typename Context, typename ValueType>
struct interpreter_t<Context, verbatim_t<ValueType>>
{
using T = verbatim_t<ValueType>;
static Context& _(const T& t, Context& context)
{
context << t._verbatim;
return context;
}
};
}
template<typename ValueType, typename StringType> template<typename ValueType, typename StringType>
auto verbatim(StringType&& s) -> verbatim_t<ValueType> auto verbatim(StringType&& s) -> verbatim_t<ValueType>
{ {
return { std::forward<StringType>(s) }; return { std::forward<StringType>(s) };
} }
template<typename Expression, typename Db> template<typename Expression, typename Context>
auto flatten(const Expression& exp, const Db& db) -> verbatim_t<typename std::decay<Expression>::type::_value_type::_base_value_type> auto flatten(const Expression& exp, const Context& context) -> verbatim_t<typename std::decay<Expression>::type::_value_type::_base_value_type>
{ {
std::ostringstream os; static_assert(not make_parameter_list_t<Expression>::type::size::value, "parameters not supported in flattened expressions");
exp.serialize(os, db); context.clear();
return { os.str() }; interpret(exp, context);
return { context.str() };
} }
template<typename Container> template<typename Container>
struct value_list_t // to be used in .in() method struct value_list_t // to be used in .in() method
{ {
using _container_t = Container; using _container_t = Container;
using _value_type = typename operand_t<typename _container_t::value_type, is_value_t>::type::_value_type; using _value_type = typename operand_t<typename _container_t::value_type, is_value_t>::type::_value_type;
using _iterator = decltype(std::begin(std::declval<_container_t>()));
template<typename Db>
void serialize(std::ostream& os, const Db& db) const
{
bool first = true;
for (const auto& entry: _container)
{
if (first)
first = false;
else
os << ',';
value(entry).serialize(os, db);
}
}
_container_t _container; _container_t _container;
}; };
template<typename Container> namespace vendor
auto value_list(Container&& c) -> value_list_t<typename std::decay<Container>::type>
{ {
static_assert(not is_value_t<typename std::decay<Container>::type::value_type>::value, "value_list() is to be called with a container of non-sql-type like std::vector<int>, or std::list(string)"); template<typename Context, typename Container>
return { std::forward<Container>(c) }; struct interpreter_t<Context, value_list_t<Container>>
{
using T = value_list_t<Container>;
static Context& _(const T& t, Context& context)
{
bool first = true;
for (const auto& entry: t._container)
{
if (first)
first = false;
else
context << ',';
interpret(value(entry), context);
}
return context;
}
};
} }
template<typename Container>
auto value_list(Container&& c) -> value_list_t<typename std::decay<Container>::type>
{
static_assert(not is_value_t<typename std::decay<Container>::type::value_type>::value, "value_list() is to be called with a container of non-sql-type like std::vector<int>, or std::list(string)");
return { std::forward<Container>(c) };
}
template<typename T> template<typename T>
constexpr const char* get_sql_name(const T&) constexpr const char* get_sql_name(const T&)
{ {

View File

@ -1,90 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_GROUP_BY_H
#define SQLPP_GROUP_BY_H
#include <ostream>
#include <tuple>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/expression.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/detail/serialize_tuple.h>
#include <sqlpp11/detail/serializable_list.h>
namespace sqlpp
{
template<typename Database, typename... Expr>
struct group_by_t
{
using _is_group_by = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Expr...>;
// ensure one argument at least
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression (e.g. a column) required in group_by()");
// check for duplicate expressions
static_assert(not detail::has_duplicates<Expr...>::value, "at least one duplicate argument detected in group_by()");
// check for invalid expressions
using _valid_expressions = typename detail::make_set_if<is_expression_t, Expr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in group_by()");
template<typename E>
void add(E&& expr)
{
static_assert(is_table_t<typename std::decay<E>::type>::value, "from arguments require to be tables or joins");
_dynamic_expressions.emplace_back(std::forward<E>(expr));
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_group_by, "group_by() not supported by current database");
if (sizeof...(Expr) == 0 and _dynamic_expressions.empty())
return;
os << " GROUP BY ";
detail::serialize_tuple(os, db, _expressions, ',');
_dynamic_expressions.serialize(os, db, sizeof...(Expr) == 0);
}
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_expressions, index);
return index;
}
_parameter_tuple_t _expressions;
detail::serializable_list<Database> _dynamic_expressions;
};
}
#endif

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_HAVING_H
#define SQLPP_HAVING_H
#include <ostream>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/expression.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/detail/serialize_tuple.h>
#include <sqlpp11/detail/serializable_list.h>
namespace sqlpp
{
template<typename Database, typename... Expr>
struct having_t
{
using _is_having = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Expr...>;
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in having()");
using _valid_expressions = typename detail::make_set_if<is_expression_t, Expr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in having()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
static_assert(not _parameter_list_t::_contains_trivial_value_is_null_t::value, "must not use trivial_value_is_null in parameters of having expression, use where_parameter() instead of parameter() to turn off automatic conversion");
template<typename E>
void add(E&& expr)
{
static_assert(is_expression_t<typename std::decay<E>::type>::value, "invalid expression argument in add_having()");
_dynamic_expressions.emplace_back(std::forward<E>(expr));
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_having, "having() not supported by current database");
if (sizeof...(Expr) == 0 and _dynamic_expressions.empty())
return;
os << " HAVING ";
detail::serialize_tuple(os, db, _expressions, " AND ");
_dynamic_expressions.serialize(os, db, " AND ", sizeof...(Expr) == 0);
}
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_expressions, index);
return index;
}
_parameter_tuple_t _expressions;
detail::serializable_list<Database> _dynamic_expressions;
};
}
#endif

View File

@ -27,61 +27,63 @@
#ifndef SQLPP_INSERT_H #ifndef SQLPP_INSERT_H
#define SQLPP_INSERT_H #define SQLPP_INSERT_H
#include <sstream>
#include <sqlpp11/noop.h>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/insert_list.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_insert.h> #include <sqlpp11/prepared_insert.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/detail/serialize_tuple.h> #include <sqlpp11/vendor/insert_list.h>
#include <sqlpp11/parameter_list.h>
namespace sqlpp namespace sqlpp
{ {
template<
typename Database = void,
typename Table = noop,
typename InsertList = noop
>
struct insert_t;
template< template<
typename Database, typename Database = void,
typename Table, typename Table = vendor::noop,
typename InsertList typename InsertList = vendor::noop
> >
struct insert_t struct insert_t
{ {
static_assert(is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument"); static_assert(vendor::is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument");
static_assert(is_noop<InsertList>::value or is_insert_list_t<InsertList>::value, "invalid 'InsertList' argument"); static_assert(vendor::is_noop<InsertList>::value or is_insert_list_t<InsertList>::value, "invalid 'InsertList' argument");
template<typename AssignmentT> template<typename AssignmentT>
using set_insert_list_t = insert_t<Database, Table, AssignmentT>; using set_insert_list_t = insert_t<Database, Table, AssignmentT>;
using use_default_values_t = insert_t<Database, Table, vendor::insert_default_values_t>;
using _parameter_tuple_t = std::tuple<Table, InsertList>; using _parameter_tuple_t = std::tuple<Table, InsertList>;
using _parameter_list_t = typename make_parameter_list_t<insert_t>::type; using _parameter_list_t = typename make_parameter_list_t<insert_t>::type;
template<typename... Assignment> auto default_values()
auto set(Assignment&&... assignment) -> use_default_values_t
-> set_insert_list_t<insert_list_t<void, must_not_insert_t, typename std::decay<Assignment>::type...>>
{ {
static_assert(std::is_same<InsertList, noop>::value, "cannot call set() twice"); static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call default_values() after set() or default_values()");
// FIXME: Need to check if all required columns are set // FIXME: Need to check if all required columns are set
return { return {
_table, _table,
insert_list_t<void, must_not_insert_t, typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...}, {},
};
}
template<typename... Assignment>
auto set(Assignment&&... assignment)
-> set_insert_list_t<vendor::insert_list_t<void, typename std::decay<Assignment>::type...>>
{
static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call set() after set() or default_values()");
// FIXME: Need to check if all required columns are set
return {
_table,
vendor::insert_list_t<void, typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...},
}; };
} }
template<typename... Assignment> template<typename... Assignment>
auto dynamic_set(Assignment&&... assignment) auto dynamic_set(Assignment&&... assignment)
-> set_insert_list_t<insert_list_t<Database, must_not_insert_t, typename std::decay<Assignment>::type...>> -> set_insert_list_t<vendor::insert_list_t<Database, typename std::decay<Assignment>::type...>>
{ {
static_assert(std::is_same<InsertList, noop>::value, "cannot call set() twice"); static_assert(std::is_same<InsertList, vendor::noop>::value, "cannot call set() after set() or default_values()");
return { return {
_table, _table,
insert_list_t<Database, must_not_insert_t, typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...}, vendor::insert_list_t<Database, typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...},
}; };
} }
@ -95,35 +97,12 @@ namespace sqlpp
return *this; return *this;
} }
template<typename Db>
const insert_t& serialize(std::ostream& os, Db& db) const
{
os << "INSERT INTO ";
_table.serialize(os, db);
if (is_noop<InsertList>::value)
{
detail::serialize_empty_insert_list(os, db);
}
else
{
_insert_list.serialize(os, db);
}
return *this;
}
template<typename Db>
insert_t& serialize(std::ostream& os, Db& db)
{
static_cast<const insert_t*>(this)->serialize(os, db);
return *this;
}
static constexpr size_t _get_static_no_of_parameters() static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; return _parameter_list_t::size::value;
} }
size_t _get_no_of_parameters() size_t _get_no_of_parameters() const
{ {
return _parameter_list_t::size::value; // FIXME: Need to add dynamic parameters here return _parameter_list_t::size::value; // FIXME: Need to add dynamic parameters here
} }
@ -131,7 +110,8 @@ namespace sqlpp
template<typename Db> template<typename Db>
std::size_t run(Db& db) const std::size_t run(Db& db) const
{ {
constexpr bool calledSet = not is_noop<InsertList>::value; // FIXME: check if set or default_values() has ben called
constexpr bool calledSet = not vendor::is_noop<InsertList>::value;
constexpr bool requireSet = Table::_required_insert_columns::size::value > 0; constexpr bool requireSet = Table::_required_insert_columns::size::value > 0;
static_assert(calledSet or not requireSet, "calling set() required for given table"); static_assert(calledSet or not requireSet, "calling set() required for given table");
static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead"); static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
@ -139,29 +119,37 @@ namespace sqlpp
} }
template<typename Db> template<typename Db>
auto prepare(Db& db) auto prepare(Db& db) const
-> prepared_insert_t<typename std::decay<Db>::type, insert_t> -> prepared_insert_t<typename std::decay<Db>::type, insert_t>
{ {
constexpr bool calledSet = not is_noop<InsertList>::value; constexpr bool calledSet = not vendor::is_noop<InsertList>::value;
constexpr bool requireSet = Table::_required_insert_columns::size::value > 0; constexpr bool requireSet = Table::_required_insert_columns::size::value > 0;
static_assert(calledSet or not requireSet, "calling set() required for given table"); static_assert(calledSet or not requireSet, "calling set() required for given table");
_set_parameter_index(0);
return {{}, db.prepare_insert(*this)}; return {{}, db.prepare_insert(*this)};
} }
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_table, index);
index = set_parameter_index(_insert_list, index);
return index;
}
Table _table; Table _table;
InsertList _insert_list; InsertList _insert_list;
}; };
namespace vendor
{
template<typename Context, typename Database, typename Table, typename InsertList>
struct interpreter_t<Context, insert_t<Database, Table, InsertList>>
{
using T = insert_t<Database, Table, InsertList>;
static Context& _(const T& t, Context& context)
{
context << "INSERT INTO ";
interpret(t._table, context);
interpret(t._insert_list, context);
return context;
}
};
}
template<typename Table> template<typename Table>
insert_t<void, typename std::decay<Table>::type> insert_into(Table&& table) insert_t<void, typename std::decay<Table>::type> insert_into(Table&& table)
{ {

View File

@ -1,137 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_INSERT_LIST_H
#define SQLPP_INSERT_LIST_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/detail/serialize_tuple.h>
#include <sqlpp11/detail/serializable_list.h>
namespace sqlpp
{
namespace detail
{
template<typename Db>
void serialize_empty_insert_list(std::ostream& os, const Db& db)
{
if (connector_has_empty_list_insert_t<typename std::decay<Db>::type>::value)
os << " () VALUES()";
else
os << " DEFAULT VALUES";
}
template<typename Column>
struct insert_column
{
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
_column.serialize_name(os, db);
}
Column _column;
};
}
template<typename Database, template<typename> class ProhibitPredicate, typename... Assignments>
struct insert_list_t
{
using _is_insert_list = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<typename Assignments::value_type...>;
// check for at least one order expression
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one select expression required in set()");
// check for duplicate assignments
static_assert(not detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
// check for invalid assignments
using _assignment_set = typename detail::make_set_if<is_assignment_t, Assignments...>::type;
static_assert(_assignment_set::size::value == sizeof...(Assignments), "at least one argument is not an assignment in set()");
// check for prohibited assignments
using _prohibited_assignment_set = typename detail::make_set_if<ProhibitPredicate, typename Assignments::column_type...>::type;
static_assert(_prohibited_assignment_set::size::value == 0, "at least one assignment is prohibited by its column definition in set()");
insert_list_t(Assignments... assignment):
_columns({assignment._lhs}...),
_values(assignment._rhs...)
{}
insert_list_t(const insert_list_t&) = default;
insert_list_t(insert_list_t&&) = default;
insert_list_t& operator=(const insert_list_t&) = default;
insert_list_t& operator=(insert_list_t&&) = default;
~insert_list_t() = default;
template<typename Assignment>
void add(Assignment&& assignment)
{
static_assert(is_assignment_t<typename std::decay<Assignment>::type>::value, "set() arguments require to be assigments");
static_assert(not ProhibitPredicate<typename std::decay<Assignment>::type>::value, "set() argument must not be used in insert");
_dynamic_columns.emplace_back(detail::insert_column<typename Assignment::column_type>{std::forward<typename Assignment::column_type>(assignment._lhs)});
_dynamic_values.emplace_back(std::forward<typename Assignment::value_type>(assignment._rhs));
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
if (sizeof...(Assignments) + _dynamic_columns.size() == 0)
{
detail::serialize_empty_insert_list(os, db);
}
else
{
constexpr bool first = sizeof...(Assignments) == 0;
os << " (";
detail::serialize_tuple(os, db, _columns, ',');
_dynamic_columns.serialize(os, db, first);
os << ") VALUES (";
detail::serialize_tuple(os, db, _values, ',');
_dynamic_values.serialize(os, db, first);
os << ")";
}
}
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_values, index);
return index;
}
std::tuple<detail::insert_column<typename Assignments::column_type>...> _columns;
_parameter_tuple_t _values;
typename detail::serializable_list<Database> _dynamic_columns;
typename detail::serializable_list<Database> _dynamic_values;
};
}
#endif

View File

@ -28,9 +28,10 @@
#define SQLPP_INTEGRAL_H #define SQLPP_INTEGRAL_H
#include <cstdlib> #include <cstdlib>
#include <sqlpp11/detail/basic_operators.h> #include <sqlpp11/basic_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/vendor/value_type.h>
namespace sqlpp namespace sqlpp
{ {
@ -51,27 +52,20 @@ namespace sqlpp
{ {
using _value_type = integral; using _value_type = integral;
_parameter_t(const std::true_type&): _parameter_t():
_trivial_value_is_null(true),
_value(0), _value(0),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(true)
{}
_parameter_t(const std::false_type&):
_trivial_value_is_null(false),
_value(0),
_is_null(_trivial_value_is_null and _is_trivial())
{} {}
explicit _parameter_t(const _cpp_value_type& value): explicit _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = (_trivial_value_is_null and _is_trivial()); _is_null = false;
return *this; return *this;
} }
@ -81,14 +75,6 @@ namespace sqlpp
_is_null = true; _is_null = true;
} }
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << value();
}
bool _is_trivial() const { return value() == 0; }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
@ -108,7 +94,6 @@ namespace sqlpp
} }
private: private:
bool _trivial_value_is_null;
_cpp_value_type _value; _cpp_value_type _value;
bool _is_null; bool _is_null;
}; };
@ -148,14 +133,6 @@ namespace sqlpp
_is_valid = true; _is_valid = true;
} }
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << value();
}
bool _is_trivial() const { return value() == 0; }
bool is_null() const bool is_null() const
{ {
if (not _is_valid) if (not _is_valid)
@ -184,33 +161,6 @@ namespace sqlpp
_cpp_value_type _value; _cpp_value_type _value;
}; };
template<typename T>
struct plus_
{
using _value_type = typename wrap_operand<typename std::decay<T>::type>::type::_value_type;
static constexpr const char* _name = "+";
};
template<typename T>
struct minus_
{
using _value_type = typename wrap_operand<typename std::decay<T>::type>::type::_value_type;
static constexpr const char* _name = "-";
};
template<typename T>
struct multiplies_
{
using _value_type = typename wrap_operand<typename std::decay<T>::type>::type::_value_type;
static constexpr const char* _name = "*";
};
struct divides_
{
using _value_type = floating_point;
static constexpr const char* _name = "/";
};
template<typename T> template<typename T>
using _constraint = operand_t<T, is_numeric_t>; using _constraint = operand_t<T, is_numeric_t>;
@ -218,33 +168,52 @@ namespace sqlpp
struct operators: public basic_operators<Base, _constraint> struct operators: public basic_operators<Base, _constraint>
{ {
template<typename T> template<typename T>
binary_expression_t<Base, plus_<T>, typename _constraint<T>::type> operator +(T&& t) const vendor::plus_t<Base, vendor::value_type_t<T>, typename _constraint<T>::type> operator +(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, minus_<T>, typename _constraint<T>::type> operator -(T&& t) const vendor::minus_t<Base, vendor::value_type_t<T>, typename _constraint<T>::type> operator -(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, multiplies_<T>, typename _constraint<T>::type> operator *(T&& t) const vendor::multiplies_t<Base, vendor::value_type_t<T>, typename _constraint<T>::type> operator *(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
binary_expression_t<Base, divides_, typename _constraint<T>::type> operator /(T&& t) const vendor::divides_t<Base, typename _constraint<T>::type> operator /(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T>
vendor::modulus_t<Base, typename _constraint<T>::type> operator %(T&& t) const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
}
vendor::unary_plus_t<integral, Base> operator +() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) };
}
vendor::unary_minus_t<integral, Base> operator -() const
{
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as unary operand");
return { *static_cast<const Base*>(this) };
}
template<typename T> template<typename T>
auto operator +=(T&& t) const -> decltype(std::declval<Base>() = std::declval<Base>() + std::forward<T>(t)) auto operator +=(T&& t) const -> decltype(std::declval<Base>() = std::declval<Base>() + std::forward<T>(t))
{ {

View File

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

View File

@ -29,6 +29,7 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/on.h> #include <sqlpp11/on.h>
#include <sqlpp11/vendor/noop.h>
namespace sqlpp namespace sqlpp
{ {
@ -73,84 +74,94 @@ namespace sqlpp
static constexpr const char* _name = " RIGHT OUTER "; static constexpr const char* _name = " RIGHT OUTER ";
}; };
template<typename JoinType, typename Lhs, typename Rhs, typename On = noop> template<typename JoinType, typename Lhs, typename Rhs, typename On = vendor::noop>
struct join_t struct join_t
{
static_assert(is_table_t<Lhs>::value, "invalid lhs argument for join()");
static_assert(is_table_t<Rhs>::value, "invalid rhs argument for join()");
static_assert(vendor::is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
static_assert(Lhs::_table_set::template is_disjunct_from<typename Rhs::_table_set>::value, "joined tables must not be identical");
using _is_table = std::true_type;
using _table_set = typename Lhs::_table_set::template join<typename Rhs::_table_set>::type;
template<typename OnT>
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
template<typename... Expr>
auto on(Expr&&... expr)
-> set_on_t<on_t<void, typename std::decay<Expr>::type...>>
{
static_assert(vendor::is_noop<On>::value, "cannot call on() twice for a single join()");
return { _lhs,
_rhs,
{std::tuple<typename std::decay<Expr>::type...>{std::forward<Expr>(expr)...}}
};
}
template<typename T>
join_t<inner_join_t, join_t, typename std::decay<T>::type> join(T&& t)
{
static_assert(not vendor::is_noop<On>::value, "join type requires on()");
return { *this, std::forward<T>(t) };
}
template<typename T>
join_t<inner_join_t, join_t, typename std::decay<T>::type> inner_join(T&& t)
{
static_assert(not vendor::is_noop<On>::value, "join type requires on()");
return { *this, std::forward<T>(t) };
}
template<typename T>
join_t<outer_join_t, join_t, typename std::decay<T>::type> outer_join(T&& t)
{
static_assert(not vendor::is_noop<On>::value, "join type requires on()");
return { *this, std::forward<T>(t) };
}
template<typename T>
join_t<left_outer_join_t, join_t, typename std::decay<T>::type> left_outer_join(T&& t)
{
static_assert(not vendor::is_noop<On>::value, "join type requires on()");
return { *this, std::forward<T>(t) };
}
template<typename T>
join_t<right_outer_join_t, join_t, typename std::decay<T>::type> right_outer_join(T&& t)
{
static_assert(not vendor::is_noop<On>::value, "join type requires on()");
return { *this, std::forward<T>(t) };
}
Lhs _lhs;
Rhs _rhs;
On _on;
};
// FIXME: Need to check if db supports the join type. e.g. sqlite does not support right outer or full outer join
namespace vendor
{ {
static_assert(is_table_t<Lhs>::value, "invalid lhs argument for join()"); template<typename Context, typename JoinType, typename Lhs, typename Rhs, typename On>
static_assert(is_table_t<Rhs>::value, "invalid rhs argument for join()"); struct interpreter_t<Context, join_t<JoinType, Lhs, Rhs, On>>
static_assert(is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
static_assert(Lhs::_table_set::template is_disjunct_from<typename Rhs::_table_set>::value, "joined tables must not be identical");
using _is_table = std::true_type;
using _table_set = typename Lhs::_table_set::template join<typename Rhs::_table_set>::type;
template<typename OnT>
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
template<typename... Expr>
auto on(Expr&&... expr)
-> set_on_t<on_t<void, typename std::decay<Expr>::type...>>
{ {
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()"); using T = join_t<JoinType, Lhs, Rhs, On>;
return { _lhs,
_rhs,
{std::tuple<typename std::decay<Expr>::type...>{std::forward<Expr>(expr)...}}
};
}
template<typename T> static Context& _(const T& t, Context& context)
join_t<inner_join_t, join_t, typename std::decay<T>::type> join(T&& t) {
{ static_assert(not vendor::is_noop<On>::value, "joined tables require on()");
static_assert(not is_noop<On>::value, "join type requires on()"); interpret(t._lhs, context);
return { *this, std::forward<T>(t) }; context << JoinType::_name;
} context << " JOIN ";
context << "(";
interpret(t._rhs, context);
interpret(t._on, context);
return context;
}
};
template<typename T> }
join_t<inner_join_t, join_t, typename std::decay<T>::type> inner_join(T&& t)
{
static_assert(not is_noop<On>::value, "join type requires on()");
return { *this, std::forward<T>(t) };
}
template<typename T>
join_t<outer_join_t, join_t, typename std::decay<T>::type> outer_join(T&& t)
{
static_assert(not is_noop<On>::value, "join type requires on()");
return { *this, std::forward<T>(t) };
}
template<typename T>
join_t<left_outer_join_t, join_t, typename std::decay<T>::type> left_outer_join(T&& t)
{
static_assert(not is_noop<On>::value, "join type requires on()");
return { *this, std::forward<T>(t) };
}
template<typename T>
join_t<right_outer_join_t, join_t, typename std::decay<T>::type> right_outer_join(T&& t)
{
static_assert(not is_noop<On>::value, "join type requires on()");
return { *this, std::forward<T>(t) };
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
// FIXME: Need to check if db supports the join type. e.g. sqlite does not support right outer or full outer join
static_assert(JoinType::template _is_supported<Db>::value, "join type not supported by current database");
static_assert(not is_noop<On>::value, "joined tables require on()");
_lhs.serialize(os, db);
os << JoinType::_name;
os << " JOIN ";
_rhs.serialize(os, db);
_on.serialize(os, db);
}
Lhs _lhs;
Rhs _rhs;
On _on;
};
} }
#endif #endif

View File

@ -32,7 +32,7 @@
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Expr> template<typename Expr>
struct max_t: public boolean::template operators<max_t<Expr>> struct max_t: public boolean::template operators<max_t<Expr>>
@ -70,26 +70,33 @@ namespace sqlpp
max_t& operator=(max_t&&) = default; max_t& operator=(max_t&&) = default;
~max_t() = default; ~max_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_max, "max not supported by current database");
os << "MAX(";
_expr.serialize(os, db);
os << ")";
}
private:
Expr _expr; Expr _expr;
}; };
} }
template<typename T> namespace vendor
auto max(T&& t) -> typename detail::max_t<typename operand_t<T, is_value_t>::type>
{ {
return { std::forward<T>(t) }; template<typename Context, typename Expr>
struct interpreter_t<Context, vendor::max_t<Expr>>
{
using T = vendor::max_t<Expr>;
static Context& _(const T& t, Context& context)
{
context << "MAX(";
interpret(t._expr, context);
context << ")";
return context;
}
};
} }
template<typename T>
auto max(T&& t) -> typename vendor::max_t<typename operand_t<T, is_value_t>::type>
{
return { std::forward<T>(t) };
}
} }
#endif #endif

View File

@ -32,7 +32,7 @@
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Expr> template<typename Expr>
struct min_t: public boolean::template operators<min_t<Expr>> struct min_t: public boolean::template operators<min_t<Expr>>
@ -70,26 +70,33 @@ namespace sqlpp
min_t& operator=(min_t&&) = default; min_t& operator=(min_t&&) = default;
~min_t() = default; ~min_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_min, "min not supported by current database");
os << "MIN(";
_expr.serialize(os, db);
os << ")";
}
private:
Expr _expr; Expr _expr;
}; };
} }
template<typename T> namespace vendor
auto min(T&& t) -> typename detail::min_t<typename operand_t<T, is_value_t>::type>
{ {
return { std::forward<T>(t) }; template<typename Context, typename Expr>
struct interpreter_t<Context, vendor::min_t<Expr>>
{
using T = vendor::min_t<Expr>;
static Context& _(const T& t, Context& context)
{
context << "MIN(";
interpret(t._expr, context);
context << ")";
return context;
}
};
} }
template<typename T>
auto min(T&& t) -> typename vendor::min_t<typename operand_t<T, is_value_t>::type>
{
return { std::forward<T>(t) };
}
} }
#endif #endif

View File

@ -52,20 +52,29 @@ namespace sqlpp
}; };
using _is_multi_column = std::true_type; using _is_multi_column = std::true_type;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
detail::serialize_tuple(os, db, _columns, ',');
}
std::tuple<NamedExpr...> _columns; std::tuple<NamedExpr...> _columns;
}; };
namespace vendor
{
template<typename Context, typename AliasProvider, typename... NamedExpr>
struct interpreter_t<Context, multi_column_t<AliasProvider, NamedExpr...>>
{
using T = multi_column_t<AliasProvider, NamedExpr...>;
static Context& _(const T& t, Context& context)
{
interpret_tuple(t._columns, ',', context);
return context;
}
};
}
namespace detail namespace detail
{ {
template<typename AliasProvider, typename... Expr> template<typename AliasProvider, typename... Expr>
using make_multi_column_t = using make_multi_column_t =
multi_column_t<typename std::decay<AliasProvider>::type, decltype(make_expression_tuple(std::declval<Expr>()...))>; multi_column_t<typename std::decay<AliasProvider>::type, decltype(make_expression_tuple(std::declval<Expr>()...))>;
} }
template<typename AliasProvider, typename... NamedExpr> template<typename AliasProvider, typename... NamedExpr>

View File

@ -31,7 +31,6 @@
namespace sqlpp namespace sqlpp
{ {
// boolean value type
struct no_value_t struct no_value_t
{ {
template<typename T> template<typename T>

View File

@ -27,10 +27,9 @@
#ifndef SQLPP_ON_H #ifndef SQLPP_ON_H
#define SQLPP_ON_H #define SQLPP_ON_H
#include <ostream>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/serialize_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/detail/serializable_list.h> #include <sqlpp11/vendor/interpretable_list.h>
namespace sqlpp namespace sqlpp
{ {
@ -51,20 +50,31 @@ namespace sqlpp
_dynamic_expressions.emplace_back(std::forward<E>(expr)); _dynamic_expressions.emplace_back(std::forward<E>(expr));
} }
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
if (sizeof...(Expr) == 0 and _dynamic_expressions.empty())
return;
os << " ON ";
detail::serialize_tuple(os, db, _expressions, " AND ");
_dynamic_expressions.serialize(os, db, " AND ", sizeof...(Expr) == 0);
}
std::tuple<Expr...> _expressions; std::tuple<Expr...> _expressions;
detail::serializable_list<Database> _dynamic_expressions; vendor::interpretable_list_t<Database> _dynamic_expressions;
}; };
namespace vendor
{
template<typename Context, typename Database, typename... Expr>
struct interpreter_t<Context, on_t<Database, Expr...>>
{
using T = on_t<Database, Expr...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
return context;
context << " ON ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
}
} }
#endif #endif

View File

@ -1,87 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_ORDER_BY_H
#define SQLPP_ORDER_BY_H
#include <tuple>
#include <ostream>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/serialize_tuple.h>
#include <sqlpp11/detail/serializable.h>
namespace sqlpp
{
template<typename Database,typename... Expr>
struct order_by_t
{
using _is_order_by = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Expr...>;
// check for at least one order expression
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one sort-order expression required in order_by()");
// check for duplicate order expressions
static_assert(not detail::has_duplicates<Expr...>::value, "at least one duplicate argument detected in order_by()");
// check for invalid order expressions
using _valid_expressions = typename detail::make_set_if<is_sort_order_t, Expr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not a sort order expression in order_by()");
template<typename E>
void add(E&& expr)
{
static_assert(is_sort_order_t<typename std::decay<E>::type>::value, "order_by arguments require to be sort-order expressions");
_dynamic_expressions.push_back(std::forward<E>(expr));
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_order_by, "order by not supported by current database");
if (sizeof...(Expr) == 0 and _dynamic_expressions.empty())
return;
os << " ORDER BY ";
detail::serialize_tuple(os, db, _expressions, ',');
_dynamic_expressions.serialize(os, db, sizeof...(Expr) == 0);
}
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_expressions, index);
return index;
}
_parameter_tuple_t _expressions;
detail::serializable_list<Database> _dynamic_expressions;
};
}
#endif

View File

@ -27,58 +27,46 @@
#ifndef SQLPP_PARAMETER_H #ifndef SQLPP_PARAMETER_H
#define SQLPP_PARAMETER_H #define SQLPP_PARAMETER_H
#include <ostream>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
namespace sqlpp namespace sqlpp
{ {
template<typename ValueType, typename NameType, typename TrivialValueIsNull> template<typename ValueType, typename NameType>
struct parameter_t struct parameter_t: public ValueType::template operators<parameter_t<ValueType, NameType>>
{ {
using _value_type = ValueType; using _value_type = ValueType;
using _is_parameter = std::true_type; using _is_parameter = std::true_type;
using _is_expression_t = std::true_type; using _is_expression_t = std::true_type;
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>; using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>;
using _trivial_value_is_null_t = TrivialValueIsNull;
static_assert(std::is_same<_trivial_value_is_null_t, std::true_type>::value or std::is_same<_trivial_value_is_null_t, std::false_type>::value, "Invalid template parameter TrivialValueIsNull"); parameter_t()
{}
template<typename Db> parameter_t(const parameter_t&) = default;
void serialize(std::ostream& os, Db& db) const parameter_t(parameter_t&&) = default;
{ parameter_t& operator=(const parameter_t&) = default;
static_assert(Db::_supports_prepared, "prepared statements not supported by current database"); parameter_t& operator=(parameter_t&&) = default;
static_assert(Db::_use_questionmark_parameter or Db::_use_positional_dollar_parameter, "no known way to serialize parameter placeholders for current database"); ~parameter_t() = default;
if (Db::_use_questionmark_parameter)
os << '?';
else if (Db::_use_positional_dollar_parameter)
os << '$' << _index + 1;
}
constexpr bool _is_trivial() const
{
return false;
}
size_t _set_parameter_index(size_t index)
{
_index = index;
return index + 1;
}
size_t _index;
}; };
template<typename NamedExpr, typename TrivialValueIsNull = trivial_value_is_null_t<typename std::decay<NamedExpr>::type>> namespace vendor
auto parameter(NamedExpr&& namedExpr) {
-> parameter_t<typename std::decay<NamedExpr>::type::_value_type, typename std::decay<NamedExpr>::type, TrivialValueIsNull> template<typename Context, typename ValueType, typename NameType>
{ struct interpreter_t<Context, parameter_t<ValueType, NameType>>
return {}; {
} using T = parameter_t<ValueType, NameType>;
static Context& _(const T& t, Context& context)
{
context << "?";
return context;
}
};
}
template<typename NamedExpr> template<typename NamedExpr>
auto where_parameter(NamedExpr&& namedExpr) auto parameter(NamedExpr&& namedExpr)
-> parameter_t<typename std::decay<NamedExpr>::type::_value_type, typename std::decay<NamedExpr>::type, std::false_type> -> parameter_t<typename std::decay<NamedExpr>::type::_value_type, typename std::decay<NamedExpr>::type>
{ {
return {}; return {};
} }

View File

@ -32,25 +32,6 @@
namespace sqlpp namespace sqlpp
{ {
namespace detail
{
template<typename... T>
struct or_t;
template<typename T, typename... Rest>
struct or_t<T, Rest...>
{
static constexpr bool value = T::value or or_t<Rest...>::value;
};
template<>
struct or_t<>
{
static constexpr bool value = false;
};
}
template<typename T> template<typename T>
struct parameter_list_t struct parameter_list_t
{ {
@ -62,10 +43,8 @@ namespace sqlpp
{ {
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)>;
using _contains_trivial_value_is_null_t = detail::or_t<typename Parameter::_trivial_value_is_null_t...>;
parameter_list_t(): parameter_list_t()
Parameter::_instance_t({typename Parameter::_trivial_value_is_null_t()})...
{} {}
template<typename Target> template<typename Target>
@ -126,70 +105,6 @@ namespace sqlpp
using type = parameter_list_t<typename detail::get_parameter_tuple<typename std::decay<Exp>::type>::type>; using type = parameter_list_t<typename detail::get_parameter_tuple<typename std::decay<Exp>::type>::type>;
}; };
template<typename T>
size_t set_parameter_index(T& t, size_t index);
namespace detail
{
template<typename Exp, typename Enable = void>
struct set_parameter_index_t
{
size_t operator()(Exp& e, size_t index)
{
return index;
}
};
template<typename Exp>
struct set_parameter_index_t<Exp, typename std::enable_if<is_parameter_t<Exp>::value, void>::type>
{
size_t operator()(Exp& e, size_t index)
{
return e._set_parameter_index(index);
}
};
template<typename... Param>
struct set_parameter_index_t<std::tuple<Param...>, void>
{
template<size_t> struct type{};
size_t operator()(std::tuple<Param...>& t, size_t index)
{
return impl(t, index, type<0>());
}
private:
template<size_t pos>
size_t impl(std::tuple<Param...>& t, size_t index, const type<pos>&)
{
index = sqlpp::set_parameter_index(std::get<pos>(t), index);
return impl(t, index, type<pos + 1>());
}
size_t impl(std::tuple<Param...>& t, size_t index, const type<sizeof...(Param)>&)
{
return index;
}
};
template<typename Exp>
struct set_parameter_index_t<Exp, typename std::enable_if<not std::is_same<typename Exp::_parameter_tuple_t, void>::value, void>::type>
{
size_t operator()(Exp& e, size_t index)
{
return e._set_parameter_index(index);
}
};
}
template<typename T>
size_t set_parameter_index(T& t, size_t index)
{
return detail::set_parameter_index_t<T>()(t, index);
}
} }
#endif #endif

View File

@ -27,21 +27,20 @@
#ifndef SQLPP_REMOVE_H #ifndef SQLPP_REMOVE_H
#define SQLPP_REMOVE_H #define SQLPP_REMOVE_H
#include <sstream>
#include <sqlpp11/noop.h>
#include <sqlpp11/using.h>
#include <sqlpp11/where.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_remove.h> #include <sqlpp11/prepared_remove.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/using.h>
#include <sqlpp11/vendor/where.h>
namespace sqlpp namespace sqlpp
{ {
template< template<
typename Database, typename Database,
typename Table, typename Table,
typename Using = noop, typename Using = vendor::noop,
typename Where = noop typename Where = vendor::noop
> >
struct remove_t; struct remove_t;
@ -53,9 +52,12 @@ namespace sqlpp
> >
struct remove_t struct remove_t
{ {
static_assert(is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument"); static_assert(vendor::is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument");
static_assert(is_noop<Using>::value or is_using_t<Using>::value, "invalid 'Using' argument"); static_assert(vendor::is_noop<Using>::value or is_using_t<Using>::value, "invalid 'Using' argument");
static_assert(is_noop<Where>::value or is_where_t<Where>::value, "invalid 'Where' argument"); static_assert(vendor::is_noop<Where>::value or is_where_t<Where>::value, "invalid 'Where' argument");
// FIXME: We might want to have everywhere() or all() to indicate that everything is to be removed, same with update and select
template<typename UsingT> template<typename UsingT>
using set_using_t = remove_t<Database, Table, UsingT, Where>; using set_using_t = remove_t<Database, Table, UsingT, Where>;
@ -67,10 +69,10 @@ namespace sqlpp
template<typename... Tab> template<typename... Tab>
auto using_(Tab&&... tab) auto using_(Tab&&... tab)
-> set_using_t<using_t<void, typename std::decay<Tab>::type...>> -> set_using_t<vendor::using_t<void, typename std::decay<Tab>::type...>>
{ {
static_assert(std::is_same<Using, noop>::value, "cannot call using() twice"); static_assert(vendor::is_noop<Using>::value, "cannot call using() twice");
static_assert(std::is_same<Where, noop>::value, "cannot call using() after where()"); static_assert(vendor::is_noop<Where>::value, "cannot call using() after where()");
return { return {
_table, _table,
{std::tuple<typename std::decay<Tab>::type...>{std::forward<Tab>(tab)...}}, {std::tuple<typename std::decay<Tab>::type...>{std::forward<Tab>(tab)...}},
@ -80,10 +82,10 @@ namespace sqlpp
template<typename... Tab> template<typename... Tab>
auto dynamic_using_(Tab&&... tab) auto dynamic_using_(Tab&&... tab)
-> set_using_t<using_t<Database, typename std::decay<Tab>::type...>> -> set_using_t<vendor::using_t<Database, typename std::decay<Tab>::type...>>
{ {
static_assert(std::is_same<Using, noop>::value, "cannot call using() twice"); static_assert(vendor::is_noop<Using>::value, "cannot call using() twice");
static_assert(std::is_same<Where, noop>::value, "cannot call using() after where()"); static_assert(vendor::is_noop<Where>::value, "cannot call using() after where()");
return { return {
_table, _table,
{std::tuple<typename std::decay<Tab>::type...>{std::forward<Tab>(tab)...}}, {std::tuple<typename std::decay<Tab>::type...>{std::forward<Tab>(tab)...}},
@ -102,9 +104,9 @@ namespace sqlpp
template<typename... Expr> template<typename... Expr>
auto where(Expr&&... expr) auto where(Expr&&... expr)
-> set_where_t<where_t<void, typename std::decay<Expr>::type...>> -> set_where_t<vendor::where_t<void, typename std::decay<Expr>::type...>>
{ {
static_assert(std::is_same<Where, noop>::value, "cannot call where() twice"); static_assert(vendor::is_noop<Where>::value, "cannot call where() twice");
return { return {
_table, _table,
_using, _using,
@ -114,9 +116,9 @@ namespace sqlpp
template<typename... Expr> template<typename... Expr>
auto dynamic_where(Expr&&... expr) auto dynamic_where(Expr&&... expr)
-> set_where_t<where_t<Database, typename std::decay<Expr>::type...>> -> set_where_t<vendor::where_t<Database, typename std::decay<Expr>::type...>>
{ {
static_assert(std::is_same<Where, noop>::value, "cannot call where() twice"); static_assert(vendor::is_noop<Where>::value, "cannot call where() twice");
return { return {
_table, _table,
_using, _using,
@ -134,30 +136,12 @@ namespace sqlpp
return *this; return *this;
} }
template<typename Db>
const remove_t& serialize(std::ostream& os, Db& db) const
{
os << "DELETE FROM ";
_table.serialize(os, db);
_using.serialize(os, db);
_where.serialize(os, db);
return *this;
}
template<typename Db>
remove_t& serialize(std::ostream& os, Db& db)
{
static_cast<const remove_t*>(this)->serialize(os, db);
return *this;
}
static constexpr size_t _get_static_no_of_parameters() static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; return _parameter_list_t::size::value;
} }
size_t _get_no_of_parameters() size_t _get_no_of_parameters() const
{ {
return _parameter_list_t::size::value; // FIXME: Need to add dynamic parameters here return _parameter_list_t::size::value; // FIXME: Need to add dynamic parameters here
} }
@ -170,27 +154,35 @@ namespace sqlpp
} }
template<typename Db> template<typename Db>
auto prepare(Db& db) auto prepare(Db& db) const
-> prepared_remove_t<typename std::decay<Db>::type, remove_t> -> prepared_remove_t<typename std::decay<Db>::type, remove_t>
{ {
_set_parameter_index(0);
return {{}, db.prepare_remove(*this)}; return {{}, db.prepare_remove(*this)};
} }
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_table, index);
index = set_parameter_index(_using, index);
index = set_parameter_index(_where, index);
return index;
}
Table _table; Table _table;
Using _using; Using _using;
Where _where; Where _where;
}; };
namespace vendor
{
template<typename Context, typename Database, typename Table, typename Using, typename Where>
struct interpreter_t<Context, remove_t<Database, Table, Using, Where>>
{
using T = remove_t<Database, Table, Using, Where>;
static Context& _(const T& t, Context& context)
{
context << "DELETE FROM ";
interpret(t._table, context);
interpret(t._using, context);
interpret(t._where, context);
return context;
}
};
}
template<typename Table> template<typename Table>
constexpr remove_t<void, typename std::decay<Table>::type> remove_from(Table&& table) constexpr remove_t<void, typename std::decay<Table>::type> remove_from(Table&& table)
{ {

View File

@ -27,10 +27,9 @@
#ifndef SQLPP_RESULT_ROW_H #ifndef SQLPP_RESULT_ROW_H
#define SQLPP_RESULT_ROW_H #define SQLPP_RESULT_ROW_H
#include <sqlpp11/char_result_row.h> #include <sqlpp11/vendor/char_result_row.h>
#include <sqlpp11/field.h> #include <sqlpp11/vendor/field.h>
#include <sqlpp11/text.h> #include <sqlpp11/text.h>
#include <iostream>
#include <map> #include <map>
namespace sqlpp namespace sqlpp
@ -87,7 +86,7 @@ namespace sqlpp
}; };
template<size_t level, size_t index, typename AliasProvider, typename... Col, typename... Rest> template<size_t level, size_t index, typename AliasProvider, typename... Col, typename... Rest>
struct result_row_impl<level, index, multi_field_t<AliasProvider, std::tuple<Col...>>, Rest...>: struct result_row_impl<level, index, vendor::multi_field_t<AliasProvider, std::tuple<Col...>>, Rest...>:
public AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Col...>>, // level prevents identical closures to be present twice in the inheritance tree public AliasProvider::_name_t::template _member_t<result_row_impl<level, index, Col...>>, // level prevents identical closures to be present twice in the inheritance tree
public result_row_impl<level, index + sizeof...(Col), Rest...> public result_row_impl<level, index + sizeof...(Col), Rest...>
{ {

View File

@ -29,20 +29,22 @@
#include <sqlpp11/result.h> #include <sqlpp11/result.h>
#include <sqlpp11/select_fwd.h> #include <sqlpp11/select_fwd.h>
#include <sqlpp11/noop.h>
#include <sqlpp11/select_flag_list.h>
#include <sqlpp11/select_expression_list.h>
#include <sqlpp11/from.h>
#include <sqlpp11/where.h>
#include <sqlpp11/group_by.h>
#include <sqlpp11/having.h>
#include <sqlpp11/order_by.h>
#include <sqlpp11/limit.h>
#include <sqlpp11/offset.h>
#include <sqlpp11/expression.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_select.h> #include <sqlpp11/prepared_select.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/select_flag_list.h>
#include <sqlpp11/vendor/select_expression_list.h>
#include <sqlpp11/vendor/from.h>
#include <sqlpp11/vendor/where.h>
#include <sqlpp11/vendor/group_by.h>
#include <sqlpp11/vendor/having.h>
#include <sqlpp11/vendor/order_by.h>
#include <sqlpp11/vendor/limit.h>
#include <sqlpp11/vendor/offset.h>
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/detail/wrong.h> #include <sqlpp11/detail/wrong.h>
#include <sqlpp11/detail/make_flag_tuple.h> #include <sqlpp11/detail/make_flag_tuple.h>
#include <sqlpp11/detail/make_expression_tuple.h> #include <sqlpp11/detail/make_expression_tuple.h>
@ -79,15 +81,15 @@ namespace sqlpp
using _Database = Database; using _Database = Database;
using _From = From; using _From = From;
static_assert(is_noop<Flags>::value or is_select_flag_list_t<Flags>::value, "invalid list of select flags"); static_assert(vendor::is_noop<Flags>::value or is_select_flag_list_t<Flags>::value, "invalid list of select flags");
static_assert(is_select_expression_list_t<ExpressionList>::value, "invalid list of select expressions"); static_assert(is_select_expression_list_t<ExpressionList>::value, "invalid list of select expressions");
static_assert(is_noop<From>::value or is_from_t<From>::value, "invalid 'from' argument"); static_assert(vendor::is_noop<From>::value or is_from_t<From>::value, "invalid 'from' argument");
static_assert(is_noop<Where>::value or is_where_t<Where>::value, "invalid 'where' argument"); static_assert(vendor::is_noop<Where>::value or is_where_t<Where>::value, "invalid 'where' argument");
static_assert(is_noop<GroupBy>::value or is_group_by_t<GroupBy>::value, "invalid 'group by' arguments"); static_assert(vendor::is_noop<GroupBy>::value or is_group_by_t<GroupBy>::value, "invalid 'group by' arguments");
static_assert(is_noop<Having>::value or is_having_t<Having>::value, "invalid 'having' arguments"); static_assert(vendor::is_noop<Having>::value or is_having_t<Having>::value, "invalid 'having' arguments");
static_assert(is_noop<OrderBy>::value or is_order_by_t<OrderBy>::value, "invalid 'order by' arguments"); static_assert(vendor::is_noop<OrderBy>::value or is_order_by_t<OrderBy>::value, "invalid 'order by' arguments");
static_assert(is_noop<Limit>::value or is_limit_t<Limit>::value, "invalid 'limit' arguments"); static_assert(vendor::is_noop<Limit>::value or is_limit_t<Limit>::value, "invalid 'limit' arguments");
static_assert(is_noop<Offset>::value or is_offset_t<Offset>::value, "invalid 'offset' arguments"); static_assert(vendor::is_noop<Offset>::value or is_offset_t<Offset>::value, "invalid 'offset' arguments");
using _is_select = std::true_type; using _is_select = std::true_type;
using _requires_braces = std::true_type; using _requires_braces = std::true_type;
@ -116,7 +118,7 @@ namespace sqlpp
// Indicators // Indicators
using _value_type = typename std::conditional< using _value_type = typename std::conditional<
is_noop<From>::value, vendor::is_noop<From>::value,
no_value_t, // If there is no from, the select is not complete (this logic is a bit simple, but better than nothing) no_value_t, // If there is no from, the select is not complete (this logic is a bit simple, but better than nothing)
typename ExpressionList::_value_type>::type; typename ExpressionList::_value_type>::type;
@ -173,7 +175,7 @@ namespace sqlpp
-> set_expression_list_t<typename ExpressionList::template _dynamic_t<Database>> -> set_expression_list_t<typename ExpressionList::template _dynamic_t<Database>>
{ {
static_assert(not std::is_same<Database, void>::value, "cannot call dynamic_from() in a non-dynamic select"); static_assert(not std::is_same<Database, void>::value, "cannot call dynamic_from() in a non-dynamic select");
static_assert(is_noop<From>::value, "cannot call dynamic_columns() after from()"); static_assert(vendor::is_noop<From>::value, "cannot call dynamic_columns() after from()");
return { return {
_flags, _flags,
{_expression_list._expressions}, {_expression_list._expressions},
@ -200,10 +202,10 @@ namespace sqlpp
// sqlpp functions // sqlpp functions
template<typename... Table> template<typename... Table>
auto from(Table&&... table) auto from(Table&&... table)
-> set_from_t<from_t<void, typename std::decay<Table>::type...>> -> set_from_t<vendor::from_t<void, typename std::decay<Table>::type...>>
{ {
static_assert(not is_noop<ExpressionList>::value, "cannot call from() without having selected anything"); static_assert(not vendor::is_noop<ExpressionList>::value, "cannot call from() without having selected anything");
static_assert(is_noop<From>::value, "cannot call from() twice for a single select"); static_assert(vendor::is_noop<From>::value, "cannot call from() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -219,11 +221,11 @@ namespace sqlpp
template<typename... Table> template<typename... Table>
auto dynamic_from(Table&&... table) auto dynamic_from(Table&&... table)
-> set_from_t<from_t<Database, typename std::decay<Table>::type...>> -> set_from_t<vendor::from_t<Database, typename std::decay<Table>::type...>>
{ {
static_assert(not std::is_same<Database, void>::value, "cannot call dynamic_from() in a non-dynamic select"); static_assert(not std::is_same<Database, void>::value, "cannot call dynamic_from() in a non-dynamic select");
static_assert(not is_noop<ExpressionList>::value, "cannot call from() without having selected anything"); static_assert(not vendor::is_noop<ExpressionList>::value, "cannot call from() without having selected anything");
static_assert(is_noop<From>::value, "cannot call from() twice for a single select"); static_assert(vendor::is_noop<From>::value, "cannot call from() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -240,7 +242,7 @@ namespace sqlpp
template<typename Table> template<typename Table>
select_t& add_from(Table&& table) select_t& add_from(Table&& table)
{ {
static_assert(not is_noop<ExpressionList>::value, "cannot call add_from() without having selected anything"); static_assert(not vendor::is_noop<ExpressionList>::value, "cannot call add_from() without having selected anything");
static_assert(is_dynamic_t<From>::value, "cannot call add_from() in a non-dynamic from"); static_assert(is_dynamic_t<From>::value, "cannot call add_from() in a non-dynamic from");
_from.add(std::forward<Table>(table)); _from.add(std::forward<Table>(table));
@ -250,10 +252,10 @@ namespace sqlpp
template<typename... Expr> template<typename... Expr>
auto where(Expr&&... expr) auto where(Expr&&... expr)
-> set_where_t<where_t<void, typename std::decay<Expr>::type...>> -> set_where_t<vendor::where_t<void, typename std::decay<Expr>::type...>>
{ {
static_assert(not is_noop<From>::value, "cannot call where() without a from()"); static_assert(not vendor::is_noop<From>::value, "cannot call where() without a from()");
static_assert(is_noop<Where>::value, "cannot call where() or dynamic_where() twice for a single select"); static_assert(vendor::is_noop<Where>::value, "cannot call where() or dynamic_where() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -269,10 +271,10 @@ namespace sqlpp
template<typename... Expr> template<typename... Expr>
auto dynamic_where(Expr&&... expr) auto dynamic_where(Expr&&... expr)
-> set_where_t<where_t<Database, typename std::decay<Expr>::type...>> -> set_where_t<vendor::where_t<Database, typename std::decay<Expr>::type...>>
{ {
static_assert(not is_noop<From>::value, "cannot call dynamic_where() without a from()"); static_assert(not vendor::is_noop<From>::value, "cannot call dynamic_where() without a from()");
static_assert(is_noop<Where>::value, "cannot call where() or dynamic_where() twice for a single select"); static_assert(vendor::is_noop<Where>::value, "cannot call where() or dynamic_where() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -298,10 +300,10 @@ namespace sqlpp
template<typename... Col> template<typename... Col>
auto group_by(Col&&... column) auto group_by(Col&&... column)
-> set_group_by_t<group_by_t<void, typename std::decay<Col>::type...>> -> set_group_by_t<vendor::group_by_t<void, typename std::decay<Col>::type...>>
{ {
static_assert(not is_noop<From>::value, "cannot call group_by() without a from()"); static_assert(not vendor::is_noop<From>::value, "cannot call group_by() without a from()");
static_assert(is_noop<GroupBy>::value, "cannot call group_by() twice for a single select"); static_assert(vendor::is_noop<GroupBy>::value, "cannot call group_by() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -317,10 +319,10 @@ namespace sqlpp
template<typename... Col> template<typename... Col>
auto dynamic_group_by(Col&&... column) auto dynamic_group_by(Col&&... column)
-> set_group_by_t<group_by_t<Database, typename std::decay<Col>::type...>> -> set_group_by_t<vendor::group_by_t<Database, typename std::decay<Col>::type...>>
{ {
static_assert(not is_noop<From>::value, "cannot call group_by() without a from()"); static_assert(not vendor::is_noop<From>::value, "cannot call group_by() without a from()");
static_assert(is_noop<GroupBy>::value, "cannot call group_by() twice for a single select"); static_assert(vendor::is_noop<GroupBy>::value, "cannot call group_by() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -346,10 +348,10 @@ namespace sqlpp
template<typename... Expr> template<typename... Expr>
auto having(Expr&&... expr) auto having(Expr&&... expr)
-> set_having_t<having_t<void, typename std::decay<Expr>::type...>> -> set_having_t<vendor::having_t<void, typename std::decay<Expr>::type...>>
{ {
static_assert(not is_noop<GroupBy>::value, "cannot call having() without a group_by"); static_assert(not vendor::is_noop<GroupBy>::value, "cannot call having() without a group_by");
static_assert(is_noop<Having>::value, "cannot call having() twice for a single select"); static_assert(vendor::is_noop<Having>::value, "cannot call having() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -365,10 +367,10 @@ namespace sqlpp
template<typename... Expr> template<typename... Expr>
auto dynamic_having(Expr&&... expr) auto dynamic_having(Expr&&... expr)
-> set_having_t<having_t<Database, typename std::decay<Expr>::type...>> -> set_having_t<vendor::having_t<Database, typename std::decay<Expr>::type...>>
{ {
static_assert(not is_noop<GroupBy>::value, "cannot call having() without a group_by"); static_assert(not vendor::is_noop<GroupBy>::value, "cannot call having() without a group_by");
static_assert(is_noop<Having>::value, "cannot call having() twice for a single select"); static_assert(vendor::is_noop<Having>::value, "cannot call having() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -394,10 +396,10 @@ namespace sqlpp
template<typename... OrderExpr> template<typename... OrderExpr>
auto order_by(OrderExpr&&... expr) auto order_by(OrderExpr&&... expr)
-> set_order_by_t<order_by_t<void, typename std::decay<OrderExpr>::type...>> -> set_order_by_t<vendor::order_by_t<void, typename std::decay<OrderExpr>::type...>>
{ {
static_assert(not is_noop<From>::value, "cannot call order_by() without a from()"); static_assert(not vendor::is_noop<From>::value, "cannot call order_by() without a from()");
static_assert(is_noop<OrderBy>::value, "cannot call order_by() twice for a single select"); static_assert(vendor::is_noop<OrderBy>::value, "cannot call order_by() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -413,10 +415,10 @@ namespace sqlpp
template<typename... OrderExpr> template<typename... OrderExpr>
auto dynamic_order_by(OrderExpr&&... expr) auto dynamic_order_by(OrderExpr&&... expr)
-> set_order_by_t<order_by_t<Database, typename std::decay<OrderExpr>::type...>> -> set_order_by_t<vendor::order_by_t<Database, typename std::decay<OrderExpr>::type...>>
{ {
static_assert(not is_noop<From>::value, "cannot call order_by() without a from()"); static_assert(not vendor::is_noop<From>::value, "cannot call order_by() without a from()");
static_assert(is_noop<OrderBy>::value, "cannot call order_by() twice for a single select"); static_assert(vendor::is_noop<OrderBy>::value, "cannot call order_by() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -442,10 +444,10 @@ namespace sqlpp
template<typename Expr> template<typename Expr>
auto limit(Expr limit) auto limit(Expr limit)
-> set_limit_t<limit_t<typename std::decay<Expr>::type>> -> set_limit_t<vendor::limit_t<typename vendor::wrap_operand<typename std::decay<Expr>::type>::type>>
{ {
static_assert(not is_noop<From>::value, "cannot call limit() without a from()"); static_assert(not vendor::is_noop<From>::value, "cannot call limit() without a from()");
static_assert(is_noop<Limit>::value, "cannot call limit() twice for a single select"); static_assert(vendor::is_noop<Limit>::value, "cannot call limit() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -460,10 +462,10 @@ namespace sqlpp
} }
auto dynamic_limit(std::size_t limit = 0) auto dynamic_limit(std::size_t limit = 0)
->set_limit_t<dynamic_limit_t> ->set_limit_t<vendor::dynamic_limit_t>
{ {
static_assert(not is_noop<From>::value, "cannot call limit() without a from()"); static_assert(not vendor::is_noop<From>::value, "cannot call limit() without a from()");
static_assert(is_noop<Limit>::value, "cannot call limit() twice for a single select"); static_assert(vendor::is_noop<Limit>::value, "cannot call limit() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -488,10 +490,10 @@ namespace sqlpp
template<typename Expr> template<typename Expr>
auto offset(Expr offset) auto offset(Expr offset)
-> set_offset_t<offset_t<typename std::decay<Expr>::type>> -> set_offset_t<vendor::offset_t<typename vendor::wrap_operand<typename std::decay<Expr>::type>::type>>
{ {
static_assert(not is_noop<Limit>::value, "cannot call offset() without a limit"); static_assert(not vendor::is_noop<Limit>::value, "cannot call offset() without a limit");
static_assert(is_noop<Offset>::value, "cannot call offset() twice for a single select"); static_assert(vendor::is_noop<Offset>::value, "cannot call offset() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -506,10 +508,10 @@ namespace sqlpp
} }
auto dynamic_offset(std::size_t offset = 0) auto dynamic_offset(std::size_t offset = 0)
-> set_offset_t<dynamic_offset_t> -> set_offset_t<vendor::dynamic_offset_t>
{ {
static_assert(not is_noop<Limit>::value, "cannot call offset() without a limit"); static_assert(not vendor::is_noop<Limit>::value, "cannot call offset() without a limit");
static_assert(is_noop<Offset>::value, "cannot call offset() twice for a single select"); static_assert(vendor::is_noop<Offset>::value, "cannot call offset() twice for a single select");
return { return {
_flags, _flags,
_expression_list, _expression_list,
@ -536,7 +538,7 @@ namespace sqlpp
struct _pseudo_table_t struct _pseudo_table_t
{ {
using table = typename ExpressionList::template _pseudo_table_t<select_t>; using table = typename ExpressionList::template _pseudo_table_t<select_t>;
using alias = typename table::template alias_t<AliasProvider>; using alias = typename table::template _alias_t<AliasProvider>;
}; };
template<typename AliasProvider> template<typename AliasProvider>
@ -546,32 +548,6 @@ namespace sqlpp
*this).as(aliasProvider); *this).as(aliasProvider);
} }
// Serialize
template<typename Db>
const select_t& serialize(std::ostream& os, Db& db) const
{
os << "SELECT ";
_flags.serialize(os, db);
_expression_list.serialize(os, db);
_from.serialize(os, db);
_where.serialize(os, db);
_group_by.serialize(os, db);
_having.serialize(os, db);
_order_by.serialize(os, db);
_limit.serialize(os, db);
_offset.serialize(os, db);
return *this;
}
template<typename Db>
select_t& serialize(std::ostream& os, Db& db)
{
const_cast<const select_t*>(this)->serialize(os, db);
return *this;
}
const typename ExpressionList::_dynamic_names_t& get_dynamic_names() const const typename ExpressionList::_dynamic_names_t& get_dynamic_names() const
{ {
return _expression_list._dynamic_expressions._dynamic_expression_names; return _expression_list._dynamic_expressions._dynamic_expression_names;
@ -582,7 +558,7 @@ namespace sqlpp
return _parameter_list_t::size::value; return _parameter_list_t::size::value;
} }
size_t _get_no_of_parameters() size_t _get_no_of_parameters() const
{ {
return _parameter_list_t::size::value; // FIXME: Need to add dynamic parameters here return _parameter_list_t::size::value; // FIXME: Need to add dynamic parameters here
} }
@ -597,7 +573,7 @@ namespace sqlpp
auto run(Db& db) const auto run(Db& db) const
-> result_t<decltype(db.select(*this)), _result_row_t> -> result_t<decltype(db.select(*this)), _result_row_t>
{ {
static_assert(not is_noop<ExpressionList>::value, "cannot run select without having selected anything"); static_assert(not vendor::is_noop<ExpressionList>::value, "cannot run select without having selected anything");
static_assert(is_from_t<From>::value, "cannot run select without a from()"); static_assert(is_from_t<From>::value, "cannot run select without a from()");
static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead"); static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
// FIXME: Check for missing aliases (if references are used) // FIXME: Check for missing aliases (if references are used)
@ -608,30 +584,17 @@ namespace sqlpp
// Prepare // Prepare
template<typename Db> template<typename Db>
auto prepare(Db& db) auto prepare(Db& db) const
-> prepared_select_t<typename std::decay<Db>::type, select_t> -> prepared_select_t<typename std::decay<Db>::type, select_t>
{ {
static_assert(not is_noop<ExpressionList>::value, "cannot run select without having selected anything"); static_assert(not vendor::is_noop<ExpressionList>::value, "cannot run select without having selected anything");
static_assert(is_from_t<From>::value, "cannot run select without a from()"); static_assert(is_from_t<From>::value, "cannot run select without a from()");
// FIXME: Check for missing aliases (if references are used) // FIXME: Check for missing aliases (if references are used)
// FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc. // FIXME: Check for missing tables, well, actually, check for missing tables at the where(), order_by(), etc.
_set_parameter_index(0);
return {{}, get_dynamic_names(), db.prepare_select(*this)}; return {{}, get_dynamic_names(), db.prepare_select(*this)};
} }
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_expression_list, index);
index = set_parameter_index(_where, index);
index = set_parameter_index(_group_by, index);
index = set_parameter_index(_having, index);
index = set_parameter_index(_order_by, index);
index = set_parameter_index(_limit, index);
index = set_parameter_index(_offset, index);
return index;
}
Flags _flags; Flags _flags;
ExpressionList _expression_list; ExpressionList _expression_list;
From _from; From _from;
@ -643,12 +606,68 @@ namespace sqlpp
Offset _offset; Offset _offset;
}; };
namespace vendor
{
template<typename Context,
typename Database,
typename Flags,
typename ExpressionList,
typename From,
typename Where,
typename GroupBy,
typename Having,
typename OrderBy,
typename Limit,
typename Offset
>
struct interpreter_t<Context, select_t<Database,
Flags,
ExpressionList,
From,
Where,
GroupBy,
Having,
OrderBy,
Limit,
Offset>>
{
using T = select_t<Database,
Flags,
ExpressionList,
From,
Where,
GroupBy,
Having,
OrderBy,
Limit,
Offset>;
static Context& _(const T& t, Context& context)
{
context << "SELECT ";
interpret(t._flags, context);
interpret(t._expression_list, context);
interpret(t._from, context);
interpret(t._where, context);
interpret(t._group_by, context);
interpret(t._having, context);
interpret(t._order_by, context);
interpret(t._limit, context);
interpret(t._offset, context);
return context;
}
};
}
// construct select flag list // construct select flag list
namespace detail namespace detail
{ {
template<typename... Expr> template<typename... Expr>
using make_select_flag_list_t = using make_select_flag_list_t =
select_flag_list_t<decltype(make_flag_tuple(std::declval<Expr>()...))>; vendor::select_flag_list_t<decltype(make_flag_tuple(std::declval<Expr>()...))>;
} }
// construct select expression list // construct select expression list
@ -656,7 +675,7 @@ namespace sqlpp
{ {
template<typename... Expr> template<typename... Expr>
using make_select_expression_list_t = using make_select_expression_list_t =
select_expression_list_t<void, decltype(make_expression_tuple(std::declval<Expr>()...))>; vendor::select_expression_list_t<void, decltype(make_expression_tuple(std::declval<Expr>()...))>;
} }
template<typename... NamedExpr> template<typename... NamedExpr>
@ -665,7 +684,7 @@ namespace sqlpp
{ {
return { return {
{ detail::make_flag_tuple(std::forward<NamedExpr>(namedExpr)...) }, { detail::make_flag_tuple(std::forward<NamedExpr>(namedExpr)...) },
{ detail::make_expression_tuple(std::forward<NamedExpr>(namedExpr)...) } { detail::make_expression_tuple(std::forward<NamedExpr>(namedExpr)...) }
}; };
} }
template<typename Db, typename... NamedExpr> template<typename Db, typename... NamedExpr>
@ -674,7 +693,7 @@ namespace sqlpp
{ {
return { return {
{ detail::make_flag_tuple(std::forward<NamedExpr>(namedExpr)...) }, { detail::make_flag_tuple(std::forward<NamedExpr>(namedExpr)...) },
{ detail::make_expression_tuple(std::forward<NamedExpr>(namedExpr)...) } { detail::make_expression_tuple(std::forward<NamedExpr>(namedExpr)...) }
}; };
} }

View File

@ -1,176 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_SELECT_EXPRESSION_LIST_H
#define SQLPP_SELECT_EXPRESSION_LIST_H
#include <tuple>
#include <ostream>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/expression_fwd.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/field.h>
#include <sqlpp11/result_row.h>
#include <sqlpp11/table_base.h>
#include <sqlpp11/select_pseudo_table.h>
#include <sqlpp11/detail/named_serializable.h>
#include <sqlpp11/detail/serialize_tuple.h>
#include <sqlpp11/detail/set.h>
namespace sqlpp
{
namespace detail
{
template<typename... Rest>
struct get_first_argument_if_unique
{
using _value_type = no_value_t;
struct _name_t {};
};
template<typename T>
struct get_first_argument_if_unique<T>
{
using _value_type = typename T::_value_type;
using _name_t = typename T::_name_t;
};
template<typename Db>
struct dynamic_select_expression_list
{
using _names_t = std::vector<std::string>;
std::vector<detail::named_serializable_t<Db>> _dynamic_expressions;
_names_t _dynamic_expression_names;
template<typename Expr>
void push_back(Expr&& expr)
{
_dynamic_expression_names.push_back(std::decay<Expr>::type::_name_t::_get_name());
_dynamic_expressions.emplace_back(std::forward<Expr>(expr));
}
void serialize(std::ostream& os, Db& db, bool first) const
{
for (const auto column : _dynamic_expressions)
{
if (not first)
os << ',';
column.serialize(os, db);
first = false;
}
}
};
template<>
struct dynamic_select_expression_list<void>
{
struct _names_t {};
_names_t _dynamic_expression_names;
template<typename T>
void push_back(const T&) {}
template<typename Db>
void serialize(std::ostream&, Db&, bool) const
{
}
};
}
template<typename Database, typename... NamedExpr>
struct select_expression_list_t<Database, std::tuple<NamedExpr...>>
{
using _is_select_expression_list = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<NamedExpr...>;
// check for duplicate select expressions
static_assert(not detail::has_duplicates<NamedExpr...>::value, "at least one duplicate argument detected");
// check for invalid select expressions
template<typename T>
struct is_valid_expression_t: public std::integral_constant<bool, is_named_expression_t<T>::value or is_multi_column_t<T>::value> {};
using _valid_expressions = typename detail::make_set_if<is_valid_expression_t, NamedExpr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(NamedExpr), "at least one argument is not a named expression");
// check for duplicate select expression names
static_assert(not detail::has_duplicates<typename NamedExpr::_name_t...>::value, "at least one duplicate name detected");
// provide type information for sub-selects that are used as expressions
struct _column_type {};
struct _value_type: detail::get_first_argument_if_unique<NamedExpr...>::_value_type
{
using _is_expression = typename std::conditional<sizeof...(NamedExpr) == 1, std::true_type, std::false_type>::type;
using _is_named_expression = typename std::conditional<sizeof...(NamedExpr) == 1, std::true_type, std::false_type>::type;
using _is_alias = std::false_type;
};
using _name_t = typename detail::get_first_argument_if_unique<NamedExpr...>::_name_t;
using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<make_field_t<NamedExpr>...>,
result_row_t<make_field_t<NamedExpr>...>>::type;
using _dynamic_names_t = typename detail::dynamic_select_expression_list<Database>::_names_t;
template <typename Select>
using _pseudo_table_t = select_pseudo_table_t<Select, NamedExpr...>;
template <typename Db>
using _dynamic_t = select_expression_list_t<Db, std::tuple<NamedExpr...>>;
template<typename Expr>
void add(Expr&& namedExpr)
{
static_assert(is_named_expression_t<typename std::decay<Expr>::type>::value, "select() arguments require to be named expressions");
static_assert(_is_dynamic::value, "cannot add columns to a non-dynamic column list");
_dynamic_expressions.push_back(std::forward<Expr>(namedExpr));
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
// check for at least one select expression
static_assert(_is_dynamic::value or sizeof...(NamedExpr), "at least one select expression required");
detail::serialize_tuple(os, db, _expressions, ',');
_dynamic_expressions.serialize(os, db, sizeof...(NamedExpr) == 0);
}
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_expressions, index);
return index;
}
_parameter_tuple_t _expressions;
detail::dynamic_select_expression_list<Database> _dynamic_expressions;
};
}
#endif

View File

@ -27,7 +27,8 @@
#ifndef SQLPP_SELECT_FWD_H #ifndef SQLPP_SELECT_FWD_H
#define SQLPP_SELECT_FWD_H #define SQLPP_SELECT_FWD_H
#include <sqlpp11/noop_fwd.h> // FIXME: Do we really need this file?
#include <sqlpp11/vendor/noop_fwd.h>
#include <type_traits> #include <type_traits>
namespace sqlpp namespace sqlpp
@ -37,36 +38,17 @@ namespace sqlpp
struct distinct_t; struct distinct_t;
struct straight_join_t; struct straight_join_t;
template<typename FlagTuple> struct select_flag_list_t;
template<typename Database, typename NamedExprTuple> struct select_expression_list_t;
template<typename Database, typename... TableOrJoin> struct from_t;
template<typename Database, typename... Expr> struct where_t;
template<typename Database, typename... Expr> struct group_by_t;
template<typename Database, typename... Expr> struct having_t;
template<typename Database, typename... Expr> struct order_by_t;
template<typename Limit>
struct limit_t;
template<typename Offset>
struct offset_t;
template< template<
typename Db, typename Db,
typename Flags = noop, typename Flags = vendor::noop,
typename ExpressionList = noop, typename ExpressionList = vendor::noop,
typename From = noop, typename From = vendor::noop,
typename Where = noop, typename Where = vendor::noop,
typename GroupBy = noop, typename GroupBy = vendor::noop,
typename Having = noop, typename Having = vendor::noop,
typename OrderBy = noop, typename OrderBy = vendor::noop,
typename Limit = noop, typename Limit = vendor::noop,
typename Offset = noop typename Offset = vendor::noop
> >
struct select_t; struct select_t;
} }

View File

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

View File

@ -32,7 +32,7 @@
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Select> template<typename Select>
struct some_t: public boolean::template operators<some_t<Select>> struct some_t: public boolean::template operators<some_t<Select>>
@ -71,26 +71,33 @@ namespace sqlpp
some_t& operator=(some_t&&) = default; some_t& operator=(some_t&&) = default;
~some_t() = default; ~some_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_some, "some() not supported by current database");
os << "SOME(";
_select.serialize(os, db);
os << ")";
}
private:
Select _select; Select _select;
}; };
} }
template<typename T> namespace vendor
auto some(T&& t) -> typename detail::some_t<typename operand_t<T, is_select_t>::type>
{ {
return { std::forward<T>(t) }; template<typename Context, typename Select>
struct interpreter_t<Context, vendor::some_t<Select>>
{
using T = vendor::some_t<Select>;
static Context& _(const T& t, Context& context)
{
context << "SOME(";
interpret(t._select, context);
context << ")";
return context;
}
};
} }
template<typename T>
auto some(T&& t) -> typename vendor::some_t<typename operand_t<T, is_select_t>::type>
{
return { std::forward<T>(t) };
}
} }
#endif #endif

View File

@ -40,23 +40,33 @@ namespace sqlpp
{ {
using _is_sort_order = std::true_type; using _is_sort_order = std::true_type;
template<typename Db> Expression _expression;
void serialize(std::ostream& os, Db& db) const };
namespace vendor
{
template<typename Context, typename Expression, sort_type SortType>
struct interpreter_t<Context, sort_order_t<Expression, SortType>>
{
using T = sort_order_t<Expression, SortType>;
static Context& _(const T& t, Context& context)
{ {
_expression.serialize(os, db); interpret(t._expression, context);
switch(SortType) switch(SortType)
{ {
case sort_type::asc: case sort_type::asc:
os << " ASC"; context << " ASC";
break; break;
default: default:
os << " DESC"; context << " DESC";
break; break;
} }
return context;
} }
};
Expression _expression; }
};
} }
#endif #endif

View File

@ -27,6 +27,7 @@
#ifndef SQLPP_H #ifndef SQLPP_H
#define SQLPP_H #define SQLPP_H
#include <sqlpp11/alias_provider.h>
#include <sqlpp11/column_types.h> #include <sqlpp11/column_types.h>
#include <sqlpp11/insert.h> #include <sqlpp11/insert.h>
#include <sqlpp11/remove.h> #include <sqlpp11/remove.h>

View File

@ -32,7 +32,7 @@
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Expr> template<typename Expr>
struct sum_t: public boolean::template operators<sum_t<Expr>> struct sum_t: public boolean::template operators<sum_t<Expr>>
@ -70,26 +70,33 @@ namespace sqlpp
sum_t& operator=(sum_t&&) = default; sum_t& operator=(sum_t&&) = default;
~sum_t() = default; ~sum_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_sum, "sum not supported by current database");
os << "SUM(";
_expr.serialize(os, db);
os << ")";
}
private:
Expr _expr; Expr _expr;
}; };
} }
template<typename T> namespace vendor
auto sum(T&& t) -> typename detail::sum_t<typename operand_t<T, is_value_t>::type>
{ {
return { std::forward<T>(t) }; template<typename Context, typename Expr>
struct interpreter_t<Context, vendor::sum_t<Expr>>
{
using T = vendor::sum_t<Expr>;
static Context& _(const T& t, Context& context)
{
context << "SUM(";
interpret(t._expr, context);
context << ")";
return context;
}
};
} }
template<typename T>
auto sum(T&& t) -> typename vendor::sum_t<typename operand_t<T, is_value_t>::type>
{
return { std::forward<T>(t) };
}
} }
#endif #endif

View File

@ -24,27 +24,30 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_TABLE_BASE_H #ifndef SQLPP_TABLE_H
#define SQLPP_TABLE_BASE_H #define SQLPP_TABLE_H
#include <ostream> #include <sqlpp11/type_traits.h>
#include <sqlpp11/alias.h> #include <sqlpp11/table_alias.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/column.h> #include <sqlpp11/column.h>
#include <sqlpp11/detail/set.h> #include <sqlpp11/detail/set.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/join.h> #include <sqlpp11/join.h>
#include <sqlpp11/no_value.h>
namespace sqlpp namespace sqlpp
{ {
struct table_base_t {};
template<typename Table, typename... ColumnSpec> template<typename Table, typename... ColumnSpec>
struct table_base_t: public ColumnSpec::_name_t::template _member_t<column_t<Table, ColumnSpec>>... struct table_t: public table_base_t, public ColumnSpec::_name_t::template _member_t<column_t<Table, ColumnSpec>>...
{ {
using _table_set = detail::set<Table>; // Hint need a set here to be similar to a join (which always represents more than one table) using _table_set = detail::set<Table>; // Hint need a set here to be similar to a join (which always represents more than one table)
using _all_columns = typename detail::make_set<column_t<Table, ColumnSpec>...>::type; using _all_columns = typename detail::make_set<column_t<Table, ColumnSpec>...>::type;
static_assert(_all_columns::size::value, "at least one column required per table"); static_assert(_all_columns::size::value, "at least one column required per table");
using _required_insert_columns = typename detail::make_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type; using _required_insert_columns = typename detail::make_set_if<require_insert_t, column_t<Table, ColumnSpec>...>::type;
using _all_of_t = std::tuple<column_t<Table, ColumnSpec>...>; using _all_of_t = std::tuple<column_t<Table, ColumnSpec>...>;
template<typename AliasProvider>
using _alias_t = table_alias_t<typename std::decay<AliasProvider>::type, Table, ColumnSpec...>;
using _is_table = std::true_type; using _is_table = std::true_type;
@ -79,50 +82,15 @@ namespace sqlpp
} }
template<typename AliasProvider> template<typename AliasProvider>
struct alias_t: public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>... _alias_t<AliasProvider> as(const AliasProvider&) const
{
using _is_table = std::true_type;
using _table_set = detail::set<alias_t>;
struct _value_type: Table::_value_type
{
using _is_expression = std::false_type;
using _is_named_expression = copy_type_trait<Table, is_value_t>;
using _is_alias = std::true_type;
};
using _name_t = typename AliasProvider::_name_t;
using _all_of_t = std::tuple<column_t<AliasProvider, ColumnSpec>...>;
alias_t(const Table& table):
_table(table)
{}
alias_t(Table&& table):
_table(std::move(table))
{}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << "("; _table.serialize(os, db); os << ") AS " << _name_t::_get_name();
}
Table _table;
};
template<typename AliasProvider>
alias_t<AliasProvider> as(const AliasProvider&) const
{ {
return {*static_cast<const Table*>(this)}; return {*static_cast<const Table*>(this)};
} }
template<typename Db> const Table& ref() const
void serialize(std::ostream& os, Db& db) const {
{ return *static_cast<const Table*>(this);
static_cast<const Table*>(this)->serialize_impl(os, db); }
}
}; };
template<typename Table> template<typename Table>
@ -131,6 +99,22 @@ namespace sqlpp
return {}; return {};
} }
namespace vendor
{
template<typename Context, typename X>
struct interpreter_t<Context, X, typename std::enable_if<std::is_base_of<table_base_t, X>::value and not is_pseudo_table_t<X>::value, void>::type>
{
using T = X;
static Context& _(const T& t, Context& context)
{
context << T::_name_t::_get_name();
return context;
}
};
}
} }
#endif #endif

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_TABLE_ALIAS_H
#define SQLPP_TABLE_ALIAS_H
#include <sqlpp11/column_fwd.h>
#include <sqlpp11/interpret.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/alias.h>
#include <sqlpp11/detail/set.h>
namespace sqlpp
{
struct table_alias_base_t {};
template<typename AliasProvider, typename Table, typename... ColumnSpec>
struct table_alias_t: public table_alias_base_t, public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
{
//FIXME: Need to add join functionality
using _is_table = std::true_type;
using _table_set = detail::set<table_alias_t>;
struct _value_type: Table::_value_type
{
using _is_expression = std::false_type;
using _is_named_expression = copy_type_trait<Table, is_value_t>;
using _is_alias = std::true_type;
};
using _name_t = typename AliasProvider::_name_t;
using _all_of_t = std::tuple<column_t<AliasProvider, ColumnSpec>...>;
table_alias_t(Table table):
_table(table)
{}
Table _table;
};
namespace vendor
{
template<typename Context, typename X>
struct interpreter_t<Context, X, typename std::enable_if<std::is_base_of<table_alias_base_t, X>::value, void>::type>
{
using T = X;
static Context& _(const T& t, Context& context)
{
context << "(";
interpret(t._table, context);
context << ") AS " << T::_name_t::_get_name();
return context;
}
};
}
}
#endif

View File

@ -28,11 +28,11 @@
#define SQLPP_TEXT_H #define SQLPP_TEXT_H
#include <cstdlib> #include <cstdlib>
#include <sqlpp11/detail/basic_operators.h> #include <sqlpp11/basic_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/concat.h> #include <sqlpp11/vendor/concat.h>
#include <sqlpp11/like.h> #include <sqlpp11/vendor/like.h>
namespace sqlpp namespace sqlpp
{ {
@ -51,27 +51,20 @@ namespace sqlpp
{ {
using _value_type = integral; using _value_type = integral;
_parameter_t(const std::true_type&): _parameter_t():
_trivial_value_is_null(true),
_value(""), _value(""),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(true)
{}
_parameter_t(const std::false_type&):
_trivial_value_is_null(false),
_value(""),
_is_null(_trivial_value_is_null and _is_trivial())
{} {}
_parameter_t(const _cpp_value_type& value): _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = (_trivial_value_is_null and _is_trivial()); _is_null = false;
return *this; return *this;
} }
@ -82,14 +75,6 @@ namespace sqlpp
return *this; return *this;
} }
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << value();
}
bool _is_trivial() const { return value() == ""; }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
@ -109,7 +94,6 @@ namespace sqlpp
} }
private: private:
bool _trivial_value_is_null;
_cpp_value_type _value; _cpp_value_type _value;
bool _is_null; bool _is_null;
}; };
@ -147,14 +131,6 @@ namespace sqlpp
_len = 0; _len = 0;
} }
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << value();
}
bool _is_trivial() const { return _len == 0; }
bool operator==(const _cpp_value_type& rhs) const { return value() == rhs; } bool operator==(const _cpp_value_type& rhs) const { return value() == rhs; }
bool operator!=(const _cpp_value_type& rhs) const { return not operator==(rhs); } bool operator!=(const _cpp_value_type& rhs) const { return not operator==(rhs); }
@ -196,17 +172,17 @@ namespace sqlpp
struct operators: public basic_operators<Base, _constraint> struct operators: public basic_operators<Base, _constraint>
{ {
template<typename T> template<typename T>
detail::concat_t<Base, typename _constraint<T>::type> operator+(T&& t) const vendor::concat_t<Base, typename _constraint<T>::type> operator+(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
template<typename T> template<typename T>
detail::like_t<boolean, Base, typename _constraint<T>::type> like(T&& t) const vendor::like_t<Base, typename _constraint<T>::type> like(T&& t) const
{ {
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot be used as left hand side operand");
return { *static_cast<const Base*>(this), std::forward<T>(t) }; return { *static_cast<const Base*>(this), {std::forward<T>(t)} };
} }
}; };

140
include/sqlpp11/tvin.h Normal file
View File

@ -0,0 +1,140 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_TVIN_H
#define SQLPP_TVIN_H
// TVIN: Trivial value is NULL
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpreter.h>
namespace sqlpp
{
template<typename T>
struct tvin_t
{
using _operand_t = typename vendor::wrap_operand<T>::type;
static_assert(not std::is_same<_operand_t, T>::value, "tvin() used with invalid type (only string and primitive types allowed)");
using _value_type = typename _operand_t::_value_type;
tvin_t(T t):
_value({t})
{}
tvin_t(const tvin_t&) = default;
tvin_t(tvin_t&&) = default;
tvin_t& operator=(const tvin_t&) = default;
tvin_t& operator=(tvin_t&&) = default;
~tvin_t() = default;
_operand_t _value;
};
namespace vendor
{
template<typename Context, typename Type>
struct interpreter_t<Context, tvin_t<Type>>
{
using T = tvin_t<Type>;
static void _(const T& t, Context& context)
{
static_assert(detail::wrong<T>::value, "tvin() must not be used with anything but =, ==, != and !");
}
};
}
template<typename T>
struct tvin_wrap_t
{
static constexpr bool _is_trivial()
{
return false;
}
tvin_wrap_t(T t):
_value(t)
{}
tvin_wrap_t(const tvin_wrap_t&) = default;
tvin_wrap_t(tvin_wrap_t&&) = default;
tvin_wrap_t& operator=(const tvin_wrap_t&) = default;
tvin_wrap_t& operator=(tvin_wrap_t&&) = default;
~tvin_wrap_t() = default;
T _value;
};
template<typename T>
struct tvin_wrap_t<tvin_t<T>>
{
bool _is_trivial() const
{
return _value._is_trivial();
};
tvin_wrap_t(tvin_t<T> t):
_value(t._value)
{}
tvin_wrap_t(const tvin_wrap_t&) = default;
tvin_wrap_t(tvin_wrap_t&&) = default;
tvin_wrap_t& operator=(const tvin_wrap_t&) = default;
tvin_wrap_t& operator=(tvin_wrap_t&&) = default;
~tvin_wrap_t() = default;
typename tvin_t<T>::_operand_t _value;
};
namespace vendor
{
template<typename Context, typename Type>
struct interpreter_t<Context, tvin_wrap_t<Type>>
{
using T = tvin_wrap_t<Type>;
static Context& _(const T& t, Context& context)
{
if (t._is_trivial())
{
context << "NULL";
}
else
{
interpret(t._value, context);
}
return context;
}
};
}
template<typename T>
auto tvin(T t) -> tvin_t<typename std::decay<T>::type>
{
return {t};
}
}
#endif

View File

@ -28,7 +28,7 @@
#define SQLPP_TYPE_TRAITS_H #define SQLPP_TYPE_TRAITS_H
#include <type_traits> #include <type_traits>
#include <sqlpp11/detail/wrap_operand.h> #include <sqlpp11/vendor/wrap_operand.h>
namespace sqlpp namespace sqlpp
{ {
@ -92,9 +92,9 @@ namespace sqlpp
SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_update); SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_update);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert); SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null);
SQLPP_TYPE_TRAIT_GENERATOR(is_table); SQLPP_TYPE_TRAIT_GENERATOR(is_table);
SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table);
SQLPP_TYPE_TRAIT_GENERATOR(is_select); SQLPP_TYPE_TRAIT_GENERATOR(is_select);
SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list); SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_select_expression_list); SQLPP_TYPE_TRAIT_GENERATOR(is_select_expression_list);
@ -112,7 +112,7 @@ namespace sqlpp
SQLPP_TYPE_TRAIT_GENERATOR(is_multi_column); SQLPP_TYPE_TRAIT_GENERATOR(is_multi_column);
SQLPP_TYPE_TRAIT_GENERATOR(is_value_list); SQLPP_TYPE_TRAIT_GENERATOR(is_value_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_assignment); SQLPP_TYPE_TRAIT_GENERATOR(is_assignment);
SQLPP_TYPE_TRAIT_GENERATOR(is_assignment_list); SQLPP_TYPE_TRAIT_GENERATOR(is_update_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_list); SQLPP_TYPE_TRAIT_GENERATOR(is_insert_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_sort_order); SQLPP_TYPE_TRAIT_GENERATOR(is_sort_order);
SQLPP_TYPE_TRAIT_GENERATOR(requires_braces); SQLPP_TYPE_TRAIT_GENERATOR(requires_braces);
@ -126,12 +126,11 @@ namespace sqlpp
template<typename T, template<typename> class IsCorrectType> template<typename T, template<typename> class IsCorrectType>
struct operand_t struct operand_t
{ {
using type = typename detail::wrap_operand<typename std::decay<T>::type>::type; using type = typename vendor::wrap_operand<typename std::decay<T>::type>::type;
static_assert(not is_alias_t<type>::value, "expression operand must not be an alias"); static_assert(not is_alias_t<type>::value, "expression operand must not be an alias");
static_assert(is_expression_t<type>::value, "expression required"); static_assert(is_expression_t<type>::value, "expression required");
static_assert(IsCorrectType<type>::value, "invalid operand type"); static_assert(IsCorrectType<type>::value, "invalid operand type");
}; };
} }

View File

@ -27,21 +27,20 @@
#ifndef SQLPP_UPDATE_H #ifndef SQLPP_UPDATE_H
#define SQLPP_UPDATE_H #define SQLPP_UPDATE_H
#include <sstream>
#include <sqlpp11/noop.h>
#include <sqlpp11/assignment_list.h>
#include <sqlpp11/where.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_update.h> #include <sqlpp11/prepared_update.h>
#include <sqlpp11/vendor/update_list.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/where.h>
namespace sqlpp namespace sqlpp
{ {
template< template<
typename Database = void, typename Database = void,
typename Table = noop, typename Table = vendor::noop,
typename Assignments = noop, typename Assignments = vendor::noop,
typename Where = noop typename Where = vendor::noop
> >
struct update_t; struct update_t;
@ -53,23 +52,24 @@ namespace sqlpp
> >
struct update_t struct update_t
{ {
static_assert(is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument"); static_assert(vendor::is_noop<Table>::value or is_table_t<Table>::value, "invalid 'Table' argument");
static_assert(is_noop<Assignments>::value or is_assignment_list_t<Assignments>::value, "invalid 'Assignments' arguments"); static_assert(vendor::is_noop<Assignments>::value or is_update_list_t<Assignments>::value, "invalid 'Assignments' arguments");
static_assert(is_noop<Where>::value or is_where_t<Where>::value, "invalid 'Where' argument"); static_assert(vendor::is_noop<Where>::value or is_where_t<Where>::value, "invalid 'Where' argument");
template<typename AssignmentsT> template<typename AssignmentsT>
using set_assignments_t = update_t<Database, Table, AssignmentsT, Where>; using set_assignments_t = update_t<Database, Table, AssignmentsT, Where>;
template<typename WhereT> template<typename WhereT>
using set_where_t = update_t<Database, Table, Assignments, WhereT>; using set_where_t = update_t<Database, Table, Assignments, WhereT>;
//FIXME: add method to explicitly indicate that EVERYTHING should be updated?
using _parameter_tuple_t = std::tuple<Table, Assignments, Where>; using _parameter_tuple_t = std::tuple<Table, Assignments, Where>;
using _parameter_list_t = typename make_parameter_list_t<update_t>::type; using _parameter_list_t = typename make_parameter_list_t<update_t>::type;
template<typename... Assignment> template<typename... Assignment>
auto set(Assignment&&... assignment) auto set(Assignment&&... assignment)
-> set_assignments_t<assignment_list_t<void, must_not_update_t, typename std::decay<Assignment>::type...>> -> set_assignments_t<vendor::update_list_t<void, typename std::decay<Assignment>::type...>>
{ {
static_assert(std::is_same<Assignments, noop>::value, "cannot call set() twice"); static_assert(vendor::is_noop<Assignments>::value, "cannot call set() twice");
return { return {
_table, _table,
{std::tuple<typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...}}, {std::tuple<typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...}},
@ -79,9 +79,9 @@ namespace sqlpp
template<typename... Assignment> template<typename... Assignment>
auto dynamic_set(Assignment&&... assignment) auto dynamic_set(Assignment&&... assignment)
-> set_assignments_t<assignment_list_t<Database, must_not_update_t, typename std::decay<Assignment>::type...>> -> set_assignments_t<vendor::update_list_t<Database, typename std::decay<Assignment>::type...>>
{ {
static_assert(std::is_same<Assignments, noop>::value, "cannot call set() twice"); static_assert(vendor::is_noop<Assignments>::value, "cannot call set() twice");
return { return {
_table, _table,
{std::tuple<typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...}}, {std::tuple<typename std::decay<Assignment>::type...>{std::forward<Assignment>(assignment)...}},
@ -101,10 +101,10 @@ namespace sqlpp
template<typename... Expr> template<typename... Expr>
auto where(Expr&&... expr) auto where(Expr&&... expr)
-> set_where_t<where_t<void, typename std::decay<Expr>::type...>> -> set_where_t<vendor::where_t<void, typename std::decay<Expr>::type...>>
{ {
static_assert(not std::is_same<Assignments, noop>::value, "cannot call where() if set() hasn't been called yet"); static_assert(not vendor::is_noop<Assignments>::value, "cannot call where() if set() hasn't been called yet");
static_assert(std::is_same<Where, noop>::value, "cannot call where() twice"); static_assert(vendor::is_noop<Where>::value, "cannot call where() twice");
return { return {
_table, _table,
_assignments, _assignments,
@ -114,10 +114,10 @@ namespace sqlpp
template<typename... Expr> template<typename... Expr>
auto dynamic_where(Expr&&... expr) auto dynamic_where(Expr&&... expr)
-> set_where_t<where_t<Database, typename std::decay<Expr>::type...>> -> set_where_t<vendor::where_t<Database, typename std::decay<Expr>::type...>>
{ {
static_assert(not std::is_same<Assignments, noop>::value, "cannot call where() if set() hasn't been called yet"); static_assert(not vendor::is_noop<Assignments>::value, "cannot call where() if set() hasn't been called yet");
static_assert(std::is_same<Where, noop>::value, "cannot call where() twice"); static_assert(vendor::is_noop<Where>::value, "cannot call where() twice");
return { return {
_table, _table,
_assignments, _assignments,
@ -135,29 +135,12 @@ namespace sqlpp
return *this; return *this;
} }
template<typename Db>
const update_t& serialize(std::ostream& os, Db& db) const
{
os << "UPDATE ";
_table.serialize(os, db);
_assignments.serialize(os, db);
_where.serialize(os, db);
return *this;
}
template<typename Db>
update_t& serialize(std::ostream& os, Db& db)
{
static_cast<const update_t*>(this)->serialize(os, db);
return *this;
}
static constexpr size_t _get_static_no_of_parameters() static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; return _parameter_list_t::size::value;
} }
size_t _get_no_of_parameters() size_t _get_no_of_parameters() const
{ {
return _parameter_list_t::size::value; // FIXME: Need to add dynamic parameters here return _parameter_list_t::size::value; // FIXME: Need to add dynamic parameters here
} }
@ -165,33 +148,48 @@ namespace sqlpp
template<typename Db> template<typename Db>
std::size_t run(Db& db) const std::size_t run(Db& db) const
{ {
static_assert(not is_noop<Assignments>::value, "calling set() required before running update"); static_assert(not vendor::is_noop<Assignments>::value, "calling set() required before running update");
static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead"); static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead");
return db.update(*this); return db.update(*this);
} }
template<typename Db> template<typename Db>
auto prepare(Db& db) auto prepare(Db& db) const
-> prepared_update_t<typename std::decay<Db>::type, update_t> -> prepared_update_t<typename std::decay<Db>::type, update_t>
{ {
static_assert(not is_noop<Assignments>::value, "calling set() required before running update"); static_assert(not vendor::is_noop<Assignments>::value, "calling set() required before running update");
_set_parameter_index(0);
return {{}, db.prepare_update(*this)}; return {{}, db.prepare_update(*this)};
} }
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_table, index);
index = set_parameter_index(_assignments, index);
return index;
}
Table _table; Table _table;
Assignments _assignments; Assignments _assignments;
Where _where; Where _where;
}; };
namespace vendor
{
template<typename Context,
typename Database,
typename Table,
typename Assignments,
typename Where
>
struct interpreter_t<Context, update_t<Database, Table, Assignments, Where>>
{
using T = update_t<Database, Table, Assignments, Where>;
static Context& _(const T& t, Context& context)
{
context << "UPDATE ";
interpret(t._table, context);
interpret(t._assignments, context);
interpret(t._where, context);
return context;
}
};
}
template<typename Table> template<typename Table>
constexpr update_t<void, typename std::decay<Table>::type> update(Table&& table) constexpr update_t<void, typename std::decay<Table>::type> update(Table&& table)
{ {

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_USING_H
#define SQLPP_USING_H
#include <ostream>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/detail/serializable_list.h>
#include <sqlpp11/detail/serialize_tuple.h>
namespace sqlpp
{
template<typename Database, typename... Table>
struct using_t
{
using _is_using = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Table...>;
static_assert(_is_dynamic::value or sizeof...(Table), "at least one table argument required in using()");
// check for duplicate arguments
static_assert(not detail::has_duplicates<Table...>::value, "at least one duplicate argument detected in using()");
// check for invalid arguments
using _valid_expressions = typename detail::make_set_if<is_table_t, Table...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Table), "at least one argument is not an table in using()");
template<typename T>
void add(T&& table)
{
static_assert(is_table_t<typename std::decay<T>::type>::value, "using() arguments require to be tables");
_dynamic_tables.emplace_back(std::forward<T>(table));
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
if (sizeof...(Table) == 0 and _dynamic_tables.empty())
return;
os << " USING ";
detail::serialize_tuple(os, db, _tables, ',');
_dynamic_tables.serialize(os, db, sizeof...(Table) == 0);
}
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_tables, index);
return index;
}
_parameter_tuple_t _tables;
detail::serializable_list<Database> _dynamic_tables;
};
}
#endif

View File

@ -27,19 +27,19 @@
#ifndef SQLPP_CONCAT_H #ifndef SQLPP_CONCAT_H
#define SQLPP_CONCAT_H #define SQLPP_CONCAT_H
#include <sstream>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/detail/set.h> #include <sqlpp11/detail/set.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename First, typename... Args> template<typename First, typename... Args>
struct concat_t: public First::_value_type::template operators<concat_t<First, Args...>> struct concat_t: public First::_value_type::template operators<concat_t<First, Args...>>
{ {
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
using _valid_args = typename detail::make_set_if_not<is_text_t, First, Args...>::type; using _valid_args = typename ::sqlpp::detail::make_set_if_not<is_text_t, First, Args...>::type;
static_assert(_valid_args::size::value == 0, "at least one non-text argument detected in concat()"); static_assert(_valid_args::size::value == 0, "at least one non-text argument detected in concat()");
struct _value_type: public First::_value_type::_base_value_type struct _value_type: public First::_value_type::_base_value_type
@ -57,11 +57,7 @@ namespace sqlpp
}; };
}; };
concat_t(First&& first, Args&&... args): concat_t(First first, Args... args):
_args(std::move(first), std::move(args)...)
{}
concat_t(const First& first, const Args&... args):
_args(first, args...) _args(first, args...)
{} {}
@ -71,35 +67,23 @@ namespace sqlpp
concat_t& operator=(concat_t&&) = default; concat_t& operator=(concat_t&&) = default;
~concat_t() = default; ~concat_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_use_concat_operator or Db::_use_concat_function, "neither concat operator nor concat function supported by current database");
if (Db::_use_concat_operator)
{
os << "(";
detail::serialize_tuple(os, db, _args, "||");
os << ")";
}
else if (Db::_use_concat_function)
{
os << "CONCAT(";
detail::serialize_tuple(os, db, _args, ',');
os << ")";
}
}
private:
std::tuple<First, Args...> _args; std::tuple<First, Args...> _args;
}; };
}
template<typename... T> template<typename Context, typename First, typename... Args>
auto concat(T&&... t) -> typename detail::concat_t<typename operand_t<T, is_text_t>::type...> struct interpreter_t<Context, concat_t<First, Args...>>
{ {
return { std::forward<T>(t)... }; using T = concat_t<First, Args...>;
}
static Context& _(const T& t, Context& context)
{
context << "(";
interpret_tuple(t._args, "||", context);
context << ")";
return context;
}
};
}
} }
#endif #endif

282
include/sqlpp11/vendor/expression.h vendored Normal file
View File

@ -0,0 +1,282 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EXPRESSION_H
#define SQLPP_EXPRESSION_H
#include <sqlpp11/alias.h>
#include <sqlpp11/boolean.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/expression_fwd.h>
#include <sqlpp11/vendor/interpreter.h>
#include <sqlpp11/vendor/wrap_operand.h>
namespace sqlpp
{
namespace vendor
{
template<typename Lhs, typename Rhs>
struct assignment_t
{
using _is_assignment = std::true_type;
using column_type = Lhs;
using value_type = tvin_wrap_t<Rhs>;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
assignment_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
assignment_t(const assignment_t&) = default;
assignment_t(assignment_t&&) = default;
assignment_t& operator=(const assignment_t&) = default;
assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default;
Lhs _lhs;
tvin_wrap_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct interpreter_t<Context, assignment_t<Lhs, Rhs>>
{
using T = assignment_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
interpret(t._lhs, context);
if (t._rhs._is_trivial())
{
context << "=NULL";
}
else
{
context << "=";
interpret(t._rhs, context);
}
return context;
}
};
template<typename Lhs, typename Rhs>
struct equal_t: public detail::boolean::template operators<equal_t<Lhs, Rhs>>
{
using _value_type = detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
equal_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
equal_t(const equal_t&) = default;
equal_t(equal_t&&) = default;
equal_t& operator=(const equal_t&) = default;
equal_t& operator=(equal_t&&) = default;
~equal_t() = default;
Lhs _lhs;
tvin_wrap_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct interpreter_t<Context, equal_t<Lhs, Rhs>>
{
using T = equal_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
interpret(t._lhs, context);
if (t._rhs._is_trivial())
{
context << " IS NULL";
}
else
{
context << "=";
interpret(t._rhs, context);
}
context << ")";
return context;
}
};
template<typename Lhs, typename Rhs>
struct not_equal_t: public detail::boolean::template operators<not_equal_t<Lhs, Rhs>>
{
using _value_type = detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
not_equal_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
not_equal_t(const not_equal_t&) = default;
not_equal_t(not_equal_t&&) = default;
not_equal_t& operator=(const not_equal_t&) = default;
not_equal_t& operator=(not_equal_t&&) = default;
~not_equal_t() = default;
Lhs _lhs;
tvin_wrap_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct interpreter_t<Context, not_equal_t<Lhs, Rhs>>
{
using T = not_equal_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
interpret(t._lhs, context);
if (t._rhs._is_trivial())
{
context << " IS NOT NULL";
}
else
{
context << "!=";
interpret(t._rhs, context);
}
context << ")";
return context;
}
};
template<typename Lhs>
struct logical_not_t: public detail::boolean::template operators<logical_not_t<Lhs>>
{
using _value_type = detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs>;
logical_not_t(Lhs l):
_lhs(l)
{}
logical_not_t(const logical_not_t&) = default;
logical_not_t(logical_not_t&&) = default;
logical_not_t& operator=(const logical_not_t&) = default;
logical_not_t& operator=(logical_not_t&&) = default;
~logical_not_t() = default;
Lhs _lhs;
};
template<typename Context, typename Lhs>
struct interpreter_t<Context, logical_not_t<Lhs>>
{
using T = logical_not_t<Lhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
context << "NOT ";
interpret(t._lhs, context);
context << ")";
return context;
}
};
template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t: public O::_value_type::template operators<binary_expression_t<Lhs, O, Rhs>>
{
using _value_type = typename O::_value_type;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
Rhs _rhs;
};
template<typename Context, typename Lhs, typename O, typename Rhs>
struct interpreter_t<Context, binary_expression_t<Lhs, O, Rhs>>
{
using T = binary_expression_t<Lhs, O, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
interpret(t._lhs, context);
context << O::_name;
interpret(t._rhs, context);
context << ")";
return context;
}
};
template<typename O, typename Rhs>
struct unary_expression_t: public O::_value_type::template operators<unary_expression_t<O, Rhs>>
{
using _value_type = typename O::_value_type;
using _parameter_tuple_t = std::tuple<Rhs>;
unary_expression_t(Rhs rhs):
_rhs(rhs)
{}
unary_expression_t(const unary_expression_t&) = default;
unary_expression_t(unary_expression_t&&) = default;
unary_expression_t& operator=(const unary_expression_t&) = default;
unary_expression_t& operator=(unary_expression_t&&) = default;
~unary_expression_t() = default;
Rhs _rhs;
};
template<typename Context, typename O, typename Rhs>
struct interpreter_t<Context, unary_expression_t<O, Rhs>>
{
using T = unary_expression_t<O, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
context << O::_name;
interpret(t._rhs, context);
context << ")";
return context;
}
};
}
}
#endif

180
include/sqlpp11/vendor/expression_fwd.h vendored Normal file
View File

@ -0,0 +1,180 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EXPRESSION_FWD_H
#define SQLPP_EXPRESSION_FWD_H
namespace sqlpp
{
namespace vendor
{
template<typename Lhs, typename Rhs>
struct assignment_t;
template<typename Lhs, typename Rhs>
struct equal_t;
template<typename Lhs, typename Rhs>
struct not_equal_t;
template<typename Lhs>
struct logical_not_t;
namespace tag
{
struct less_than
{
using _value_type = detail::boolean;
static constexpr const char* _name = "<";
};
struct less_equal
{
using _value_type = detail::boolean;
static constexpr const char* _name = "<=";
};
struct greater_equal
{
using _value_type = detail::boolean;
static constexpr const char* _name = ">=";
};
struct greater_than
{
using _value_type = detail::boolean;
static constexpr const char* _name = ">";
};
struct logical_or
{
using _value_type = detail::boolean;
static constexpr const char* _name = " OR ";
};
struct logical_and
{
using _value_type = detail::boolean;
static constexpr const char* _name = " AND ";
};
template<typename ValueType>
struct plus
{
using _value_type = ValueType;
static constexpr const char* _name = "+";
};
template<typename ValueType>
struct minus
{
using _value_type = ValueType;
static constexpr const char* _name = "-";
};
template<typename ValueType>
struct multiplies
{
using _value_type = ValueType;
static constexpr const char* _name = "*";
};
struct divides
{
using _value_type = detail::floating_point;
static constexpr const char* _name = "/";
};
struct modulus
{
using _value_type = detail::integral;
static constexpr const char* _name = "%";
};
template<typename ValueType>
struct unary_minus
{
using _value_type = ValueType;
static constexpr const char* _name = "-";
};
template<typename ValueType>
struct unary_plus
{
using _value_type = ValueType;
static constexpr const char* _name = "+";
};
}
template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t;
template<typename O, typename Rhs>
struct unary_expression_t;
template<typename Lhs, typename Rhs>
using less_than_t = binary_expression_t<Lhs, tag::less_than, Rhs>;
template<typename Lhs, typename Rhs>
using less_equal_t = binary_expression_t<Lhs, tag::less_equal, Rhs>;
template<typename Lhs, typename Rhs>
using greater_than_t = binary_expression_t<Lhs, tag::greater_than, Rhs>;
template<typename Lhs, typename Rhs>
using greater_equal_t = binary_expression_t<Lhs, tag::greater_equal, Rhs>;
template<typename Lhs, typename Rhs>
using logical_and_t = binary_expression_t<Lhs, tag::logical_and, Rhs>;
template<typename Lhs, typename Rhs>
using logical_or_t = binary_expression_t<Lhs, tag::logical_or, Rhs>;
template<typename Lhs, typename ValueType, typename Rhs>
using plus_t = binary_expression_t<Lhs, tag::plus<ValueType>, Rhs>;
template<typename Lhs, typename ValueType, typename Rhs>
using minus_t = binary_expression_t<Lhs, tag::minus<ValueType>, Rhs>;
template<typename Lhs, typename ValueType, typename Rhs>
using multiplies_t = binary_expression_t<Lhs, tag::multiplies<ValueType>, Rhs>;
template<typename Lhs, typename Rhs>
using divides_t = binary_expression_t<Lhs, tag::divides, Rhs>;
template<typename Lhs, typename Rhs>
using modulus_t = binary_expression_t<Lhs, tag::modulus, Rhs>;
template<typename ValueType, typename Rhs>
using unary_plus_t = unary_expression_t<tag::unary_plus<ValueType>, Rhs>;
template<typename ValueType, typename Rhs>
using unary_minus_t = unary_expression_t<tag::unary_minus<ValueType>, Rhs>;
}
}
#endif

View File

@ -27,41 +27,43 @@
#ifndef SQLPP_FIELD_H #ifndef SQLPP_FIELD_H
#define SQLPP_FIELD_H #define SQLPP_FIELD_H
#include <ostream>
#include <sqlpp11/multi_column.h> #include <sqlpp11/multi_column.h>
namespace sqlpp namespace sqlpp
{ {
template<typename NameType, typename ValueType> namespace vendor
struct field_t
{
using _name_t = NameType;
using _value_type = ValueType;
};
template<typename AliasProvider, typename FieldTuple>
struct multi_field_t
{
};
namespace detail
{ {
template<typename NameType, typename ValueType>
struct field_t
{
using _name_t = NameType;
using _value_type = ValueType;
};
template<typename AliasProvider, typename FieldTuple>
struct multi_field_t
{
};
namespace detail
{
template<typename NamedExpr>
struct make_field_t_impl
{
using type = field_t<typename NamedExpr::_name_t, typename NamedExpr::_value_type::_base_value_type>;
};
template<typename AliasProvider, typename... NamedExpr>
struct make_field_t_impl<multi_column_t<AliasProvider, std::tuple<NamedExpr...>>>
{
using type = multi_field_t<AliasProvider, std::tuple<typename make_field_t_impl<NamedExpr>::type...>>;
};
}
template<typename NamedExpr> template<typename NamedExpr>
struct make_field_t_impl using make_field_t = typename detail::make_field_t_impl<NamedExpr>::type;
{
using type = field_t<typename NamedExpr::_name_t, typename NamedExpr::_value_type::_base_value_type>;
};
template<typename AliasProvider, typename... NamedExpr>
struct make_field_t_impl<multi_column_t<AliasProvider, std::tuple<NamedExpr...>>>
{
using type = multi_field_t<AliasProvider, std::tuple<typename make_field_t_impl<NamedExpr>::type...>>;
};
} }
template<typename NamedExpr>
using make_field_t = typename detail::make_field_t_impl<NamedExpr>::type;
} }
#endif #endif

91
include/sqlpp11/vendor/from.h vendored Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_FROM_H
#define SQLPP_FROM_H
#include <ostream>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/interpret_tuple.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... TableOrJoin>
struct from_t
{
using _is_from = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
// ensure one argument at least
static_assert(_is_dynamic::value or sizeof...(TableOrJoin), "at least one table or join argument required in from()");
// check for duplicate arguments
static_assert(not ::sqlpp::detail::has_duplicates<TableOrJoin...>::value, "at least one duplicate argument detected in from()");
// check for invalid arguments
using _valid_expressions = typename ::sqlpp::detail::make_set_if<is_table_t, TableOrJoin...>::type;
static_assert(_valid_expressions::size::value == sizeof...(TableOrJoin), "at least one argument is not a table or join in from()");
// FIXME: Joins contain two tables. This is not being dealt with at the moment when looking at duplicates, for instance
template<typename Table>
void add(Table&& table)
{
static_assert(is_table_t<typename std::decay<Table>::type>::value, "from arguments require to be tables or joins");
_dynamic_tables.emplace_back(std::forward<Table>(table));
}
std::tuple<TableOrJoin...> _tables;
vendor::interpretable_list_t<Database> _dynamic_tables;
};
template<typename Context, typename Database, typename... TableOrJoin>
struct interpreter_t<Context, from_t<Database, TableOrJoin...>>
{
using T = from_t<Database, TableOrJoin...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(TableOrJoin) == 0 and t._dynamic_tables.empty())
return context;
context << " FROM ";
interpret_tuple(t._tables, ',', context);
if (sizeof...(TableOrJoin) and not t._dynamic_tables.empty())
context << ',';
interpret_list(t._dynamic_tables, ',', context);
return context;
}
};
}
}
#endif

90
include/sqlpp11/vendor/group_by.h vendored Normal file
View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_GROUP_BY_H
#define SQLPP_GROUP_BY_H
#include <tuple>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/detail/set.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... Expr>
struct group_by_t
{
using _is_group_by = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Expr...>;
// ensure one argument at least
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression (e.g. a column) required in group_by()");
// check for duplicate expressions
static_assert(not ::sqlpp::detail::has_duplicates<Expr...>::value, "at least one duplicate argument detected in group_by()");
// check for invalid expressions
using _valid_expressions = typename ::sqlpp::detail::make_set_if<is_expression_t, Expr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in group_by()");
template<typename E>
void add(E&& expr)
{
static_assert(is_table_t<typename std::decay<E>::type>::value, "from arguments require to be tables or joins");
_dynamic_expressions.emplace_back(std::forward<E>(expr));
}
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
template<typename Context, typename Database, typename... Expr>
struct interpreter_t<Context, group_by_t<Database, Expr...>>
{
using T = group_by_t<Database, Expr...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
return context;
context << " GROUP BY ";
interpret_tuple(t._expressions, ',', context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
context << ',';
interpret_list(t._dynamic_expressions, ',', context);
return context;
}
};
}
}
#endif

84
include/sqlpp11/vendor/having.h vendored Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_HAVING_H
#define SQLPP_HAVING_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/detail/set.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... Expr>
struct having_t
{
using _is_having = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Expr...>;
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in having()");
using _valid_expressions = typename ::sqlpp::detail::make_set_if<is_expression_t, Expr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in having()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
template<typename E>
void add(E&& expr)
{
static_assert(is_expression_t<typename std::decay<E>::type>::value, "invalid expression argument in add_having()");
_dynamic_expressions.emplace_back(std::forward<E>(expr));
}
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
template<typename Context, typename Database, typename... Expr>
struct interpreter_t<Context, having_t<Database, Expr...>>
{
using T = having_t<Database, Expr...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
return context;
context << " HAVING ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
}
}
#endif

View File

@ -27,22 +27,22 @@
#ifndef SQLPP_IN_H #ifndef SQLPP_IN_H
#define SQLPP_IN_H #define SQLPP_IN_H
#include <sstream>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/boolean.h>
#include <sqlpp11/vendor/in_fwd.h>
#include <sqlpp11/detail/set.h> #include <sqlpp11/detail/set.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
// The ValueType should be boolean, this is a hack because boolean is not fully defined when the compiler first gets here... template<bool NotInverted, typename Operand, typename... Args>
template<bool NotInverted, typename ValueType, typename Operand, typename... Args> struct in_t: public boolean::template operators<in_t<NotInverted, Operand, Args...>>
struct in_t: public ValueType::_base_value_type::template operators<in_t<NotInverted, ValueType, Args...>>
{ {
static constexpr bool _inverted = not NotInverted; 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 _value_type: public ValueType::_base_value_type // we requite fully defined boolean here struct _value_type: public boolean
{ {
using _is_named_expression = std::true_type; using _is_named_expression = std::true_type;
}; };
@ -73,22 +73,26 @@ namespace sqlpp
in_t& operator=(in_t&&) = default; in_t& operator=(in_t&&) = default;
~in_t() = default; ~in_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert((NotInverted and Db::_supports_in)
or (_inverted and Db::_supports_not_in), "in() and/or not_in() not supported by current database");
_operand.serialize(os, db);
os << (_inverted ? " NOT IN(" : " IN(");
detail::serialize_tuple(os, db, _args, ',');
os << ")";
}
private:
Operand _operand; Operand _operand;
std::tuple<Args...> _args; std::tuple<Args...> _args;
}; };
template<typename Context, bool NotInverted, typename Operand, typename... Args>
struct interpreter_t<Context, vendor::in_t<NotInverted, Operand, Args...>>
{
using T = vendor::in_t<NotInverted, Operand, Args...>;
static Context& _(const T& t, Context& context)
{
interpret(t._operand, context);
context << (t._inverted ? " NOT IN(" : " IN(");
interpret_tuple(t._args, ',', context);
context << ')';
return context;
}
};
} }
} }
#endif #endif

View File

@ -24,16 +24,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_EXPRESSION_FWD_H #ifndef SQLPP_IN_FWD_H
#define SQLPP_EXPRESSION_FWD_H #define SQLPP_IN_FWD_H
namespace sqlpp namespace sqlpp
{ {
template<typename T> namespace vendor
struct is_expression_t; {
template<bool NotInverted, typename Operand, typename... Args>
struct in_t;
}
template<typename T>
struct is_named_expression_t;
} }
#endif #endif

155
include/sqlpp11/vendor/insert_list.h vendored Normal file
View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_INSERT_LIST_H
#define SQLPP_INSERT_LIST_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
namespace sqlpp
{
namespace vendor
{
struct insert_default_values_t
{
using _is_insert_list = std::true_type;
using _is_dynamic = std::false_type;
};
template<typename Context>
struct interpreter_t<Context, insert_default_values_t>
{
using T = insert_default_values_t;
static Context& _(const T& t, Context& context)
{
context << " DEFAULT VALUES";
return context;
}
};
template<typename Column>
struct insert_column_t
{
Column _column;
};
template<typename Context, typename Column>
struct interpreter_t<Context, insert_column_t<Column>>
{
using T = insert_column_t<Column>;
static Context& _(const T& t, Context& context)
{
context << t._column._get_name();
return context;
}
};
template<typename Database, typename... Assignments>
struct insert_list_t
{
using _is_insert_list = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Assignments...>;
// check for at least one order expression
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one select expression required in set()");
// check for duplicate assignments
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
// check for invalid assignments
using _assignment_set = typename ::sqlpp::detail::make_set_if<is_assignment_t, Assignments...>::type;
static_assert(_assignment_set::size::value == sizeof...(Assignments), "at least one argument is not an assignment in set()");
// check for prohibited assignments
using _prohibited_assignment_set = typename ::sqlpp::detail::make_set_if<must_not_insert_t, typename Assignments::column_type...>::type;
static_assert(_prohibited_assignment_set::size::value == 0, "at least one assignment is prohibited by its column definition in set()");
insert_list_t(Assignments... assignment):
_columns({assignment._lhs}...),
_values(assignment._rhs...)
{}
insert_list_t(const insert_list_t&) = default;
insert_list_t(insert_list_t&&) = default;
insert_list_t& operator=(const insert_list_t&) = default;
insert_list_t& operator=(insert_list_t&&) = default;
~insert_list_t() = default;
template<typename Assignment>
void add(Assignment&& assignment)
{
static_assert(is_assignment_t<typename std::decay<Assignment>::type>::value, "set() arguments require to be assigments");
static_assert(not must_not_insert_t<typename std::decay<Assignment>::type>::value, "set() argument must not be used in insert");
_dynamic_columns.emplace_back(insert_column_t<typename Assignment::column_type>{std::forward<typename Assignment::column_type>(assignment._lhs)});
_dynamic_values.emplace_back(std::forward<typename Assignment::value_type>(assignment._rhs));
}
std::tuple<insert_column_t<typename Assignments::column_type>...> _columns;
std::tuple<typename Assignments::value_type...> _values;
typename vendor::interpretable_list_t<Database> _dynamic_columns;
typename vendor::interpretable_list_t<Database> _dynamic_values;
};
template<typename Context, typename Database, typename... Assignments>
struct interpreter_t<Context, insert_list_t<Database, Assignments...>>
{
using T = insert_list_t<Database, Assignments...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Assignments) + t._dynamic_columns.size() == 0)
{
interpret(insert_default_values_t(), context);
}
else
{
context << " (";
interpret_tuple(t._columns, ",", context);
if (sizeof...(Assignments) and not t._dynamic_columns.empty())
context << ',';
interpret_list(t._dynamic_columns, ',', context);
context << ") VALUES(";
interpret_tuple(t._values, ",", context);
if (sizeof...(Assignments) and not t._dynamic_values.empty())
context << ',';
interpret_list(t._dynamic_values, ',', context);
context << ")";
}
return context;
}
};
}
}
#endif

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_INTERPRET_TUPLE_H
#define SQLPP_INTERPRET_TUPLE_H
#include <tuple>
#include <ostream>
#include <sqlpp11/type_traits.h>
namespace sqlpp
{
template<typename Context, typename Tuple>
struct tuple_interpreter_t
{
template<typename Separator>
static void _(const Tuple& t, const Separator& separator, Context& context)
{
_impl(t, separator, context, type<0>());
};
private:
template<size_t> struct type {};
template<typename Separator, size_t index>
static void _impl(const Tuple& t, const Separator& separator, Context& context, const type<index>&)
{
if (index)
context << separator;
const auto& entry = std::get<index>(t);
using entry_type = typename std::tuple_element<index, Tuple>::type;
if (requires_braces_t<entry_type>::value)
context << "(";
interpret(entry, context);
if (requires_braces_t<entry_type>::value)
context << ")";
_impl(t, separator, context, type<index + 1>());
}
template<typename Separator>
static void _impl(const Tuple& t, const Separator& separator, Context& context, const type<std::tuple_size<Tuple>::value>&)
{
}
};
template<typename Tuple, typename Separator, typename Context>
auto interpret_tuple(const Tuple& t, const Separator& separator, Context& context)
-> decltype(tuple_interpreter_t<typename std::decay<Context>::type, typename std::decay<Tuple>::type>::_(t, separator, context))
{
return tuple_interpreter_t<typename std::decay<Context>::type, typename std::decay<Tuple>::type>::_(t, separator, context);
}
}
#endif

View File

@ -24,43 +24,49 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_SERIALIZABLE_H #ifndef SQLPP_INTERPRETABLE_H
#define SQLPP_SERIALIZABLE_H #define SQLPP_INTERPRETABLE_H
#include <ostream>
#include <vector>
#include <memory> #include <memory>
#include <sqlpp11/serializer.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/interpret.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Db> template<typename Db>
struct serializable_t struct interpretable_t
{ {
template<typename T, using _context_t = typename Db::_context_t;
typename std::enable_if<not std::is_same<typename std::decay<T>::type, serializable_t<Db>>::value, int>::type = 0 // prevent accidental overload for copy constructor
> template<typename T>
serializable_t(T&& t): interpretable_t(T t):
_impl(std::make_shared<_impl_t<typename std::decay<T>::type>>(std::forward<T>(t))) _impl(std::make_shared<_impl_t<typename std::decay<T>::type>>(t))
{} {}
serializable_t(const serializable_t&) = default; interpretable_t(const interpretable_t&) = default;
serializable_t(serializable_t&&) = default; interpretable_t(interpretable_t&&) = default;
serializable_t& operator=(const serializable_t&) = default; interpretable_t& operator=(const interpretable_t&) = default;
serializable_t& operator=(serializable_t&&) = default; interpretable_t& operator=(interpretable_t&&) = default;
~serializable_t() = default; ~interpretable_t() = default;
void serialize(std::ostream& os, Db& db) const sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const
{ {
_impl->serialize(os, db); return _impl->interpret(context);
}
_context_t& interpret(_context_t& context) const
{
return _impl->interpret(context);
} }
private: private:
struct _impl_base struct _impl_base
{ {
virtual void serialize(std::ostream& os, Db& db) const = 0; virtual sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const = 0;
virtual _context_t& interpret(_context_t& context) const = 0;
}; };
template<typename T> template<typename T>
@ -75,15 +81,36 @@ namespace sqlpp
_t(std::move(t)) _t(std::move(t))
{} {}
void serialize(std::ostream& os, Db& db) const sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const
{ {
_t.serialize(os, db); sqlpp::interpret(_t, context);
return context;
} }
_context_t& interpret(_context_t& context) const
{
sqlpp::interpret(_t, context);
return context;
}
T _t; T _t;
}; };
std::shared_ptr<const _impl_base> _impl; std::shared_ptr<const _impl_base> _impl;
}; };
template<typename Context, typename Database>
struct interpreter_t<Context, interpretable_t<Database>>
{
using T = interpretable_t<Database>;
static Context& _(const T& t, Context& context)
{
t.interpret(context);
return context;
}
};
} }
} }

View File

@ -24,20 +24,20 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_SERIALIZABLE_LIST_H #ifndef SQLPP_INTERPRETABLE_LIST_H
#define SQLPP_SERIALIZABLE_LIST_H #define SQLPP_INTERPRETABLE_LIST_H
#include <vector> #include <vector>
#include <sqlpp11/detail/serializable.h> #include <sqlpp11/vendor/interpretable.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Db> template<typename Db>
struct serializable_list struct interpretable_list_t
{ {
std::vector<detail::serializable_t<Db>> _serializables; std::vector<interpretable_t<Db>> _serializables;
std::size_t size() const std::size_t size() const
{ {
@ -55,59 +55,67 @@ namespace sqlpp
_serializables.emplace_back(std::forward<Expr>(expr)); _serializables.emplace_back(std::forward<Expr>(expr));
} }
void serialize(std::ostream& os, Db& db, bool first) const
{
for (const auto entry : _serializables)
{
if (not first)
os << ',';
entry.serialize(os, db);
first = false;
}
}
template<typename Separator>
void serialize(std::ostream& os, Db& db, const Separator& separator, bool first) const
{
for (const auto entry : _serializables)
{
if (not first)
os << separator;
entry.serialize(os, db);
first = false;
}
}
}; };
template<> template<>
struct serializable_list<void> struct interpretable_list_t<void>
{ {
template<typename T> template<typename T>
void emplace_back(const T&) {} void emplace_back(const T&) {}
constexpr std::size_t size() const static constexpr std::size_t size()
{ {
return 0; return 0;
} }
constexpr bool empty() const static constexpr bool empty()
{ {
return true; return true;
} }
template<typename Db>
void serialize(std::ostream&, Db&, bool) const
{
}
template<typename Db, typename Separator>
void serialize(std::ostream& os, Db& db, const Separator& separator, bool first) const
{
}
}; };
template<typename Context, typename List>
struct serializable_list_interpreter_t
{
using T = List;
template<typename Separator>
static Context& _(const T& t, const Separator& separator, Context& context)
{
bool first = true;
for (const auto entry : t._serializables)
{
if (not first)
{
context << separator;
first = false;
}
interpret(entry, context);
}
return context;
}
};
template<typename Context>
struct serializable_list_interpreter_t<Context, interpretable_list_t<void>>
{
using T = interpretable_list_t<void>;
template<typename Separator>
static Context& _(const T& t, const Separator& separator, Context& context)
{
return context;
}
};
template<typename T, typename Separator, typename Context>
auto interpret_list(const T& t, const Separator& separator, Context& context)
-> decltype(serializable_list_interpreter_t<typename std::decay<Context>::type, typename std::decay<T>::type>::_(t, separator, context))
{
return serializable_list_interpreter_t<typename std::decay<Context>::type, typename std::decay<T>::type>::_(t, separator, context);
}
} }
} }

48
include/sqlpp11/vendor/interpreter.h vendored Normal file
View File

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

View File

@ -27,21 +27,20 @@
#ifndef SQLPP_IS_NULL_H #ifndef SQLPP_IS_NULL_H
#define SQLPP_IS_NULL_H #define SQLPP_IS_NULL_H
#include <sstream> #include <sqlpp11/boolean.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h> #include <sqlpp11/detail/set.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
// The ValueType should be boolean, this is a hack because boolean is not fully defined when the compiler first gets here... template<bool NotInverted, typename Operand>
template<bool NotInverted, typename ValueType, typename Operand> struct is_null_t: public boolean::template operators<is_null_t<NotInverted, Operand>>
struct is_null_t: public ValueType::_base_value_type::template operators<is_null_t<NotInverted, ValueType, Operand>>
{ {
static constexpr bool _inverted = not NotInverted; static constexpr bool _inverted = not NotInverted;
struct _value_type: public ValueType::_base_value_type // we requite fully defined boolean here struct _value_type: public boolean
{ {
using _is_named_expression = std::true_type; using _is_named_expression = std::true_type;
}; };
@ -70,19 +69,23 @@ namespace sqlpp
is_null_t& operator=(is_null_t&&) = default; is_null_t& operator=(is_null_t&&) = default;
~is_null_t() = default; ~is_null_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert((NotInverted and Db::_supports_is_null)
or (_inverted and Db::_supports_is_not_null), "is_null() and/or is_not_null() not supported by current database");
_operand.serialize(os, db);
os << (_inverted ? " IS NOT NULL" : " IS NULL");
}
private:
Operand _operand; Operand _operand;
}; };
template<typename Context, bool NotInverted, typename Operand>
struct interpreter_t<Context, ::sqlpp::vendor::is_null_t<NotInverted, Operand>>
{
using T = ::sqlpp::vendor::is_null_t<NotInverted, Operand>;
static Context& _(const T& t, Context& context)
{
interpret(t._operand, context);
context << (t._inverted ? " IS NOT NULL" : " IS NULL");
return context;
}
};
} }
} }
#endif #endif

39
include/sqlpp11/vendor/is_null_fwd.h vendored Normal file
View File

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

View File

@ -27,23 +27,22 @@
#ifndef SQLPP_LIKE_H #ifndef SQLPP_LIKE_H
#define SQLPP_LIKE_H #define SQLPP_LIKE_H
#include <sstream> #include <sqlpp11/boolean.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h> #include <sqlpp11/detail/set.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
// The ValueType should be boolean, this is a hack because boolean is not fully defined when the compiler first gets here... template<typename Operand, typename Pattern>
template<typename ValueType, typename Operand, typename Pattern> struct like_t: public boolean::template operators<like_t<Operand, Pattern>>
struct like_t: public ValueType::_base_value_type::template operators<like_t<ValueType, Operand, Pattern>>
{ {
static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text"); static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text");
static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text"); static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text");
using _parameter_tuple_t = std::tuple<ValueType, Pattern>; using _parameter_tuple_t = std::tuple<Operand, Pattern>;
struct _value_type: public ValueType::_base_value_type // we require fully defined boolean here struct _value_type: public boolean
{ {
using _is_named_expression = std::true_type; using _is_named_expression = std::true_type;
}; };
@ -74,27 +73,24 @@ namespace sqlpp
like_t& operator=(like_t&&) = default; like_t& operator=(like_t&&) = default;
~like_t() = default; ~like_t() = default;
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_operand, index);
index = set_parameter_index(_pattern, index);
return index;
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_like, "like() not supported by current database");
_operand.serialize(os, db);
os << " LIKE(";
_pattern.serialize(os, db);
os << ")";
}
private:
Operand _operand; Operand _operand;
Pattern _pattern; Pattern _pattern;
}; };
template<typename Context, typename Operand, typename Pattern>
struct interpreter_t<Context, like_t<Operand, Pattern>>
{
using T = like_t<Operand, Pattern>;
static Context& _(const T& t, Context& context)
{
interpret(t._operand, context);
context << " LIKE(";
interpret(t._pattern, context);
context << ")";
return context;
}
};
} }
} }

View File

@ -33,50 +33,57 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Limit> namespace vendor
struct limit_t {
template<typename Limit>
struct limit_t
{
using _is_limit = std::true_type;
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
Limit _limit;
};
template<typename Context, typename Limit>
struct interpreter_t<Context, limit_t<Limit>>
{
using T = limit_t<Limit>;
static Context& _(const T& t, Context& context)
{
context << " LIMIT ";
interpret(t._limit, context);
return context;
}
};
struct dynamic_limit_t
{ {
using _is_limit = std::true_type; using _is_limit = std::true_type;
using _parameter_tuple_t = std::tuple<Limit>; using _is_dynamic = std::true_type;
static_assert(std::is_integral<Limit>::value
or (is_parameter_t<Limit>::value and is_numeric_t<Limit>::value), "limit requires an integral value or integral parameter");
template<typename Db> void set(std::size_t limit)
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_limit, "limit not supported by current database");
os << " LIMIT " << _limit;
}
size_t _set_parameter_index(size_t index)
{ {
index = set_parameter_index(_limit, index); _limit = limit;
return index;
} }
Limit _limit; std::size_t _limit;
}; };
struct dynamic_limit_t template<typename Context>
{ struct interpreter_t<Context, dynamic_limit_t>
using _is_limit = std::true_type;
using _is_dynamic = std::true_type;
void set(std::size_t limit)
{
_limit = limit;
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{ {
static_assert(Db::_supports_limit, "limit not supported by current database"); using T = dynamic_limit_t;
if (_limit > 0)
os << " LIMIT " << _limit; static Context& _(const T& t, Context& context)
} {
if (t._limit > 0)
context << " LIMIT " << t._limit;
return context;
}
};
}
std::size_t _limit;
};
} }
#endif #endif

View File

@ -27,33 +27,38 @@
#ifndef SQLPP_NAMED_SERIALIZABLE_H #ifndef SQLPP_NAMED_SERIALIZABLE_H
#define SQLPP_NAMED_SERIALIZABLE_H #define SQLPP_NAMED_SERIALIZABLE_H
#include <ostream>
#include <vector>
#include <memory> #include <memory>
#include <sqlpp11/serializer.h>
#include <sqlpp11/parameter_list.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace vendor
{ {
template<typename Db> template<typename Db>
struct named_serializable_t struct named_interpretable_t
{ {
template<typename T, using _context_t = typename Db::_context_t;
typename std::enable_if<not std::is_same<typename std::decay<T>::type, named_serializable_t<Db>>::value, int>::type = 0 // prevent accidental overload for copy constructor
> template<typename T>
named_serializable_t(T&& t): named_interpretable_t(T t):
_impl(std::make_shared<_impl_t<typename std::decay<T>::type>>(std::forward<T>(t))) _impl(std::make_shared<_impl_t<typename std::decay<T>::type>>(t))
{} {}
named_serializable_t(const named_serializable_t&) = default; named_interpretable_t(const named_interpretable_t&) = default;
named_serializable_t(named_serializable_t&&) = default; named_interpretable_t(named_interpretable_t&&) = default;
named_serializable_t& operator=(const named_serializable_t&) = default; named_interpretable_t& operator=(const named_interpretable_t&) = default;
named_serializable_t& operator=(named_serializable_t&&) = default; named_interpretable_t& operator=(named_interpretable_t&&) = default;
~named_serializable_t() = default; ~named_interpretable_t() = default;
void serialize(std::ostream& os, Db& db) const sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const
{ {
_impl->serialize(os, db); return _impl->interpret(context);
}
_context_t& interpret(_context_t& context) const
{
return _impl->interpret(context);
} }
std::string _get_name() const std::string _get_name() const
@ -64,13 +69,15 @@ namespace sqlpp
private: private:
struct _impl_base struct _impl_base
{ {
virtual void serialize(std::ostream& os, Db& db) const = 0; virtual sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const = 0;
virtual _context_t& interpret(_context_t& context) const = 0;
virtual std::string _get_name() const = 0; virtual std::string _get_name() const = 0;
}; };
template<typename T> template<typename T>
struct _impl_t: public _impl_base struct _impl_t: public _impl_base
{ {
static_assert(not make_parameter_list_t<T>::type::size::value, "parameters not supported in dynamic query parts");
_impl_t(const T& t): _impl_t(const T& t):
_t(t) _t(t)
{} {}
@ -79,9 +86,16 @@ namespace sqlpp
_t(std::move(t)) _t(std::move(t))
{} {}
void serialize(std::ostream& os, Db& db) const sqlpp::serializer_t& interpret(sqlpp::serializer_t& context) const
{ {
_t.serialize(os, db); sqlpp::interpret(_t, context);
return context;
}
_context_t& interpret(_context_t& context) const
{
sqlpp::interpret(_t, context);
return context;
} }
std::string _get_name() const std::string _get_name() const
@ -94,7 +108,20 @@ namespace sqlpp
std::shared_ptr<const _impl_base> _impl; std::shared_ptr<const _impl_base> _impl;
}; };
template<typename Context, typename Database>
struct interpreter_t<Context, named_interpretable_t<Database>>
{
using T = named_interpretable_t<Database>;
static Context& _(const T& t, Context& context)
{
t.interpret(context);
return context;
}
};
} }
} }
#endif #endif

View File

@ -28,18 +28,30 @@
#define SQLPP_NOOP_H #define SQLPP_NOOP_H
#include <type_traits> #include <type_traits>
#include <sqlpp11/vendor/noop_fwd.h>
namespace sqlpp namespace sqlpp
{ {
struct noop namespace vendor
{ {
template<typename Db> struct noop
void serialize(std::ostream& os, Db& db) const {
{} };
};
template<typename T> template<typename Context>
struct is_noop: std::is_same<T, noop> {}; struct interpreter_t<Context, noop>
{
using T = noop;
static Context& _(const T& t, Context& context)
{
return context;
}
};
template<typename T>
struct is_noop: std::is_same<T, noop> {};
}
} }
#endif #endif

View File

@ -29,9 +29,12 @@
namespace sqlpp namespace sqlpp
{ {
struct noop; namespace vendor
{
struct noop;
template<typename T> template<typename T>
struct is_noop; struct is_noop;
}
} }
#endif #endif

View File

@ -27,56 +27,61 @@
#ifndef SQLPP_OFFSET_H #ifndef SQLPP_OFFSET_H
#define SQLPP_OFFSET_H #define SQLPP_OFFSET_H
#include <ostream>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Offset> namespace vendor
struct offset_t {
template<typename Offset>
struct offset_t
{
using _is_offset = std::true_type;
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
Offset _offset;
};
template<typename Context, typename Offset>
struct interpreter_t<Context, offset_t<Offset>>
{
using T = offset_t<Offset>;
static Context& _(const T& t, Context& context)
{
context << " OFFSET ";
interpret(t._offset, context);
return context;
}
};
struct dynamic_offset_t
{ {
using _is_offset = std::true_type; using _is_offset = std::true_type;
using _parameter_tuple_t = std::tuple<Offset>; using _is_dynamic = std::true_type;
static_assert(std::is_integral<Offset>::value
or (is_parameter_t<Offset>::value and is_numeric_t<Offset>::value), "offset requires an integral value or integral parameter");
void set(std::size_t offset)
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << " OFFSET " << _offset;
}
size_t _set_parameter_index(size_t index)
{ {
index = set_parameter_index(_offset, index); _offset = offset;
return index;
} }
Offset _offset; std::size_t _offset;
}; };
struct dynamic_offset_t template<typename Context>
{ struct interpreter_t<Context, dynamic_offset_t>
using _is_offset = std::true_type;
using _is_dynamic = std::true_type;
void set(std::size_t offset)
{
_offset = offset;
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{ {
if (_offset > 0) using T = dynamic_offset_t;
os << " OFFSET " << _offset;
}
std::size_t _offset; static Context& _(const T& t, Context& context)
}; {
if (t._offset > 0)
context << " OFFSET " << t._offset;
return context;
}
};
}
} }
#endif #endif

88
include/sqlpp11/vendor/order_by.h vendored Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_ORDER_BY_H
#define SQLPP_ORDER_BY_H
#include <tuple>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database,typename... Expr>
struct order_by_t
{
using _is_order_by = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Expr...>;
// check for at least one order expression
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one sort-order expression required in order_by()");
// check for duplicate order expressions
static_assert(not ::sqlpp::detail::has_duplicates<Expr...>::value, "at least one duplicate argument detected in order_by()");
// check for invalid order expressions
using _valid_expressions = typename ::sqlpp::detail::make_set_if<is_sort_order_t, Expr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not a sort order expression in order_by()");
template<typename E>
void add(E&& expr)
{
static_assert(is_sort_order_t<typename std::decay<E>::type>::value, "order_by arguments require to be sort-order expressions");
_dynamic_expressions.push_back(std::forward<E>(expr));
}
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
template<typename Context, typename Database, typename... Expr>
struct interpreter_t<Context, order_by_t<Database, Expr...>>
{
using T = order_by_t<Database, Expr...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
return context;
context << " ORDER BY ";
interpret_tuple(t._expressions, ',', context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
context << ',';
interpret_list(t._dynamic_expressions, ',', context);
return context;
}
};
}
}
#endif

View File

@ -0,0 +1,204 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_SELECT_EXPRESSION_LIST_H
#define SQLPP_SELECT_EXPRESSION_LIST_H
#include <tuple>
#include <sqlpp11/result_row.h>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/table.h>
#include <sqlpp11/vendor/expression_fwd.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/vendor/field.h>
#include <sqlpp11/vendor/select_pseudo_table.h>
#include <sqlpp11/vendor/named_interpretable.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/detail/set.h>
namespace sqlpp
{
namespace detail
{
template<typename... Rest>
struct get_first_argument_if_unique
{
using _value_type = no_value_t;
struct _name_t {};
};
template<typename T>
struct get_first_argument_if_unique<T>
{
using _value_type = typename T::_value_type;
using _name_t = typename T::_name_t;
};
}
namespace vendor
{
template<typename Db>
struct dynamic_select_expression_list
{
using _names_t = std::vector<std::string>;
std::vector<vendor::named_interpretable_t<Db>> _dynamic_expressions;
_names_t _dynamic_expression_names;
template<typename Expr>
void push_back(Expr&& expr)
{
_dynamic_expression_names.push_back(std::decay<Expr>::type::_name_t::_get_name());
_dynamic_expressions.emplace_back(std::forward<Expr>(expr));
}
bool empty() const
{
return _dynamic_expressions.empty();
}
};
template<>
struct dynamic_select_expression_list<void>
{
struct _names_t {};
_names_t _dynamic_expression_names;
template<typename T>
void push_back(const T&) {}
static constexpr bool empty()
{
return true;
}
};
template<typename Context, typename Db>
struct interpreter_t<Context, dynamic_select_expression_list<Db>>
{
using T = dynamic_select_expression_list<Db>;
static Context& _(const T& t, Context& context)
{
for (const auto column : t._dynamic_expressions)
{
interpret(column, context);
}
return context;
}
};
template<typename Context>
struct interpreter_t<Context, dynamic_select_expression_list<void>>
{
using T = dynamic_select_expression_list<void>;
static Context& _(const T& t, Context& context)
{
return context;
}
};
template<typename Database, typename T>
struct select_expression_list_t
{
static_assert(::sqlpp::detail::wrong<Database, T>::value, "invalid template argument for select_expression_list");
};
template<typename Database, typename... NamedExpr>
struct select_expression_list_t<Database, std::tuple<NamedExpr...>>
{
using _is_select_expression_list = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<NamedExpr...>;
// check for duplicate select expressions
static_assert(not ::sqlpp::detail::has_duplicates<NamedExpr...>::value, "at least one duplicate argument detected");
// check for invalid select expressions
template<typename T>
struct is_valid_expression_t: public std::integral_constant<bool, is_named_expression_t<T>::value or is_multi_column_t<T>::value> {};
using _valid_expressions = typename ::sqlpp::detail::make_set_if<is_valid_expression_t, NamedExpr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(NamedExpr), "at least one argument is not a named expression");
// check for duplicate select expression names
static_assert(not ::sqlpp::detail::has_duplicates<typename NamedExpr::_name_t...>::value, "at least one duplicate name detected");
// provide type information for sub-selects that are used as expressions
struct _column_type {};
struct _value_type: ::sqlpp::detail::get_first_argument_if_unique<NamedExpr...>::_value_type
{
using _is_expression = typename std::conditional<sizeof...(NamedExpr) == 1, std::true_type, std::false_type>::type;
using _is_named_expression = typename std::conditional<sizeof...(NamedExpr) == 1, std::true_type, std::false_type>::type;
using _is_alias = std::false_type;
};
using _name_t = typename ::sqlpp::detail::get_first_argument_if_unique<NamedExpr...>::_name_t;
using _result_row_t = typename std::conditional<_is_dynamic::value,
dynamic_result_row_t<make_field_t<NamedExpr>...>,
result_row_t<make_field_t<NamedExpr>...>>::type;
using _dynamic_names_t = typename dynamic_select_expression_list<Database>::_names_t;
template <typename Select>
using _pseudo_table_t = select_pseudo_table_t<Select, NamedExpr...>;
template <typename Db>
using _dynamic_t = select_expression_list_t<Db, std::tuple<NamedExpr...>>;
template<typename Expr>
void add(Expr&& namedExpr)
{
static_assert(is_named_expression_t<typename std::decay<Expr>::type>::value, "select() arguments require to be named expressions");
static_assert(_is_dynamic::value, "cannot add columns to a non-dynamic column list");
_dynamic_expressions.push_back(std::forward<Expr>(namedExpr));
}
_parameter_tuple_t _expressions;
dynamic_select_expression_list<Database> _dynamic_expressions;
};
template<typename Context, typename Database, typename... NamedExpr>
struct interpreter_t<Context, select_expression_list_t<Database, NamedExpr...>>
{
using T = select_expression_list_t<Database, NamedExpr...>;
static Context& _(const T& t, Context& context)
{
// check for at least one expression
static_assert(T::_is_dynamic::value or sizeof...(NamedExpr), "at least one select expression required");
interpret_tuple(t._expressions, ',', context);
if (sizeof...(NamedExpr) and not t._dynamic_expressions.empty())
context << ',';
interpret(t._dynamic_expressions, context);
return context;
}
};
}
}
#endif

View File

@ -30,9 +30,8 @@
#include <sqlpp11/select_fwd.h> #include <sqlpp11/select_fwd.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h> #include <sqlpp11/detail/set.h>
#include <sqlpp11/detail/serialize_tuple.h> #include <sqlpp11/vendor/interpret_tuple.h>
#include <tuple> #include <tuple>
#include <ostream>
namespace sqlpp namespace sqlpp
{ {
@ -43,67 +42,104 @@ namespace sqlpp
{ {
using _is_select_flag = std::true_type; using _is_select_flag = std::true_type;
}; };
template<typename Db>
void serialize(std::ostream& os, const Db&) const
{
os << "ALL";
}
}; };
static constexpr all_t all = {}; static constexpr all_t all = {};
namespace vendor
{
template<typename Context>
struct interpreter_t<Context, all_t>
{
static Context& _(const all_t&, Context& context)
{
context << "ALL";
return context;
}
};
}
struct distinct_t struct distinct_t
{ {
struct _value_type struct _value_type
{ {
using _is_select_flag = std::true_type; using _is_select_flag = std::true_type;
}; };
template<typename Db>
void serialize(std::ostream& os, const Db&) const
{
os << "DISTINCT";
}
}; };
static constexpr distinct_t distinct = {}; static constexpr distinct_t distinct = {};
namespace vendor
{
template<typename Context>
struct interpreter_t<Context, distinct_t>
{
static Context& _(const distinct_t&, Context& context)
{
context << "DISTINCT";
return context;
}
};
}
struct straight_join_t struct straight_join_t
{ {
struct _value_type struct _value_type
{ {
using _is_select_flag = std::true_type; using _is_select_flag = std::true_type;
}; };
template<typename Db>
void serialize(std::ostream& os, const Db&) const
{
os << "STRAIGHT_JOIN";
}
}; };
static constexpr straight_join_t straight_join = {}; static constexpr straight_join_t straight_join = {};
// select_flag_list_t namespace vendor
template<typename... Flag> {
struct select_flag_list_t<std::tuple<Flag...>> template<typename Context>
{ struct interpreter_t<Context, straight_join_t>
// check for duplicate order expressions {
static_assert(not detail::has_duplicates<Flag...>::value, "at least one duplicate argument detected in select flag list"); static Context& _(const straight_join_t&, Context& context)
// check for invalid order expressions
using _valid_flags = typename detail::make_set_if<is_select_flag_t, Flag...>::type;
static_assert(_valid_flags::size::value == sizeof...(Flag), "at least one argument is not a select flag in select flag list");
using _is_select_flag_list = std::true_type;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{ {
detail::serialize_tuple(os, db, _flags, ' '); context << "STRAIGHT_JOIN";
os << ' '; return context;
} }
};
}
std::tuple<Flag...> _flags; namespace vendor
}; {
template<typename T>
struct select_flag_list_t
{
static_assert(detail::wrong<T>::value, "invalid argument for select_flag_list");
};
// select_flag_list_t
template<typename... Flag>
struct select_flag_list_t<std::tuple<Flag...>>
{
// check for duplicate order expressions
static_assert(not detail::has_duplicates<Flag...>::value, "at least one duplicate argument detected in select flag list");
// check for invalid order expressions
using _valid_flags = typename detail::make_set_if<is_select_flag_t, Flag...>::type;
static_assert(_valid_flags::size::value == sizeof...(Flag), "at least one argument is not a select flag in select flag list");
using _is_select_flag_list = std::true_type;
std::tuple<Flag...> _flags;
};
template<typename Context, typename... Flag>
struct interpreter_t<Context, select_flag_list_t<std::tuple<Flag...>>>
{
using T = select_flag_list_t<std::tuple<Flag...>>;
static Context& _(const T& t, Context& context)
{
interpret_tuple(t._flags, ' ', context);
if (sizeof...(Flag))
context << ' ';
return context;
}
};
}
} }

View File

@ -44,11 +44,12 @@ namespace sqlpp
typename Select, typename Select,
typename... NamedExpr typename... NamedExpr
> >
struct select_pseudo_table_t: public sqlpp::table_base_t<select_pseudo_table_t< struct select_pseudo_table_t: public sqlpp::table_t<select_pseudo_table_t<
Select, Select,
NamedExpr...>, select_column_spec_t<NamedExpr>...> NamedExpr...>, select_column_spec_t<NamedExpr>...>
{ {
using _value_type = no_value_t; using _value_type = no_value_t;
using _is_pseudo_table = std::true_type;
select_pseudo_table_t(const Select& select): select_pseudo_table_t(const Select& select):
_select(select) _select(select)
@ -66,16 +67,24 @@ namespace sqlpp
select_pseudo_table_t& operator=(select_pseudo_table_t&& rhs) = default; select_pseudo_table_t& operator=(select_pseudo_table_t&& rhs) = default;
~select_pseudo_table_t() = default; ~select_pseudo_table_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_select_as_table, "select as table not supported by current database");
_select.serialize(os, db);
}
Select _select; Select _select;
}; };
namespace vendor
{
template<typename Context, typename Select, typename... NamedExpr>
struct interpreter_t<Context, select_pseudo_table_t<Select, NamedExpr...>>
{
using T = select_pseudo_table_t<Select, NamedExpr...>;
static Context& _(const T& t, Context& context)
{
interpret(t._select, context);
return context;
}
};
}
} }
#endif #endif

90
include/sqlpp11/vendor/update_list.h vendored Normal file
View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_UPDATE_LIST_H
#define SQLPP_UPDATE_LIST_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... Assignments>
struct update_list_t
{
using _is_update_list = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Assignments...>;
// check for at least one order expression
static_assert(_is_dynamic::value or sizeof...(Assignments), "at least one assignment expression required in set()");
// check for duplicate assignments
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
// check for invalid assignments
using _assignment_set = typename ::sqlpp::detail::make_set_if<is_assignment_t, Assignments...>::type;
static_assert(_assignment_set::size::value == sizeof...(Assignments), "at least one argument is not an assignment in set()");
// check for prohibited assignments
using _prohibited_assignment_set = typename ::sqlpp::detail::make_set_if<must_not_update_t, typename Assignments::column_type...>::type;
static_assert(_prohibited_assignment_set::size::value == 0, "at least one assignment is prohibited by its column definition in set()");
template<typename Assignment>
void add(Assignment&& assignment)
{
static_assert(is_assignment_t<typename std::decay<Assignment>::type>::value, "set() arguments require to be assigments");
static_assert(not must_not_update_t<typename std::decay<Assignment>::type::column_type>::value, "set() argument must not be updated");
_dynamic_assignments.emplace_back(std::forward<Assignment>(assignment));
}
_parameter_tuple_t _assignments;
typename vendor::interpretable_list_t<Database> _dynamic_assignments;
};
template<typename Context, typename Database, typename... Assignments>
struct interpreter_t<Context, update_list_t<Database, Assignments...>>
{
using T = update_list_t<Database, Assignments...>;
static Context& _(const T& t, Context& context)
{
context << " SET ";
interpret_tuple(t._assignments, ",", context);
if (sizeof...(Assignments) and not t._dynamic_assignments.empty())
context << ',';
interpret_list(t._dynamic_assignments, ',', context);
return context;
}
};
}
}
#endif

87
include/sqlpp11/vendor/using.h vendored Normal file
View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_USING_H
#define SQLPP_USING_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/interpret_tuple.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... Table>
struct using_t
{
using _is_using = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Table...>;
static_assert(_is_dynamic::value or sizeof...(Table), "at least one table argument required in using()");
// check for duplicate arguments
static_assert(not ::sqlpp::detail::has_duplicates<Table...>::value, "at least one duplicate argument detected in using()");
// check for invalid arguments
using _valid_expressions = typename ::sqlpp::detail::make_set_if<is_table_t, Table...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Table), "at least one argument is not an table in using()");
template<typename T>
void add(T&& table)
{
static_assert(is_table_t<typename std::decay<T>::type>::value, "using() arguments require to be tables");
_dynamic_tables.emplace_back(std::forward<T>(table));
}
_parameter_tuple_t _tables;
vendor::interpretable_list_t<Database> _dynamic_tables;
};
template<typename Context, typename Database, typename... Table>
struct interpreter_t<Context, using_t<Database, Table...>>
{
using T = using_t<Database, Table...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Table) == 0 and t._dynamic_tables.empty())
return context;
context << " USING ";
interpret_tuple(t._tables, ',', context);
if (sizeof...(Table) and not t._dynamic_tables.empty())
context << ',';
interpret_list(t._dynamic_tables, ',', context);
return context;
}
};
}
}
#endif

41
include/sqlpp11/vendor/value_type.h vendored Normal file
View File

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

88
include/sqlpp11/vendor/where.h vendored Normal file
View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_WHERE_H
#define SQLPP_WHERE_H
#include <ostream>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/parameter_list.h>
namespace sqlpp
{
namespace vendor
{
template<typename Database, typename... Expr>
struct where_t
{
using _is_where = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Expr...>;
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in where()");
using _valid_expressions = typename sqlpp::detail::make_set_if<is_expression_t, Expr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in where()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
template<typename E>
void add(E&& expr)
{
static_assert(is_expression_t<typename std::decay<E>::type>::value, "invalid expression argument in add_where()");
_dynamic_expressions.emplace_back(std::forward<E>(expr));
}
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
template<typename Context, typename Database, typename... Expr>
struct interpreter_t<Context, where_t<Database, Expr...>>
{
using T = where_t<Database, Expr...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
return context;
context << " WHERE ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
}
}
#endif

View File

@ -27,8 +27,8 @@
#ifndef SQLPP_DETAIL_WRAP_OPERAND_H #ifndef SQLPP_DETAIL_WRAP_OPERAND_H
#define SQLPP_DETAIL_WRAP_OPERAND_H #define SQLPP_DETAIL_WRAP_OPERAND_H
#include <ostream> #include <string>
#include <type_traits> #include <sqlpp11/vendor/interpreter.h>
namespace sqlpp namespace sqlpp
{ {
@ -38,100 +38,99 @@ namespace sqlpp
struct integral; struct integral;
struct floating_point; struct floating_point;
struct text; struct text;
}
struct bool_operand namespace vendor
{
struct boolean_operand
{ {
static constexpr bool _is_expression = true; static constexpr bool _is_expression = true;
using _value_type = boolean; using _value_type = detail::boolean;
bool_operand(bool t): _t(t) {}
bool_operand(const bool_operand&) = default;
bool_operand(bool_operand&&) = default;
bool_operand& operator=(const bool_operand&) = default;
bool_operand& operator=(bool_operand&&) = default;
~bool_operand() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << _t;
}
bool _is_trivial() const { return _t == false; } bool _is_trivial() const { return _t == false; }
bool _t; bool _t;
}; };
template<typename Context>
struct interpreter_t<Context, boolean_operand>
{
using Operand = boolean_operand;
static Context& _(const Operand& t, Context& context)
{
context << t._t;
return context;
}
};
template<typename T> template<typename T>
struct integral_operand struct integral_operand
{ {
static constexpr bool _is_expression = true; static constexpr bool _is_expression = true;
using _value_type = integral; using _value_type = detail::integral;
integral_operand(T t): _t(t) {}
integral_operand(const integral_operand&) = default;
integral_operand(integral_operand&&) = default;
integral_operand& operator=(const integral_operand&) = default;
integral_operand& operator=(integral_operand&&) = default;
~integral_operand() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << _t;
}
bool _is_trivial() const { return _t == 0; } bool _is_trivial() const { return _t == 0; }
T _t; T _t;
}; };
template<typename Context, typename T>
struct interpreter_t<Context, integral_operand<T>>
{
using Operand = integral_operand<T>;
static Context& _(const Operand& t, Context& context)
{
context << t._t;
return context;
}
};
template<typename T> template<typename T>
struct floating_point_operand struct floating_point_operand
{ {
static constexpr bool _is_expression = true; static constexpr bool _is_expression = true;
using _value_type = floating_point; using _value_type = detail::floating_point;
floating_point_operand(T t): _t(t) {}
floating_point_operand(const floating_point_operand&) = default;
floating_point_operand(floating_point_operand&&) = default;
floating_point_operand& operator=(const floating_point_operand&) = default;
floating_point_operand& operator=(floating_point_operand&&) = default;
~floating_point_operand() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << _t;
}
bool _is_trivial() const { return _t == 0; } bool _is_trivial() const { return _t == 0; }
T _t; T _t;
}; };
template<typename T> template<typename Context, typename T>
struct text_operand struct interpreter_t<Context, floating_point_operand<T>>
{ {
static constexpr bool _is_expression = true; using Operand = floating_point_operand<T>;
using _value_type = text;
text_operand(const T& t): _t(t) {} static Context& _(const Operand& t, Context& context)
text_operand(const text_operand&) = default; {
text_operand(text_operand&&) = default; context << t._t;
text_operand& operator=(const text_operand&) = default; return context;
text_operand& operator=(text_operand&&) = default; }
~text_operand() = default; };
template<typename Db> struct text_operand
void serialize(std::ostream& os, Db& db) const {
{ static constexpr bool _is_expression = true;
os << '\'' << db.escape(_t) << '\''; using _value_type = detail::text;
}
bool _is_trivial() const { return _t.empty(); } bool _is_trivial() const { return _t.empty(); }
std::string _t; std::string _t;
};
template<typename Context>
struct interpreter_t<Context, text_operand>
{
using Operand = text_operand;
static Context& _(const Operand& t, Context& context)
{
context << '\'' << context.escape(t._t) << '\'';
return context;
}
}; };
template<typename T, typename Enable = void> template<typename T, typename Enable = void>
@ -143,7 +142,7 @@ namespace sqlpp
template<> template<>
struct wrap_operand<bool, void> struct wrap_operand<bool, void>
{ {
using type = bool_operand; using type = boolean_operand;
}; };
template<typename T> template<typename T>
@ -161,7 +160,7 @@ namespace sqlpp
template<typename T> template<typename T>
struct wrap_operand<T, typename std::enable_if<std::is_convertible<T, std::string>::value>::type> struct wrap_operand<T, typename std::enable_if<std::is_convertible<T, std::string>::value>::type>
{ {
using type = text_operand<T>; using type = text_operand;
}; };
} }
} }

View File

@ -47,7 +47,7 @@ namespace sqlpp
}; };
} }
struct verbatim_table_t: public sqlpp::table_base_t<verbatim_table_t, detail::unusable_pseudo_column_t> struct verbatim_table_t: public sqlpp::table_t<verbatim_table_t, detail::unusable_pseudo_column_t>
{ {
using _value_type = no_value_t; using _value_type = no_value_t;
@ -62,15 +62,25 @@ namespace sqlpp
verbatim_table_t& operator=(verbatim_table_t&& rhs) = default; verbatim_table_t& operator=(verbatim_table_t&& rhs) = default;
~verbatim_table_t() = default; ~verbatim_table_t() = default;
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
os << _name;
}
std::string _name; std::string _name;
}; };
namespace vendor
{
template<typename Context>
struct interpreter_t<Context, verbatim_table_t>
{
using T = verbatim_table_t;
static Context& _(const T& t, Context& context)
{
context << t._name;
return context;
}
};
}
verbatim_table_t verbatim_table(std::string name) verbatim_table_t verbatim_table(std::string name)
{ {
return { name }; return { name };

View File

@ -1,83 +0,0 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_WHERE_H
#define SQLPP_WHERE_H
#include <ostream>
#include <sqlpp11/select_fwd.h>
#include <sqlpp11/expression.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/set.h>
#include <sqlpp11/detail/serialize_tuple.h>
#include <sqlpp11/detail/serializable_list.h>
#include <sqlpp11/parameter_list.h>
namespace sqlpp
{
template<typename Database, typename... Expr>
struct where_t
{
using _is_where = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Expr...>;
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in where()");
using _valid_expressions = typename detail::make_set_if<is_expression_t, Expr...>::type;
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in where()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
static_assert(not _parameter_list_t::_contains_trivial_value_is_null_t::value, "must not use trivial_value_is_null in parameters of where expression, use where_parameter() instead of parameter() to turn off automatic conversion");
template<typename E>
void add(E&& expr)
{
static_assert(is_expression_t<typename std::decay<E>::type>::value, "invalid expression argument in add_where()");
_dynamic_expressions.emplace_back(std::forward<E>(expr));
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
if (sizeof...(Expr) == 0 and _dynamic_expressions.empty())
return;
os << " WHERE ";
detail::serialize_tuple(os, db, _expressions, " AND ");
_dynamic_expressions.serialize(os, db, " AND ", sizeof...(Expr) == 0);
}
size_t _set_parameter_index(size_t index)
{
index = set_parameter_index(_expressions, index);
return index;
}
_parameter_tuple_t _expressions;
detail::serializable_list<Database> _dynamic_expressions;
};
}
#endif

View File

@ -3,6 +3,7 @@ macro (build_and_run arg)
add_test(${arg} ${arg}) add_test(${arg} ${arg})
endmacro () endmacro ()
build_and_run(InterpretTest)
build_and_run(InsertTest) build_and_run(InsertTest)
build_and_run(RemoveTest) build_and_run(RemoveTest)
build_and_run(UpdateTest) build_and_run(UpdateTest)

View File

@ -25,6 +25,7 @@
#include "TabSample.h" #include "TabSample.h"
#include "MockDb.h" #include "MockDb.h"
#include <sqlpp11/alias_provider.h>
#include <sqlpp11/select.h> #include <sqlpp11/select.h>
#include <sqlpp11/functions.h> #include <sqlpp11/functions.h>
#include <sqlpp11/connection.h> #include <sqlpp11/connection.h>
@ -32,7 +33,7 @@
#include <iostream> #include <iostream>
DbMock db = {}; DbMock db = {};
SQLPP_ALIAS_PROVIDER_GENERATOR(kaesekuchen); SQLPP_ALIAS_PROVIDER(kaesekuchen);
int main() int main()
{ {

View File

@ -30,6 +30,7 @@
#include <iostream> #include <iostream>
DbMock db; DbMock db;
DbMock::_context_t printer(std::cerr);
int main() int main()
{ {
@ -56,11 +57,11 @@ int main()
static_assert(sqlpp::is_regular<T>::value, "type requirement"); static_assert(sqlpp::is_regular<T>::value, "type requirement");
} }
insert_into(t).serialize(std::cerr, db); std::cerr << "\n"; interpret(insert_into(t), printer).flush();
insert_into(t).set(t.beta = "kirschauflauf").serialize(std::cerr, db); std::cerr << "\n"; interpret(insert_into(t).set(t.beta = "kirschauflauf"), printer).flush();
auto i = dynamic_insert_into(db, t).dynamic_set(); auto i = dynamic_insert_into(db, t).dynamic_set();
i = i.add_set(t.beta = "kirschauflauf"); i = i.add_set(t.beta = "kirschauflauf");
i.serialize(std::cerr, db); std::cerr << "\n"; interpret(i, printer).flush();
return 0; return 0;
} }

116
tests/InterpretTest.cpp Normal file
View File

@ -0,0 +1,116 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "TabSample.h"
#include "MockDb.h"
#include <sqlpp11/alias_provider.h>
#include <sqlpp11/insert.h>
#include <sqlpp11/select.h>
#include <sqlpp11/update.h>
#include <sqlpp11/remove.h>
#include <sqlpp11/functions.h>
#include <iostream>
DbMock db = {};
DbMock::_context_t printer(std::cerr);
SQLPP_ALIAS_PROVIDER(kaesekuchen);
int main()
{
TabSample t;
interpret(t.alpha, printer).flush();
interpret(-t.alpha, printer).flush();
interpret(+t.alpha, printer).flush();
interpret(-(t.alpha + 7), printer).flush();
interpret(t.alpha = 0, printer).flush();
interpret(t.alpha = sqlpp::tvin(0), printer).flush();
interpret(t.alpha == 0, printer).flush();
interpret(t.alpha == sqlpp::tvin(0), printer).flush();
interpret(t.alpha != 0, printer).flush();
interpret(t.gamma != sqlpp::tvin(false), printer).flush();
interpret(t.alpha == 7, printer).flush();
interpret(t.beta + "kaesekuchen", printer).flush();
interpret(select(sqlpp::distinct, t.alpha, t.beta), printer).flush();
interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t), printer).flush();
interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3), printer).flush();
interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma), printer).flush();
interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")), printer).flush();
interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()), printer).flush();
interpret(select(sqlpp::distinct, t.alpha, t.beta).from(t).where(t.alpha == 3).group_by(t.gamma).having(t.beta.like("%kuchen")).order_by(t.beta.asc()).limit(17).offset(3), printer).flush();
interpret(parameter(t.alpha), printer).flush();
interpret(t.alpha == parameter(t.alpha), printer).flush();
interpret(t.alpha == parameter(t.alpha) and (t.beta + "gimmick").like(parameter(t.beta)), printer).flush();
interpret(insert_into(t), printer).flush();
interpret(insert_into(t).default_values(), printer).flush();
interpret(insert_into(t).set(t.gamma = true), printer).flush();
interpret(insert_into(t).set(t.gamma = sqlpp::tvin(false)), printer).flush();
interpret(update(t), printer).flush();
interpret(update(t).set(t.gamma = true), printer).flush();
interpret(update(t).set(t.gamma = true).where(t.beta.in("kaesekuchen", "cheesecake")), printer).flush();
interpret(remove_from(t), printer).flush();
interpret(remove_from(t).where(t.alpha == sqlpp::tvin(0)), printer).flush();
interpret(remove_from(t).using_(t).where(t.alpha == sqlpp::tvin(0)), printer).flush();
// functions
sqlpp::interpret(sqlpp::value(7), printer).flush(); // FIXME: Why is the namespace specifier required?
interpret(sqlpp::verbatim<sqlpp::detail::integral>("irgendwas integrales"), printer).flush();
interpret(sqlpp::value_list(std::vector<int>({1,2,3,4,5,6,8})), printer).flush();
interpret(exists(select(t.alpha).from(t)), printer).flush();
interpret(any(select(t.alpha).from(t)), printer).flush();
interpret(some(select(t.alpha).from(t)), printer).flush();
interpret(count(t.alpha), printer).flush();
interpret(min(t.alpha), printer).flush();
interpret(max(t.alpha), printer).flush();
interpret(avg(t.alpha), printer).flush();
interpret(sum(t.alpha), printer).flush();
interpret(sqlpp::verbatim_table("whatever"), printer).flush();
// alias
interpret(t.as(t.alpha), printer).flush();
interpret(t.as(t.alpha).beta, printer).flush();
// select alias
interpret(select(t.alpha).from(t).where(t.beta > "kaesekuchen").as(t.gamma), printer).flush();
interpret(t.alpha.is_null(), printer).flush();
// join
interpret(t.inner_join(t.as(t.alpha)).on(t.beta == t.as(t.alpha).beta), printer).flush();
// multi_column
interpret(multi_column(t.alpha, t.alpha, (t.beta + "cake").as(t.gamma)), printer).flush();
// dynamic select
interpret(dynamic_select(db, t.alpha).dynamic_columns().add_column(t.beta), printer).flush();
return 0;
}

View File

@ -27,40 +27,14 @@
#define SQLPP_MOCK_DB_H #define SQLPP_MOCK_DB_H
#include <sqlpp11/connection.h> #include <sqlpp11/connection.h>
#include <sqlpp11/serializer.h>
class DbMock: public sqlpp::connection struct DbMock: public sqlpp::connection
{ {
public: struct _context_t : public sqlpp::serializer_t
// join types {
static constexpr bool _supports_inner_join = true; _context_t(std::ostream& os): sqlpp::serializer_t(os) {}
static constexpr bool _supports_outer_join = true; };
static constexpr bool _supports_left_outer_join = true;
static constexpr bool _supports_right_outer_join = true;
// functions
static constexpr bool _supports_avg = true;
static constexpr bool _supports_count = true;
static constexpr bool _supports_exists = true;
static constexpr bool _supports_like = true;
static constexpr bool _supports_in = true;
static constexpr bool _supports_max = true;
static constexpr bool _supports_min = true;
static constexpr bool _supports_not_in = true;
static constexpr bool _supports_sum = true;
// select
static constexpr bool _supports_group_by = true;
static constexpr bool _supports_having = true;
static constexpr bool _supports_limit = true;
static constexpr bool _supports_order_by = true;
static constexpr bool _supports_select_as_table = true;
static constexpr bool _supports_some = true;
static constexpr bool _supports_any = true;
static constexpr bool _use_concat_operator = true;
static constexpr bool _use_concat_function = true;
const std::string& escape(const std::string& text) { return text; }
}; };
#endif #endif

View File

@ -87,7 +87,7 @@ int main()
// Wonderful, now take a look at the parameter list of a select // Wonderful, now take a look at the parameter list of a select
{ {
auto s = select(all_of(t)).from(t).where(t.beta.like(where_parameter(t.beta)) and t.alpha == where_parameter(t.alpha) or t.gamma != parameter(t.gamma)); auto s = select(all_of(t)).from(t).where(t.beta.like(parameter(t.beta)) and t.alpha == parameter(t.alpha) or t.gamma != parameter(t.gamma));
using S = decltype(s); using S = decltype(s);
using T = sqlpp::make_parameter_list_t<S>::type; using T = sqlpp::make_parameter_list_t<S>::type;
T npl; T npl;

View File

@ -32,6 +32,7 @@
DbMock db; DbMock db;
DbMock::_context_t printer(std::cerr);
int main() int main()
{ {
@ -56,13 +57,13 @@ int main()
static_assert(sqlpp::is_regular<T>::value, "type requirement"); static_assert(sqlpp::is_regular<T>::value, "type requirement");
} }
remove_from(t).serialize(std::cerr, db); std::cerr << "\n"; interpret(remove_from(t), printer).flush();
remove_from(t).where(t.beta != "transparent").serialize(std::cerr, db); std::cerr << "\n"; interpret(remove_from(t).where(t.beta != "transparent"), printer).flush();
remove_from(t).using_(t).serialize(std::cerr, db); std::cerr << "\n"; interpret(remove_from(t).using_(t), printer).flush();
auto r = dynamic_remove_from(db, t).dynamic_using_().dynamic_where(); auto r = dynamic_remove_from(db, t).dynamic_using_().dynamic_where();
r = r.add_using_(t); r = r.add_using_(t);
r = r.add_where(t.beta != "transparent"); r = r.add_where(t.beta != "transparent");
r.serialize(std::cerr, db); std::cerr << "\n"; interpret(r, printer).flush();
return 0; return 0;
} }

View File

@ -26,6 +26,7 @@
#include "TabSample.h" #include "TabSample.h"
#include "MockDb.h" #include "MockDb.h"
#include "is_regular.h" #include "is_regular.h"
#include <sqlpp11/alias_provider.h>
#include <sqlpp11/select.h> #include <sqlpp11/select.h>
#include <sqlpp11/functions.h> #include <sqlpp11/functions.h>
#include <sqlpp11/connection.h> #include <sqlpp11/connection.h>
@ -33,6 +34,15 @@
#include <iostream> #include <iostream>
DbMock db = {}; DbMock db = {};
DbMock::_context_t printer(std::cerr);
namespace alias
{
SQLPP_ALIAS_PROVIDER(a);
SQLPP_ALIAS_PROVIDER(b);
SQLPP_ALIAS_PROVIDER(left);
SQLPP_ALIAS_PROVIDER(right);
}
int main() int main()
{ {
@ -59,7 +69,7 @@ int main()
// Test an alias of table // Test an alias of table
{ {
using T = decltype(t.as(sqlpp::alias::a)); using T = decltype(t.as(alias::a));
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_integral_t<T>::value, "type requirement"); static_assert(not sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<T>::value, "type requirement"); static_assert(not sqlpp::is_floating_point_t<T>::value, "type requirement");
@ -77,7 +87,7 @@ int main()
// Test an integral column of an alias of table // Test an integral column of an alias of table
{ {
using T = decltype(t.as(sqlpp::alias::a).alpha); using T = decltype(t.as(alias::a).alpha);
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_integral_t<T>::value, "type requirement"); static_assert(sqlpp::is_integral_t<T>::value, "type requirement");
static_assert(not sqlpp::is_floating_point_t<T>::value, "type requirement"); static_assert(not sqlpp::is_floating_point_t<T>::value, "type requirement");
@ -132,7 +142,7 @@ int main()
// Test a an alias of a numeric table column // Test a an alias of a numeric table column
{ {
using T = decltype(t.alpha.as(sqlpp::alias::a)); using T = decltype(t.alpha.as(alias::a));
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
@ -180,7 +190,7 @@ int main()
// Test a select of an alias of a single numeric table column // Test a select of an alias of a single numeric table column
{ {
using T = decltype(select(t.alpha.as(sqlpp::alias::a)).from(t)); using T = decltype(select(t.alpha.as(alias::a)).from(t));
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
@ -196,7 +206,7 @@ int main()
// Test an alias of a select of a single numeric table column // Test an alias of a select of a single numeric table column
{ {
using T = decltype(select(t.alpha).from(t).as(sqlpp::alias::b)); using T = decltype(select(t.alpha).from(t).as(alias::b));
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
@ -212,7 +222,7 @@ int main()
// Test the column of an alias of a select of an alias of a single numeric table column // Test the column of an alias of a select of an alias of a single numeric table column
{ {
using T = decltype(select(t.alpha.as(sqlpp::alias::a)).from(t).as(sqlpp::alias::b)); using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b));
static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement"); static_assert(not sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(not sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(not sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(not sqlpp::is_named_expression_t<T>::value, "type requirement");
@ -228,7 +238,7 @@ int main()
// Test the column of an alias of a select of a single numeric table column // Test the column of an alias of a select of a single numeric table column
{ {
using T = decltype(select(t.alpha).from(t).as(sqlpp::alias::b).alpha); using T = decltype(select(t.alpha).from(t).as(alias::b).alpha);
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
@ -244,7 +254,7 @@ int main()
// Test an alias of a select of an alias of a single numeric table column // Test an alias of a select of an alias of a single numeric table column
{ {
using T = decltype(select(t.alpha.as(sqlpp::alias::a)).from(t).as(sqlpp::alias::b).a); using T = decltype(select(t.alpha.as(alias::a)).from(t).as(alias::b).a);
static_assert(sqlpp::is_numeric_t<T>::value, "type requirement"); static_assert(sqlpp::is_numeric_t<T>::value, "type requirement");
static_assert(sqlpp::is_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_expression_t<T>::value, "type requirement");
static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement"); static_assert(sqlpp::is_named_expression_t<T>::value, "type requirement");
@ -269,22 +279,22 @@ int main()
// Test that select(all_of(tab)) is expanded in multi_column // Test that select(all_of(tab)) is expanded in multi_column
{ {
auto a = multi_column(sqlpp::alias::a, all_of(t)); auto a = multi_column(alias::a, all_of(t));
auto b = multi_column(sqlpp::alias::a, t.alpha, t.beta, t.gamma); auto b = multi_column(alias::a, t.alpha, t.beta, t.gamma);
static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by multi_column"); static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by multi_column");
} }
// Test that select(tab) is expanded in multi_column // Test that select(tab) is expanded in multi_column
{ {
auto a = multi_column(sqlpp::alias::a, all_of(t)); auto a = multi_column(alias::a, all_of(t));
auto b = multi_column(sqlpp::alias::a, t.alpha, t.beta, t.gamma); auto b = multi_column(alias::a, t.alpha, t.beta, t.gamma);
static_assert(std::is_same<decltype(a), decltype(b)>::value, "t has to be expanded by multi_column"); static_assert(std::is_same<decltype(a), decltype(b)>::value, "t has to be expanded by multi_column");
} }
// Test that a multicolumn is not a value // Test that a multicolumn is not a value
{ {
auto m = multi_column(sqlpp::alias::a, t.alpha, t.beta); auto m = multi_column(alias::a, t.alpha, t.beta);
auto a = select(m).from(t).as(sqlpp::alias::b).a; auto a = select(m).from(t).as(alias::b).a;
static_assert(not sqlpp::is_value_t<decltype(a)>::value, "a multi_column is not a value"); static_assert(not sqlpp::is_value_t<decltype(a)>::value, "a multi_column is not a value");
} }
@ -307,7 +317,7 @@ int main()
s = s.set_limit(30); s = s.set_limit(30);
s = s.set_limit(3); s = s.set_limit(3);
std::cerr << "------------------------\n"; std::cerr << "------------------------\n";
s.serialize(std::cerr, db); interpret(s, printer).flush();
std::cerr << "------------------------\n"; std::cerr << "------------------------\n";
using T = decltype(s); using T = decltype(s);
static_assert(sqlpp::is_regular<T>::value, "type requirement"); static_assert(sqlpp::is_regular<T>::value, "type requirement");
@ -316,18 +326,18 @@ int main()
// Test that select can be called with zero columns if it is used with dynamic columns. // Test that select can be called with zero columns if it is used with dynamic columns.
{ {
auto s = dynamic_select(db).dynamic_columns().add_column(t.alpha); auto s = dynamic_select(db).dynamic_columns().add_column(t.alpha);
s.serialize(std::cerr, db); std::cerr << "\n"; interpret(s, printer).flush();
} }
// Test that verbatim_table compiles // Test that verbatim_table compiles
{ {
auto s = select(t.alpha).from(sqlpp::verbatim_table("my_unknown_table")); auto s = select(t.alpha).from(sqlpp::verbatim_table("my_unknown_table"));
s.serialize(std::cerr, db); std::cerr << "\n"; interpret(s, printer).flush();
} }
static_assert(sqlpp::is_select_flag_t<decltype(sqlpp::all)>::value, "sqlpp::all has to be a select_flag"); static_assert(sqlpp::is_select_flag_t<decltype(sqlpp::all)>::value, "sqlpp::all has to be a select_flag");
using T = sqlpp::detail::wrap_operand<int>::type; using T = sqlpp::vendor::wrap_operand<int>::type;
static_assert(sqlpp::is_regular<T>::value, "type requirement"); static_assert(sqlpp::is_regular<T>::value, "type requirement");
static_assert(T::_is_expression, "T has to be an expression"); static_assert(T::_is_expression, "T has to be an expression");
static_assert(std::is_same<typename T::_value_type::_is_numeric, std::true_type>::value, "T has to be a numeric"); static_assert(std::is_same<typename T::_value_type::_is_numeric, std::true_type>::value, "T has to be a numeric");
@ -339,29 +349,28 @@ int main()
auto y = t.gamma and true and t.gamma; auto y = t.gamma and true and t.gamma;
!t.gamma; !t.gamma;
t.beta < "kaesekuchen"; t.beta < "kaesekuchen";
(t.beta + "hallenhalma").serialize(std::cerr, db); interpret(t.beta + "hallenhalma", printer).flush();
concat(t.beta, "hallenhalma").serialize(std::cerr, db);
static_assert(sqlpp::must_not_insert_t<decltype(t.alpha)>::value, "alpha must not be inserted"); static_assert(sqlpp::must_not_insert_t<decltype(t.alpha)>::value, "alpha must not be inserted");
t.alpha.serialize(std::cerr, db); interpret(t.alpha, printer).flush();
std::cerr << "\n" << sizeof(TabSample) << std::endl; std::cerr << "\n" << sizeof(TabSample) << std::endl;
static_assert(std::is_same<typename decltype(t.alpha)::_value_type::_is_named_expression, std::true_type>::value, "alpha should be a named expression"); static_assert(std::is_same<typename decltype(t.alpha)::_value_type::_is_named_expression, std::true_type>::value, "alpha should be a named expression");
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha)>::value, "alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t<decltype(t.alpha)>::value, "alpha should be a named expression");
static_assert(sqlpp::is_named_expression_t<decltype(t.alpha.as(sqlpp::alias::a))>::value, "an alias of alpha should be a named expression"); static_assert(sqlpp::is_named_expression_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be a named expression");
static_assert(sqlpp::is_alias_t<decltype(t.alpha.as(sqlpp::alias::a))>::value, "an alias of alpha should be an alias"); static_assert(sqlpp::is_alias_t<decltype(t.alpha.as(alias::a))>::value, "an alias of alpha should be an alias");
auto z = select(t.alpha) == 7; auto z = select(t.alpha) == 7;
auto l = t.as(sqlpp::alias::left); auto l = t.as(alias::left);
auto r = select(t.gamma.as(sqlpp::alias::a)).from(t).where(t.gamma == true).as(sqlpp::alias::right); auto r = select(t.gamma.as(alias::a)).from(t).where(t.gamma == true).as(alias::right);
static_assert(sqlpp::is_boolean_t<decltype(select(t.gamma).from(t))>::value, "select(bool) has to be a bool"); static_assert(sqlpp::is_boolean_t<decltype(select(t.gamma).from(t))>::value, "select(bool) has to be a bool");
select(sqlpp::distinct, sqlpp::straight_join, l.alpha, l.beta, select(r.a).from(r)) interpret(select(sqlpp::distinct, sqlpp::straight_join, l.alpha, l.beta, select(r.a).from(r))
.from(l, r) .from(l, r)
.where(t.beta == "hello world" and select(t.gamma).from(t))// .as(sqlpp::alias::right)) .where(t.beta == "hello world" and select(t.gamma).from(t))// .as(alias::right))
.group_by(l.gamma, r.a) .group_by(l.gamma, r.a)
.having(r.a != true) .having(r.a != true)
.order_by(l.beta.asc()) .order_by(l.beta.asc())
.limit(17) .limit(17)
.offset(3) .offset(3)
.as(sqlpp::alias::a) .as(alias::a)
.serialize(std::cerr, db); , printer).flush();
return 0; return 0;
} }

View File

@ -27,7 +27,7 @@
#ifndef SQLPP_TAB_SAMPLE_H #ifndef SQLPP_TAB_SAMPLE_H
#define SQLPP_TAB_SAMPLE_H #define SQLPP_TAB_SAMPLE_H
#include <sqlpp11/table_base.h> #include <sqlpp11/table.h>
#include <sqlpp11/column_types.h> #include <sqlpp11/column_types.h>
@ -72,7 +72,7 @@ namespace TabFoo_
}; };
} }
struct TabFoo: sqlpp::table_base_t< struct TabFoo: sqlpp::table_t<
TabFoo, TabFoo,
TabFoo_::Epsilon, TabFoo_::Epsilon,
TabFoo_::Omega TabFoo_::Omega
@ -166,7 +166,7 @@ namespace TabSample_
}; };
} }
struct TabSample: sqlpp::table_base_t< struct TabSample: sqlpp::table_t<
TabSample, TabSample,
TabSample_::Alpha, TabSample_::Alpha,
TabSample_::Beta, TabSample_::Beta,

View File

@ -30,6 +30,7 @@
#include "is_regular.h" #include "is_regular.h"
DbMock db; DbMock db;
DbMock::_context_t printer(std::cerr);
int main() int main()
{ {
@ -54,12 +55,12 @@ int main()
static_assert(sqlpp::is_regular<T>::value, "type requirement"); static_assert(sqlpp::is_regular<T>::value, "type requirement");
} }
update(t).serialize(std::cerr, db); std::cerr << "\n"; interpret(update(t), printer).flush();
update(t).set(t.gamma = false).serialize(std::cerr, db); std::cerr << "\n"; interpret(update(t).set(t.gamma = false), printer).flush();
update(t).set(t.gamma = false).where(t.beta != "transparent").serialize(std::cerr, db); std::cerr << "\n"; interpret(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).flush();
auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where(); auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where();
u = u.add_set(t.gamma = false); u = u.add_set(t.gamma = false);
u.serialize(std::cerr, db); std::cerr << "\n"; interpret(u, printer).flush();
return 0; return 0;
} }