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

Fixed serializability of statements

This commit is contained in:
rbock 2014-06-09 14:06:04 +02:00
parent 79aa358624
commit f8e0e90477
12 changed files with 228 additions and 127 deletions

View File

@ -38,8 +38,30 @@
namespace sqlpp
{
struct insert_name_t {};
struct insert_t: public vendor::statement_name_t<insert_name_t>
{};
namespace vendor
{
template<typename Context>
struct serializer_t<Context, insert_name_t>
{
using T = insert_name_t;
static Context& _(const T& t, Context& context)
{
context << "INSERT ";
return context;
}
};
}
template<typename Database>
using blank_insert_t = statement_t<Database,
insert_t,
vendor::no_into_t,
vendor::no_insert_value_list_t>;

View File

@ -33,17 +33,91 @@
#include <sqlpp11/prepared_remove.h>
#include <sqlpp11/vendor/noop.h>
#warning: need to use another table provider, since delete can be used with several tables
#include <sqlpp11/vendor/single_table.h>
#include <sqlpp11/vendor/from.h>
#include <sqlpp11/vendor/extra_tables.h>
#include <sqlpp11/vendor/using.h>
#include <sqlpp11/vendor/where.h>
namespace sqlpp
{
struct remove_name_t {};
struct remove_t: public vendor::statement_name_t<remove_name_t>
{
using _traits = make_traits<no_value_t, tag::return_value>;
struct _name_t {};
template<typename Policies>
struct _result_methods_t
{
using _statement_t = typename Policies::_statement_t;
const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
static constexpr size_t _get_static_no_of_parameters()
{
#warning need to fix this
return 0;
//return _parameter_list_t::size::value;
}
size_t _get_no_of_parameters() const
{
#warning need to fix this
return 0;
//return _parameter_list_t::size::value;
}
void _check_consistency() const
{
// FIXME: Read up on what is allowed/prohibited in INSERT
}
template<typename Db>
auto _run(Db& db) const -> decltype(db.remove(_get_statement()))
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead");
return db.remove(*this);
}
/*
template<typename Db>
auto _prepare(Db& db) const
-> prepared_remove_t<Db, remove_t>
{
_check_consistency();
return {{}, db.prepare_remove(*this)};
}
*/
};
};
namespace vendor
{
template<typename Context>
struct serializer_t<Context, remove_name_t>
{
using T = remove_name_t;
static Context& _(const T& t, Context& context)
{
context << "DELETE";
return context;
}
};
}
template<typename Database>
using blank_remove_t = statement_t<Database,
#warning Make this another policy that can take several table (cannot be select's from, since it has to be a result provider)
vendor::no_single_table_t,
remove_t,
vendor::no_from_t,
vendor::no_using_t,
vendor::no_extra_tables_t,
vendor::no_where_t>;

View File

@ -46,8 +46,30 @@
namespace sqlpp
{
struct select_name_t {};
struct select_t: public vendor::statement_name_t<select_name_t>
{};
namespace vendor
{
template<typename Context>
struct serializer_t<Context, select_name_t>
{
using T = select_name_t;
static Context& _(const T& t, Context& context)
{
context << "SELECT ";
return context;
}
};
}
template<typename Database>
using blank_select_t = statement_t<Database,
select_t,
vendor::no_select_flag_list_t,
vendor::no_select_column_list_t,
vendor::no_from_t,

View File

@ -127,7 +127,6 @@ namespace sqlpp
};
}
// SELECT
template<typename Db,
typename... Policies
>
@ -178,15 +177,53 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
#warning: Need to have a class that provides the "SELECT" or "INSERT", etc
context << "SELECT ";
using swallow = int[];
(void) swallow{(serialize(static_cast<const typename Policies::template _member_t<P>&>(t)()._data, context), 0)...};
return context;
}
};
template<typename NameData>
struct statement_name_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = NameData;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = NameData;
_impl_t<Policies> statement_name;
_impl_t<Policies>& operator()() { return statement_name; }
const _impl_t<Policies>& operator()() const { return statement_name; }
template<typename T>
static auto _get_member(T t) -> decltype(t.statement_name)
{
return t.statement_name;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
};
};
}
}

View File

