Added missing interpreter specializations, especially for serializable

This commit is contained in:
rbock
2014-01-17 09:56:35 +01:00
parent 9826ef79e4
commit 93129be748
11 changed files with 227 additions and 75 deletions

View File

@@ -27,9 +27,9 @@
#ifndef SQLPP_NAMED_SERIALIZABLE_H
#define SQLPP_NAMED_SERIALIZABLE_H
#include <ostream>
#include <vector>
#include <memory>
#include <sqlpp11/serializer.h>
#include <sqlpp11/parameter_list.h>
namespace sqlpp
{
@@ -38,11 +38,11 @@ namespace sqlpp
template<typename Db>
struct named_serializable_t
{
template<typename 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
>
named_serializable_t(T&& t):
_impl(std::make_shared<_impl_t<typename std::decay<T>::type>>(std::forward<T>(t)))
using _context_t = typename Db::context;
template<typename T>
named_serializable_t(T t):
_impl(std::make_shared<_impl_t<typename std::decay<T>::type>>(t))
{}
named_serializable_t(const named_serializable_t&) = default;
@@ -51,9 +51,14 @@ namespace sqlpp
named_serializable_t& operator=(named_serializable_t&&) = default;
~named_serializable_t() = default;
void serialize(std::ostream& os, Db& db) const
sqlpp::serializer& interpret(sqlpp::serializer& 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
@@ -64,13 +69,15 @@ namespace sqlpp
private:
struct _impl_base
{
virtual void serialize(std::ostream& os, Db& db) const = 0;
virtual sqlpp::serializer& interpret(sqlpp::serializer& context) const = 0;
virtual _context_t& interpret(_context_t& context) const = 0;
virtual std::string _get_name() const = 0;
};
template<typename T>
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):
_t(t)
{}
@@ -79,9 +86,16 @@ namespace sqlpp
_t(std::move(t))
{}
void serialize(std::ostream& os, Db& db) const
sqlpp::serializer& interpret(sqlpp::serializer& 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
@@ -95,6 +109,19 @@ namespace sqlpp
std::shared_ptr<const _impl_base> _impl;
};
}
template<typename Context, typename Database>
struct interpreter_t<Context, detail::named_serializable_t<Database>>
{
using T = detail::named_serializable_t<Database>;
static Context& _(const T& t, Context& context)
{
t.interpret(context);
return context;
}
};
}
#endif

View File

@@ -27,9 +27,8 @@
#ifndef SQLPP_SERIALIZABLE_H
#define SQLPP_SERIALIZABLE_H
#include <ostream>
#include <vector>
#include <memory>
#include <sqlpp11/serializer.h>
#include <sqlpp11/parameter_list.h>
namespace sqlpp
@@ -39,11 +38,11 @@ namespace sqlpp
template<typename Db>
struct serializable_t
{
template<typename 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
>
serializable_t(T&& t):
_impl(std::make_shared<_impl_t<typename std::decay<T>::type>>(std::forward<T>(t)))
using _context_t = typename Db::context;
template<typename T>
serializable_t(T t):
_impl(std::make_shared<_impl_t<typename std::decay<T>::type>>(t))
{}
serializable_t(const serializable_t&) = default;
@@ -52,15 +51,21 @@ namespace sqlpp
serializable_t& operator=(serializable_t&&) = default;
~serializable_t() = default;
void serialize(std::ostream& os, Db& db) const
sqlpp::serializer& interpret(sqlpp::serializer& context) const
{
_impl->serialize(os, db);
return _impl->interpret(context);
}
_context_t& interpret(_context_t& context) const
{
return _impl->interpret(context);
}
private:
struct _impl_base
{
virtual void serialize(std::ostream& os, Db& db) const = 0;
virtual sqlpp::serializer& interpret(sqlpp::serializer& context) const = 0;
virtual _context_t interpret(_context_t& context) const = 0;
};
template<typename T>
@@ -75,16 +80,37 @@ namespace sqlpp
_t(std::move(t))
{}
void serialize(std::ostream& os, Db& db) const
sqlpp::serializer& interpret(sqlpp::serializer& 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;
};
std::shared_ptr<const _impl_base> _impl;
};
}
template<typename Context, typename Database>
struct interpreter_t<Context, detail::serializable_t<Database>>
{
using T = detail::serializable_t<Database>;
static Context& _(const T& t, Context& context)
{
t.interpret(context);
return context;
}
};
}
#endif

View File

