mirror of
https://github.com/rbock/sqlpp11.git
synced 2025-12-31 18:20:23 -06:00
Added missing interpreter specializations, especially for serializable
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() };
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
|
||||
60
include/sqlpp11/serializer.h
Normal file
60
include/sqlpp11/serializer.h
Normal 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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user