@ -39,111 +39,44 @@
namespace sqlpp
{
#if 0
template<typename Db, typename... Policies>
struct update_t;
struct update_name_t {};
namespace detail
struct update_t: public vendor::statement_name_t<update_name_t>
{
template<typename Db = void, typename... Policies>
struct update_policies_t
using _traits = make_traits<no_value_t, tag::return_value>;
struct _name_t {};
template<typename Policies>
struct _result_methods_t
{
using _database_t = Db;
using _statement_t = typename Policies::_statement_t;
using _statement_t = update_t<Db, Policies...>;
struct _methods_t: public Policies::template _methods_t<update_policies_t>...
{};
template<typename Needle, typename Replacement>
struct _policies_update_t
const _statement_t& _get_statement() const
{
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
using type = update_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
// The tables not covered by the from.
using _required_tables = detail::make_difference_set_t<
_all_required_tables,
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>;
using _traits = make_traits<no_value_t>; // FIXME
struct _recursive_traits
{
using _parameters = std::tuple<>; // FIXME
using _required_tables = _required_tables;
using _provided_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
};
};
return static_cast<const _statement_t&>(*this);
}
// UPDATE
template<typename Db, typename... Policies>
struct update_t:
public Policies...,
public detail::update_policies_t<Db, Policies...>::_methods_t
{
using _policies_t = typename detail::update_policies_t<Db, Policies...>;
using _database_t = typename _policies_t::_database_t;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type;
using _parameter_list_t = typename make_parameter_list_t<update_t>::type;
// Constructors
constexpr update_t()
{}
template<typename Statement, typename Term>
update_t(Statement statement, Term term):
Policies(detail::pick_arg<Policies>(statement, term))...
{}
update_t(const update_t&) = default;
update_t(update_t&&) = default;
update_t& operator=(const update_t&) = default;
update_t& operator=(update_t&&) = default;
~update_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
#warning need to fix this
return 0;
//return _parameter_list_t::size::value;
}
size_t _get_no_of_parameters() const
{
return _parameter_list_t::size::value;
#warning need to fix this
return 0;
//return _parameter_list_t::size::value;
}
void _check_consistency() const
{
#warning reactivate tests
/*
static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
static_assert(is_table_subset_of_table<_update_list_t>::value, "updates require additional tables");
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
*/
// FIXME: Read up on what is allowed/prohibited in INSERT
}
template<typename Database>
std::size_t _run(Database& db) const
template<typename Db>
auto _run(Db& db) const -> decltype(db.update(_get_statement()))
{
_check_consistency();
@ -151,36 +84,39 @@ namespace sqlpp
return db.update(*this);
}
template<typename Database>
auto _prepare(Database& db) const
-> prepared_update_t<Database, update_t>
/*
template<typename Db>
auto _prepare(Db& db) const
-> prepared_update_t<Db, update_t>
{
_check_consistency();
return {{}, db.prepare_update(*this)};
}
*/
};
};
namespace vendor
{
template<typename Context, typename Database, typename... Policies>
struct serializer_t<Context, update_t<Database, Policies...>>
template<typename Context>
struct serializer_t<Context, update_name_t>
{
using T = update_t<Database, Policies...>;
using T = update_name_t;
static Context& _(const T& t, Context& context)
{
context << "UPDATE ";
using swallow = int[];
(void) swallow{(serialize(static_cast<const Policies&>(t), context), 0)...};
return context;
}
};
}
#endif
template<typename Database>
using blank_update_t = statement_t<Database,
update_t,
vendor::no_single_table_t,
vendor::no_update_list_t,
vendor::no_where_t>;

View File

@ -205,6 +205,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context)
{
context << " INTO ";
serialize(t._table, context);
return context;
}

View File

@ -10,7 +10,7 @@ endmacro ()
build_and_run(InsertTest)
build_and_run(RemoveTest)
build_and_run(UpdateTest)
#build_and_run(SelectTest)
build_and_run(SelectTest)
#build_and_run(SelectTypeTest)
#build_and_run(FunctionTest)
#build_and_run(PreparedTest)

View File

@ -71,7 +71,8 @@ int main()
multi_insert.values.add(t.beta = sqlpp::default_value, t.delta = sqlpp::default_value);
auto i = dynamic_insert_into(db, t).dynamic_set();
i.insert_list.add(t.beta = "kirschauflauf");
serialize(i, printer).str();
printer.reset();
std::cerr << serialize(i, printer).str() << std::endl;
db(multi_insert);

View File

@ -43,7 +43,7 @@ struct MockDb: public sqlpp::connection
void reset()
{
_os.clear();
_os.str("");
}
template<typename T>

View File

@ -62,7 +62,10 @@ int main()
auto r = dynamic_remove_from(db, t).dynamic_using().dynamic_where();
r.using_.add(t);
r.where.add(t.beta != "transparent");
serialize(r, printer).str();
printer.reset();
std::cerr << serialize(r, printer).str() << std::endl;
printer.reset();
std::cerr << serialize(remove_from(t).where(true), printer).str() << std::endl;
db(r);

View File

@ -85,6 +85,9 @@ int main()
int64_t a = row.alpha;
}
printer.reset();
std::cerr << serialize(s, printer).str() << std::endl;
auto X = select(all_of(t)).from(t).as(t.alpha);
return 0;

View File

@ -61,9 +61,11 @@ int main()
serialize(update(t).set(t.gamma = false).where(t.beta != "transparent"), printer).str();
serialize(update(t).set(t.beta = "opaque").where(t.beta != t.beta), printer).str();
auto u = dynamic_update(db, t).dynamic_set(t.gamma = false).dynamic_where();
#warning: This should fail since gamma is set already
u.assignments.add(t.gamma = false);
u.where.add(t.gamma != false);
serialize(u, printer).str();
printer.reset();
std::cerr << serialize(u, printer).str() << std::endl;
db(u);