@@ -88,6 +88,7 @@ namespace sqlpp
template<typename Expression, typename Context>
auto flatten(const Expression& exp, const Context& context) -> verbatim_t<typename std::decay<Expression>::type::_value_type::_base_value_type>
{
static_assert(not make_parameter_list_t<Expression>::type::size::value, "parameters not supported in flattened expressions");
context.clear();
interpret(exp, context);
return { context.str() };

View File

@@ -134,23 +134,30 @@ namespace sqlpp
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;
};
// FIXME: Need to check if db supports the join type. e.g. sqlite does not support right outer or full outer join
template<typename Context, typename JoinType, typename Lhs, typename Rhs, typename On>
struct interpreter_t<Context, join_t<JoinType, Lhs, Rhs, On>>
{
using T = join_t<JoinType, Lhs, Rhs, On>;
static Context& _(const T& t, Context& context)
{
static_assert(not is_noop<On>::value, "joined tables require on()");
interpret(t._lhs, context);
context << JoinType::_name;
context << " JOIN ";
context << "(";
interpret(t._rhs, context);
interpret(t._on, context);
return context;
}
};
}
#endif

View File

@@ -37,8 +37,7 @@ namespace sqlpp
struct limit_t
{
using _is_limit = 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");
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
Limit _limit;
};
@@ -50,7 +49,8 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << " LIMIT " << t._limit;
context << " LIMIT ";
interpret(t._limit, context);
return context;
}
};
@@ -65,16 +65,22 @@ namespace sqlpp
_limit = limit;
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
static_assert(Db::_supports_limit, "limit not supported by current database");
if (_limit > 0)
os << " LIMIT " << _limit;
}
std::size_t _limit;
};
template<typename Context>
struct interpreter_t<Context, dynamic_limit_t>
{
using T = dynamic_limit_t;
static Context& _(const T& t, Context& context)
{
if (t._limit > 0)
context << " LIMIT " << t._limit;
return context;
}
};
}
#endif

View File

@@ -37,8 +37,7 @@ namespace sqlpp
struct offset_t
{
using _is_offset = 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");
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
Offset _offset;
};
@@ -50,7 +49,8 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << " OFFSET " << t._offset;
context << " OFFSET ";
interpret(t._offset, context);
return context;
}
};
@@ -65,16 +65,22 @@ namespace sqlpp
_offset = offset;
}
template<typename Db>
void serialize(std::ostream& os, Db& db) const
{
if (_offset > 0)
os << " OFFSET " << _offset;
}
std::size_t _offset;
};
template<typename Context>
struct interpreter_t<Context, dynamic_offset_t>
{
using T = dynamic_offset_t;
static Context& _(const T& t, Context& context)
{
if (t._offset > 0)
context << " OFFSET " << t._offset;
return context;
}
};
}
#endif

View File

@@ -51,20 +51,28 @@ namespace sqlpp
_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;
detail::serializable_list<Database> _dynamic_expressions;
};
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_serializable_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
}
#endif

View File

@@ -443,7 +443,7 @@ namespace sqlpp
template<typename Expr>
auto limit(Expr limit)
-> set_limit_t<limit_t<typename std::decay<Expr>::type>>
-> set_limit_t<limit_t<typename wrap_operand<typename std::decay<Expr>::type>::type>>
{
static_assert(not is_noop<From>::value, "cannot call limit() without a from()");
static_assert(is_noop<Limit>::value, "cannot call limit() twice for a single select");
@@ -489,7 +489,7 @@ namespace sqlpp
template<typename Expr>
auto offset(Expr offset)
-> set_offset_t<offset_t<typename std::decay<Expr>::type>>
-> set_offset_t<offset_t<typename wrap_operand<typename std::decay<Expr>::type>::type>>
{
static_assert(not is_noop<Limit>::value, "cannot call offset() without a limit");
static_assert(is_noop<Offset>::value, "cannot call offset() twice for a single select");

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
{
serializer(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

@@ -34,7 +34,7 @@
#include <iostream>
DbMock db = {};
DbMock::Printer printer(std::cerr);
DbMock::context printer(std::cerr);
SQLPP_ALIAS_PROVIDER_GENERATOR(kaesekuchen);
int main()
@@ -89,13 +89,24 @@ int main()
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();
interpret(multi_column(t.alpha, t.alpha, (t.beta + "cake").as(t.gamma)), 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();
interpret(select(t.alpha).from(t).where(t.beta > "kaesekuchen").as(t.gamma), 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

@@ -31,10 +31,10 @@
class DbMock: public sqlpp::connection
{
public:
struct Printer
struct context
{
using _database_t = DbMock;
Printer(std::ostream& os):
context(std::ostream& os):
_os(os)
{}