mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Reformatted using clang-format
Please use clang-format before submitting code, e.g via the pre-commit supplied in the repo (thanks AndiDog)
This commit is contained in:
parent
46c565c5c5
commit
09f23cea0a
@ -14,7 +14,7 @@ BreakBeforeBinaryOperators: false
|
|||||||
BreakBeforeTernaryOperators: true
|
BreakBeforeTernaryOperators: true
|
||||||
BreakConstructorInitializersBeforeComma: false
|
BreakConstructorInitializersBeforeComma: false
|
||||||
BinPackParameters: false
|
BinPackParameters: false
|
||||||
ColumnLimit: 160
|
ColumnLimit: 120
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
ExperimentalAutoDetectBinPacking: false
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef SQLPP_DATABASE_BIND_RESULT_H
|
#ifndef SQLPP_DATABASE_BIND_RESULT_H
|
||||||
#define SQLPP_DATABASE_BIND_RESULT_H
|
#define SQLPP_DATABASE_BIND_RESULT_H
|
||||||
|
|
||||||
@ -32,62 +31,61 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace database
|
namespace database
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* bind_result_t binds values of a sqlpp11 result row
|
* bind_result_t binds values of a sqlpp11 result row
|
||||||
* to the results of a statement
|
* to the results of a statement
|
||||||
*/
|
*/
|
||||||
class bind_result_t
|
class bind_result_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bind_result_t(); // default constructor for a result that will not yield a valid row
|
bind_result_t(); // default constructor for a result that will not yield a valid row
|
||||||
bind_result_t(...);
|
bind_result_t(...);
|
||||||
bind_result_t(const bind_result_t&) = delete;
|
bind_result_t(const bind_result_t&) = delete;
|
||||||
bind_result_t(bind_result_t&& rhs);
|
bind_result_t(bind_result_t&& rhs);
|
||||||
bind_result_t& operator=(const bind_result_t&) = delete;
|
bind_result_t& operator=(const bind_result_t&) = delete;
|
||||||
bind_result_t& operator=(bind_result_t&&);
|
bind_result_t& operator=(bind_result_t&&);
|
||||||
~bind_result_t();
|
~bind_result_t();
|
||||||
|
|
||||||
bool operator==(const bind_result_t& rhs) const;
|
bool operator==(const bind_result_t& rhs) const;
|
||||||
|
|
||||||
template<typename ResultRow>
|
template <typename ResultRow>
|
||||||
void next(ResultRow& result_row);
|
void next(ResultRow& result_row);
|
||||||
|
|
||||||
// something similar to this:
|
// something similar to this:
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
if (!_handle)
|
if (!_handle)
|
||||||
{
|
{
|
||||||
result_row.invalidate();
|
result_row.invalidate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (next_impl())
|
if (next_impl())
|
||||||
{
|
{
|
||||||
if (not result_row)
|
if (not result_row)
|
||||||
{
|
{
|
||||||
result_row.validate();
|
result_row.validate();
|
||||||
}
|
}
|
||||||
result_row._bind(*this); // bind result row values to results
|
result_row._bind(*this); // bind result row values to results
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (result_row)
|
if (result_row)
|
||||||
result_row.invalidate();
|
result_row.invalidate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// These are called by the result row to bind individual result values
|
// These are called by the result row to bind individual result values
|
||||||
// More will be added over time
|
// More will be added over time
|
||||||
void _bind_boolean_result(size_t index, signed char* value, bool* is_null);
|
void _bind_boolean_result(size_t index, signed char* value, bool* is_null);
|
||||||
void _bind_floating_point_result(size_t index, double* value, bool* is_null);
|
void _bind_floating_point_result(size_t index, double* value, bool* is_null);
|
||||||
void _bind_integral_result(size_t index, int64_t* value, bool* is_null);
|
void _bind_integral_result(size_t index, int64_t* value, bool* is_null);
|
||||||
void _bind_text_result(size_t index, const char** text, size_t* len);
|
void _bind_text_result(size_t index, const char** text, size_t* len);
|
||||||
...
|
...
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,122 +24,125 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef SQLPP_DATABASE_CONNECTION_H
|
#ifndef SQLPP_DATABASE_CONNECTION_H
|
||||||
#define SQLPP_DATABASE_CONNECTION_H
|
#define SQLPP_DATABASE_CONNECTION_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sqlpp11/connection.h>
|
#include <sqlpp11/connection.h>
|
||||||
#include <sqlpp11/database/char_result.h> // You may use char result or bind result or both
|
#include <sqlpp11/database/char_result.h> // You may use char result or bind result or both
|
||||||
#include <sqlpp11/database/bind_result.h> // to represent results of select and prepared select
|
#include <sqlpp11/database/bind_result.h> // to represent results of select and prepared select
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace database
|
namespace database
|
||||||
{
|
{
|
||||||
// The context is not a requirement, but if the database requires
|
// The context is not a requirement, but if the database requires
|
||||||
// any deviations from the SQL standard, you should use your own
|
// any deviations from the SQL standard, you should use your own
|
||||||
// context in order to specialize the behaviour, see also interpreter.h
|
// context in order to specialize the behaviour, see also interpreter.h
|
||||||
struct context_t
|
struct context_t
|
||||||
{
|
{
|
||||||
template<typename T>
|
template <typename T>
|
||||||
std::ostream& operator<<(T t);
|
std::ostream& operator<<(T t);
|
||||||
|
|
||||||
std::string escape(std::string arg);
|
std::string escape(std::string arg);
|
||||||
};
|
};
|
||||||
|
|
||||||
class connection: public sqlpp::connection // this inheritance helps with ADL for dynamic_select, for instance
|
class connection : public sqlpp::connection // this inheritance helps with ADL for dynamic_select, for instance
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using _traits = ::sqlpp::make_traits<::sqlpp::no_value_t,
|
using _traits = ::sqlpp::make_traits<
|
||||||
::sqlpp::tag::enforce_null_result_treatment // If that is what you really want, leave it out otherwise
|
::sqlpp::no_value_t,
|
||||||
>;
|
::sqlpp::tag::enforce_null_result_treatment // If that is what you really want, leave it out otherwise
|
||||||
|
>;
|
||||||
|
|
||||||
using _prepared_statement_t = << handle to a prepared statement of the database >>;
|
using _prepared_statement_t = << handle to a prepared statement of the database >> ;
|
||||||
using _serializer_context_t = << This context is used to serialize a statement >>
|
using _serializer_context_t = << This context is used to serialize a statement >> using _interpreter_context_t =
|
||||||
using _interpreter_context_t = << This context is used interpret a statement >>;
|
<< This context is used interpret a statement >>
|
||||||
// serializer and interpreter are typically the same for string based connectors
|
;
|
||||||
// the types are required for dynamic statement components, see sqlpp11/interpretable.h
|
// serializer and interpreter are typically the same for string based connectors
|
||||||
|
// the types are required for dynamic statement components, see sqlpp11/interpretable.h
|
||||||
|
|
||||||
connection(...);
|
connection(...);
|
||||||
~connection();
|
~connection();
|
||||||
connection(const connection&) = delete;
|
connection(const connection&) = delete;
|
||||||
connection(connection&&) = delete;
|
connection(connection&&) = delete;
|
||||||
connection& operator=(const connection&) = delete;
|
connection& operator=(const connection&) = delete;
|
||||||
connection& operator=(connection&&) = delete;
|
connection& operator=(connection&&) = delete;
|
||||||
|
|
||||||
//! "direct" select
|
//! "direct" select
|
||||||
template<typename Select>
|
template <typename Select>
|
||||||
<<bind_result_t>> select(const Select& s);
|
<< bind_result_t >>
|
||||||
|
select(const Select& s);
|
||||||
|
|
||||||
//! prepared select
|
//! prepared select
|
||||||
template<typename Select>
|
template <typename Select>
|
||||||
_prepared_statement_t prepare_select(Select& s);
|
_prepared_statement_t prepare_select(Select& s);
|
||||||
|
|
||||||
template<typename PreparedSelect>
|
template <typename PreparedSelect>
|
||||||
<<bind_result_t>> run_prepared_select(const PreparedSelect& s); // call s._bind_params()
|
<< bind_result_t >>
|
||||||
|
run_prepared_select(const PreparedSelect& s); // call s._bind_params()
|
||||||
|
|
||||||
//! "direct insert
|
//! "direct insert
|
||||||
template<typename Insert>
|
template <typename Insert>
|
||||||
size_t insert(const Insert& i);
|
size_t insert(const Insert& i);
|
||||||
|
|
||||||
//! prepared insert
|
//! prepared insert
|
||||||
template<typename Insert>
|
template <typename Insert>
|
||||||
_prepared_statement_t prepare_insert(Insert& i);
|
_prepared_statement_t prepare_insert(Insert& i);
|
||||||
|
|
||||||
template<typename PreparedInsert>
|
template <typename PreparedInsert>
|
||||||
size_t run_prepared_insert(const PreparedInsert& i); // call i._bind_params()
|
size_t run_prepared_insert(const PreparedInsert& i); // call i._bind_params()
|
||||||
|
|
||||||
//! "direct" update
|
//! "direct" update
|
||||||
template<typename Update>
|
template <typename Update>
|
||||||
size_t update(const Update& u);
|
size_t update(const Update& u);
|
||||||
|
|
||||||
//! "prepared" update
|
//! "prepared" update
|
||||||
template<typename Update>
|
template <typename Update>
|
||||||
_prepared_statement_t prepare_update(Update& u);
|
_prepared_statement_t prepare_update(Update& u);
|
||||||
|
|
||||||
template<typename PreparedUpdate>
|
template <typename PreparedUpdate>
|
||||||
size_t run_prepared_update(const PreparedUpdate& u); // call u._bind_params()
|
size_t run_prepared_update(const PreparedUpdate& u); // call u._bind_params()
|
||||||
|
|
||||||
//! "direct" remove
|
//! "direct" remove
|
||||||
template<typename Remove>
|
template <typename Remove>
|
||||||
size_t remove(const Remove& r)
|
size_t remove(const Remove& r)
|
||||||
|
|
||||||
//! prepared remove
|
//! prepared remove
|
||||||
template<typename Remove>
|
template <typename Remove>
|
||||||
_prepared_statement_t prepare_remove(Remove& r);
|
_prepared_statement_t prepare_remove(Remove& r);
|
||||||
|
|
||||||
template<typename PreparedRemove>
|
template <typename PreparedRemove>
|
||||||
size_t run_prepared_remove(const PreparedRemove& r); // call r._bind_params()
|
size_t run_prepared_remove(const PreparedRemove& r); // call r._bind_params()
|
||||||
|
|
||||||
//! call run on the argument
|
//! call run on the argument
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto operator() (const T& t) -> decltype(t._run(*this))
|
auto operator()(const T& t) -> decltype(t._run(*this))
|
||||||
{
|
{
|
||||||
return t._run(*this);
|
return t._run(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! call prepare on the argument
|
//! call prepare on the argument
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto prepare(const T& t) -> decltype(t._prepare(*this))
|
auto prepare(const T& t) -> decltype(t._prepare(*this))
|
||||||
{
|
{
|
||||||
return t._prepare(*this);
|
return t._prepare(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! start transaction
|
//! start transaction
|
||||||
void start_transaction();
|
void start_transaction();
|
||||||
|
|
||||||
//! commit transaction (or throw transaction if the transaction has been finished already)
|
//! commit transaction (or throw transaction if the transaction has been finished already)
|
||||||
void commit_transaction();
|
void commit_transaction();
|
||||||
|
|
||||||
//! rollback transaction with or without reporting the rollback (or throw if the transaction has been finished already)
|
//! rollback transaction with or without reporting the rollback (or throw if the transaction has been finished
|
||||||
void rollback_transaction(bool report);
|
// already)
|
||||||
|
void rollback_transaction(bool report);
|
||||||
|
|
||||||
//! report a rollback failure (will be called by transactions in case of a rollback failure in the destructor)
|
//! report a rollback failure (will be called by transactions in case of a rollback failure in the destructor)
|
||||||
void report_rollback_failure(const std::string message) noexcept;
|
void report_rollback_failure(const std::string message) noexcept;
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <sqlpp11/database/interpreter.h>
|
#include <sqlpp11/database/interpreter.h>
|
||||||
|
@ -41,22 +41,21 @@
|
|||||||
*/
|
*/
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace vendor
|
namespace vendor
|
||||||
{
|
{
|
||||||
template<typename ValueType, typename NameType>
|
template <typename ValueType, typename NameType>
|
||||||
struct interpreter_t<database::context_t, parameter_t<ValueType, NameType>>
|
struct interpreter_t<database::context_t, parameter_t<ValueType, NameType>>
|
||||||
{
|
{
|
||||||
using T = parameter_t<ValueType, NameType>;
|
using T = parameter_t<ValueType, NameType>;
|
||||||
|
|
||||||
static database::context_t& _(const T& t, database::context_t& context)
|
static database::context_t& _(const T& t, database::context_t& context)
|
||||||
{
|
{
|
||||||
context << "?" << context.count();
|
context << "?" << context.count();
|
||||||
context.pop_count();
|
context.pop_count();
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef SQLPP_DATABASE_PREPARED_STATEMENT_H
|
#ifndef SQLPP_DATABASE_PREPARED_STATEMENT_H
|
||||||
#define SQLPP_DATABASE_PREPARED_STATEMENT_H
|
#define SQLPP_DATABASE_PREPARED_STATEMENT_H
|
||||||
|
|
||||||
@ -33,28 +32,28 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace database
|
namespace database
|
||||||
{
|
{
|
||||||
class prepared_statement_t
|
class prepared_statement_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
prepared_statement_t() = delete;
|
prepared_statement_t() = delete;
|
||||||
prepared_statement_t(...);
|
prepared_statement_t(...);
|
||||||
prepared_statement_t(const prepared_statement_t&) = delete;
|
prepared_statement_t(const prepared_statement_t&) = delete;
|
||||||
prepared_statement_t(prepared_statement_t&& rhs);
|
prepared_statement_t(prepared_statement_t&& rhs);
|
||||||
prepared_statement_t& operator=(const prepared_statement_t&) = delete;
|
prepared_statement_t& operator=(const prepared_statement_t&) = delete;
|
||||||
prepared_statement_t& operator=(prepared_statement_t&&);
|
prepared_statement_t& operator=(prepared_statement_t&&);
|
||||||
~prepared_statement_t();
|
~prepared_statement_t();
|
||||||
|
|
||||||
bool operator==(const prepared_statement_t& rhs) const;
|
bool operator==(const prepared_statement_t& rhs) const;
|
||||||
|
|
||||||
// These are called by the sqlpp11::prepared_*_t to bind the individual parameters
|
// These are called by the sqlpp11::prepared_*_t to bind the individual parameters
|
||||||
// More will be added over time
|
// More will be added over time
|
||||||
void _bind_boolean_parameter(size_t index, const signed char* value, bool is_null);
|
void _bind_boolean_parameter(size_t index, const signed char* value, bool is_null);
|
||||||
void _bind_floating_point_parameter(size_t index, const double* value, bool is_null);
|
void _bind_floating_point_parameter(size_t index, const double* value, bool is_null);
|
||||||
void _bind_integral_parameter(size_t index, const int64_t* value, bool is_null);
|
void _bind_integral_parameter(size_t index, const int64_t* value, bool is_null);
|
||||||
void _bind_text_parameter(size_t index, const std::string* value, bool is_null);
|
void _bind_text_parameter(size_t index, const std::string* value, bool is_null);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <sqlpp11/column_types.h>
|
#include <sqlpp11/column_types.h>
|
||||||
#include <sqlpp11/char_sequence.h>
|
#include <sqlpp11/char_sequence.h>
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
namespace test
|
namespace test
|
||||||
{
|
{
|
||||||
namespace TabPerson_
|
namespace TabPerson_
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
#include <sqlpp11/table_base.h>
|
#include <sqlpp11/table_base.h>
|
||||||
#include <sqlpp11/column_types.h>
|
#include <sqlpp11/column_types.h>
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
namespace TabFoo_
|
namespace TabFoo_
|
||||||
{
|
{
|
||||||
struct Omega
|
struct Omega
|
||||||
|
@ -29,40 +29,38 @@
|
|||||||
|
|
||||||
int insert(int, char**)
|
int insert(int, char**)
|
||||||
{
|
{
|
||||||
MockDb db;
|
MockDb db;
|
||||||
|
|
||||||
test::TabPerson p;
|
test::TabPerson p;
|
||||||
test::TabFeature f;
|
test::TabFeature f;
|
||||||
|
|
||||||
db(insert_into(f).set(f.name = "loves c++", f.fatal = false));
|
db(insert_into(f).set(f.name = "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.nahme = "loves c++", f.fatal = false));
|
// db(insert_into(f).set(f.nahme = "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.name == "loves c++", f.fatal = false));
|
// db(insert_into(f).set(f.name == "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.name = "loves c++", f.fatal = "false"));
|
// db(insert_into(f).set(f.name = "loves c++", f.fatal = "false"));
|
||||||
|
|
||||||
//db(insert_into(p).set(f.name = "loves c++", f.fatal = false));
|
// db(insert_into(p).set(f.name = "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.name = "loves c++", p.feature = 7));
|
// db(insert_into(f).set(f.name = "loves c++", p.feature = 7));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.id = 42, f.name = "loves c++", f.fatal = false));
|
// db(insert_into(f).set(f.id = 42, f.name = "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.name = "loves c++"));
|
// db(insert_into(f).set(f.name = "loves c++"));
|
||||||
|
|
||||||
|
db(insert_into(f).default_values());
|
||||||
|
|
||||||
db(insert_into(f).default_values());
|
auto i = insert_into(p).columns(p.name, p.feature);
|
||||||
|
i.values.add(p.name = "Roland", p.feature = 1);
|
||||||
|
i.values.add(p.name = "Zaphod", p.feature = sqlpp::default_value);
|
||||||
|
db(i);
|
||||||
|
|
||||||
auto i = insert_into(p).columns(p.name, p.feature);
|
auto pi = db.prepare(insert_into(p).set(p.name = parameter(f.name), p.feature = parameter(p.feature)));
|
||||||
i.values.add(p.name = "Roland", p.feature = 1);
|
pi.params.name = "likes java";
|
||||||
i.values.add(p.name = "Zaphod", p.feature = sqlpp::default_value);
|
pi.params.feature = true;
|
||||||
db(i);
|
|
||||||
|
|
||||||
|
db(pi);
|
||||||
auto pi = db.prepare(insert_into(p).set(p.name = parameter(f.name), p.feature = parameter(p.feature)));
|
return 0;
|
||||||
pi.params.name = "likes java";
|
|
||||||
pi.params.feature = true;
|
|
||||||
|
|
||||||
db(pi);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if 0 // syntax example
|
#if 0 // syntax example
|
||||||
SQLPP_DECLARE_TABLE(
|
SQLPP_DECLARE_TABLE(
|
||||||
(table, \
|
(table, \
|
||||||
SQLPP_DROP_IF_EXISTS \
|
SQLPP_DROP_IF_EXISTS \
|
||||||
@ -45,6 +45,7 @@ SQLPP_DECLARE_TABLE(
|
|||||||
|
|
||||||
#include "MockDb.h"
|
#include "MockDb.h"
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
SQLPP_DECLARE_TABLE(
|
SQLPP_DECLARE_TABLE(
|
||||||
(tab_person)
|
(tab_person)
|
||||||
,
|
,
|
||||||
@ -60,42 +61,41 @@ SQLPP_DECLARE_TABLE(
|
|||||||
(name , varchar(255), SQLPP_NULL )
|
(name , varchar(255), SQLPP_NULL )
|
||||||
(fatal, bool , SQLPP_NOT_NULL )
|
(fatal, bool , SQLPP_NOT_NULL )
|
||||||
)
|
)
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
int ppgen(int, char**)
|
int ppgen(int, char**)
|
||||||
{
|
{
|
||||||
MockDb db;
|
MockDb db;
|
||||||
tab_person::tab_person p;
|
tab_person::tab_person p;
|
||||||
tab_feature::tab_feature f;
|
tab_feature::tab_feature f;
|
||||||
|
|
||||||
db(insert_into(f).set(f.name = "loves c++", f.fatal = false));
|
db(insert_into(f).set(f.name = "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.nahme = "loves c++", f.fatal = false));
|
// db(insert_into(f).set(f.nahme = "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.name == "loves c++", f.fatal = false));
|
// db(insert_into(f).set(f.name == "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.name = "loves c++", f.fatal = "false"));
|
// db(insert_into(f).set(f.name = "loves c++", f.fatal = "false"));
|
||||||
|
|
||||||
//db(insert_into(p).set(f.name = "loves c++", f.fatal = false));
|
// db(insert_into(p).set(f.name = "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.name = "loves c++", p.feature = 7));
|
// db(insert_into(f).set(f.name = "loves c++", p.feature = 7));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.id = 42, f.name = "loves c++", f.fatal = false));
|
// db(insert_into(f).set(f.id = 42, f.name = "loves c++", f.fatal = false));
|
||||||
|
|
||||||
//db(insert_into(f).set(f.name = "loves c++"));
|
// db(insert_into(f).set(f.name = "loves c++"));
|
||||||
|
|
||||||
|
db(insert_into(f).default_values());
|
||||||
|
|
||||||
db(insert_into(f).default_values());
|
auto i = insert_into(p).columns(p.name, p.feature);
|
||||||
|
i.values.add(p.name = "Roland", p.feature = 1);
|
||||||
|
i.values.add(p.name = "Zaphod", p.feature = sqlpp::default_value);
|
||||||
|
db(i);
|
||||||
|
|
||||||
auto i = insert_into(p).columns(p.name, p.feature);
|
auto pi = db.prepare(insert_into(p).set(p.name = parameter(f.name), p.feature = parameter(p.feature)));
|
||||||
i.values.add(p.name = "Roland", p.feature = 1);
|
pi.params.name = "likes java";
|
||||||
i.values.add(p.name = "Zaphod", p.feature = sqlpp::default_value);
|
pi.params.feature = true;
|
||||||
db(i);
|
|
||||||
|
|
||||||
|
db(pi);
|
||||||
auto pi = db.prepare(insert_into(p).set(p.name = parameter(f.name), p.feature = parameter(p.feature)));
|
return 0;
|
||||||
pi.params.name = "likes java";
|
|
||||||
pi.params.feature = true;
|
|
||||||
|
|
||||||
db(pi);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -29,13 +29,11 @@
|
|||||||
|
|
||||||
int remove(int, char**)
|
int remove(int, char**)
|
||||||
{
|
{
|
||||||
MockDb db;
|
MockDb db;
|
||||||
|
|
||||||
test::TabPerson p;
|
test::TabPerson p;
|
||||||
test::TabFeature q;
|
test::TabFeature q;
|
||||||
|
|
||||||
db(remove_from(p)
|
db(remove_from(p).using_(p, q).where(p.feature == q.id and q.fatal == true));
|
||||||
.using_(p, q)
|
return 0;
|
||||||
.where(p.feature == q.id and q.fatal == true));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -29,31 +29,28 @@
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
MockDb db;
|
MockDb db;
|
||||||
|
|
||||||
test::TabPerson p;
|
test::TabPerson p;
|
||||||
test::TabFeature f;
|
test::TabFeature f;
|
||||||
|
|
||||||
db(insert_into(f).set(f.name = "Loves C++", p.fatal = false));
|
db(insert_into(f).set(f.name = "Loves C++", p.fatal = false));
|
||||||
|
|
||||||
db(insert_into(f).set(p.name = "Roland", p.feature = 1));
|
db(insert_into(f).set(p.name = "Roland", p.feature = 1));
|
||||||
|
|
||||||
auto s = select(all_of(p))
|
auto s = select(all_of(p))
|
||||||
.from(p, q)
|
.from(p, q)
|
||||||
.where(p.name == any(select(q.name)
|
.where(p.name == any(select(q.name).from(q).where(true)))
|
||||||
.from(q)
|
.group_by(q.name)
|
||||||
.where(true)))
|
.having(p.name.like("%Bee%"))
|
||||||
.group_by(q.name)
|
.order_by(p.name.asc())
|
||||||
.having(p.name.like("%Bee%"))
|
.limit(3)
|
||||||
.order_by(p.name.asc())
|
.offset(7);
|
||||||
.limit(3).offset(7);
|
|
||||||
|
|
||||||
auto x = s.as(sqlpp::alias::x);
|
auto x = s.as(sqlpp::alias::x);
|
||||||
for (const auto& row : db(select(p.id, x.name)
|
for (const auto& row : db(select(p.id, x.name).from(p.join(x).on(p.feature == x.feature)).where(true)))
|
||||||
.from(p.join(x).on(p.feature == x.feature))
|
{
|
||||||
.where(true)))
|
int id = row.id;
|
||||||
{
|
std::string name = row.name;
|
||||||
int id = row.id;
|
}
|
||||||
std::string name = row.name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -38,23 +38,22 @@ SQLPP_ALIAS_PROVIDER(cheesecake)
|
|||||||
|
|
||||||
int select(int, char**)
|
int select(int, char**)
|
||||||
{
|
{
|
||||||
static constexpr bool some_condition = true;
|
static constexpr bool some_condition = true;
|
||||||
static constexpr bool some_other_condition = false;
|
static constexpr bool some_other_condition = false;
|
||||||
|
|
||||||
MockDb db;
|
MockDb db;
|
||||||
|
|
||||||
test::TabPerson p;
|
test::TabPerson p;
|
||||||
test::TabFeature f;
|
test::TabFeature f;
|
||||||
|
|
||||||
for (const auto& row : db(select(all_of(p)).from(p).where(p.id > 7)))
|
for (const auto& row : db(select(all_of(p)).from(p).where(p.id > 7)))
|
||||||
{
|
{
|
||||||
int64_t id = row.id;
|
int64_t id = row.id;
|
||||||
std::string name = row.name;
|
std::string name = row.name;
|
||||||
int64_t feature = row.feature;
|
int64_t feature = row.feature;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
#if 0
|
|
||||||
for (const auto& row : db(select(p.name).from(p).where(p.name.like("Herb%"))))
|
for (const auto& row : db(select(p.name).from(p).where(p.name.like("Herb%"))))
|
||||||
{
|
{
|
||||||
int64_t id = row.id;
|
int64_t id = row.id;
|
||||||
@ -63,8 +62,6 @@ int select(int, char**)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
for (const auto& row : db(select(p.name, f.name.as(cheesecake)).from(p,f).where(p.id > 7 and p.feature == 3)))
|
for (const auto& row : db(select(p.name, f.name.as(cheesecake)).from(p,f).where(p.id > 7 and p.feature == 3)))
|
||||||
{
|
{
|
||||||
@ -75,8 +72,6 @@ int select(int, char**)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
for (const auto& row : db(select(multi_column(all_of(p)).as(p), multi_column(f.name, f.id).as(f)).from(p,f).where(true)))
|
for (const auto& row : db(select(multi_column(all_of(p)).as(p), multi_column(f.name, f.id).as(f)).from(p,f).where(true)))
|
||||||
{
|
{
|
||||||
@ -88,12 +83,6 @@ int select(int, char**)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
auto s = select(p.id, p.name, f.id.as(cheesecake))
|
auto s = select(p.id, p.name, f.id.as(cheesecake))
|
||||||
.from(p, f)
|
.from(p, f)
|
||||||
@ -117,41 +106,21 @@ int select(int, char**)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if !0
|
#if !0
|
||||||
auto dysel = dynamic_select(db).dynamic_columns(p.name).from(p).dynamic_where();
|
auto dysel = dynamic_select(db).dynamic_columns(p.name).from(p).dynamic_where();
|
||||||
|
|
||||||
if (some_condition)
|
if (some_condition)
|
||||||
dysel.selected_columns.add(p.feature);
|
dysel.selected_columns.add(p.feature);
|
||||||
|
|
||||||
if (some_other_condition)
|
if (some_other_condition)
|
||||||
dysel.where.add(p.id > 17);
|
dysel.where.add(p.id > 17);
|
||||||
|
|
||||||
for (const auto& row : db(dysel))
|
for (const auto& row : db(dysel))
|
||||||
{
|
{
|
||||||
std::string name = row.name;
|
std::string name = row.name;
|
||||||
std::string feature = row.at("feature");
|
std::string feature = row.at("feature");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,11 @@
|
|||||||
|
|
||||||
int update(int, char**)
|
int update(int, char**)
|
||||||
{
|
{
|
||||||
MockDb db;
|
MockDb db;
|
||||||
|
|
||||||
test::TabPerson p;
|
test::TabPerson p;
|
||||||
//test::TabFeature q;
|
// test::TabFeature q;
|
||||||
|
|
||||||
db(update(p).set(p.feature = 7).where(p.id == 23));
|
db(update(p).set(p.feature = 7).where(p.id == 23));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -32,45 +32,44 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Expression, typename AliasProvider>
|
template <typename Expression, typename AliasProvider>
|
||||||
struct expression_alias_t
|
struct expression_alias_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<value_type_of<Expression>, tag::is_selectable, tag::is_alias>;
|
using _traits = make_traits<value_type_of<Expression>, tag::is_selectable, tag::is_alias>;
|
||||||
using _nodes = detail::type_vector<Expression>;
|
using _nodes = detail::type_vector<Expression>;
|
||||||
|
|
||||||
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");
|
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");
|
||||||
static_assert(not is_alias_t<Expression>::value, "cannot create an alias of an alias");
|
static_assert(not is_alias_t<Expression>::value, "cannot create an alias of an alias");
|
||||||
|
|
||||||
using _alias_t = typename AliasProvider::_alias_t;
|
using _alias_t = typename AliasProvider::_alias_t;
|
||||||
|
|
||||||
expression_alias_t(Expression expression):
|
expression_alias_t(Expression expression) : _expression(expression)
|
||||||
_expression(expression)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
expression_alias_t(const expression_alias_t&) = default;
|
expression_alias_t(const expression_alias_t&) = default;
|
||||||
expression_alias_t(expression_alias_t&&) = default;
|
expression_alias_t(expression_alias_t&&) = default;
|
||||||
expression_alias_t& operator=(const expression_alias_t&) = default;
|
expression_alias_t& operator=(const expression_alias_t&) = default;
|
||||||
expression_alias_t& operator=(expression_alias_t&&) = default;
|
expression_alias_t& operator=(expression_alias_t&&) = default;
|
||||||
~expression_alias_t() = default;
|
~expression_alias_t() = default;
|
||||||
|
|
||||||
Expression _expression;
|
Expression _expression;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Expression, typename AliasProvider>
|
template <typename Context, typename Expression, typename AliasProvider>
|
||||||
struct serializer_t<Context, expression_alias_t<Expression, AliasProvider>>
|
struct serializer_t<Context, expression_alias_t<Expression, AliasProvider>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Expression>;
|
using _serialize_check = serialize_check_of<Context, Expression>;
|
||||||
using T = expression_alias_t<Expression, AliasProvider>;
|
using T = expression_alias_t<Expression, AliasProvider>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
serialize_operand(t._expression, context);
|
|
||||||
context << " AS ";
|
|
||||||
context << name_of<T>::char_ptr();
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
serialize_operand(t._expression, context);
|
||||||
|
context << " AS ";
|
||||||
|
context << name_of<T>::char_ptr();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,69 +30,76 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <sqlpp11/char_sequence.h>
|
#include <sqlpp11/char_sequence.h>
|
||||||
|
|
||||||
#define SQLPP_ALIAS_PROVIDER(name) \
|
#define SQLPP_ALIAS_PROVIDER(name) \
|
||||||
struct name##_t\
|
struct name##_t \
|
||||||
{\
|
{ \
|
||||||
struct _alias_t\
|
struct _alias_t \
|
||||||
{\
|
{ \
|
||||||
static constexpr const char _literal[] = #name;\
|
static constexpr const char _literal[] = #name; \
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;\
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>; \
|
||||||
template<typename T>\
|
template <typename T> \
|
||||||
struct _member_t\
|
struct _member_t \
|
||||||
{\
|
{ \
|
||||||
T name;\
|
T name; \
|
||||||
T& operator()() { return name; }\
|
T& operator()() \
|
||||||
const T& operator()() const { return name; }\
|
{ \
|
||||||
};\
|
return name; \
|
||||||
};\
|
} \
|
||||||
};\
|
const T& operator()() const \
|
||||||
constexpr name##_t name = {};
|
{ \
|
||||||
|
return name; \
|
||||||
|
} \
|
||||||
|
}; \
|
||||||
|
}; \
|
||||||
|
}; \
|
||||||
|
constexpr name##_t name = {};
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename T, typename Enable = void>
|
template <typename T, typename Enable = void>
|
||||||
struct is_alias_provider_t
|
struct is_alias_provider_t
|
||||||
{
|
{
|
||||||
static constexpr bool value = false;
|
static constexpr bool value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct is_alias_provider_t<T, typename std::enable_if<std::is_class<typename T::_alias_t::template _member_t<int>>::value, void>::type>
|
struct is_alias_provider_t<
|
||||||
{
|
T,
|
||||||
static constexpr bool value = true;
|
typename std::enable_if<std::is_class<typename T::_alias_t::template _member_t<int>>::value, void>::type>
|
||||||
};
|
{
|
||||||
|
static constexpr bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
namespace alias
|
namespace alias
|
||||||
{
|
{
|
||||||
SQLPP_ALIAS_PROVIDER(a)
|
SQLPP_ALIAS_PROVIDER(a)
|
||||||
SQLPP_ALIAS_PROVIDER(b)
|
SQLPP_ALIAS_PROVIDER(b)
|
||||||
SQLPP_ALIAS_PROVIDER(c)
|
SQLPP_ALIAS_PROVIDER(c)
|
||||||
SQLPP_ALIAS_PROVIDER(d)
|
SQLPP_ALIAS_PROVIDER(d)
|
||||||
SQLPP_ALIAS_PROVIDER(e)
|
SQLPP_ALIAS_PROVIDER(e)
|
||||||
SQLPP_ALIAS_PROVIDER(f)
|
SQLPP_ALIAS_PROVIDER(f)
|
||||||
SQLPP_ALIAS_PROVIDER(g)
|
SQLPP_ALIAS_PROVIDER(g)
|
||||||
SQLPP_ALIAS_PROVIDER(h)
|
SQLPP_ALIAS_PROVIDER(h)
|
||||||
SQLPP_ALIAS_PROVIDER(i)
|
SQLPP_ALIAS_PROVIDER(i)
|
||||||
SQLPP_ALIAS_PROVIDER(j)
|
SQLPP_ALIAS_PROVIDER(j)
|
||||||
SQLPP_ALIAS_PROVIDER(k)
|
SQLPP_ALIAS_PROVIDER(k)
|
||||||
SQLPP_ALIAS_PROVIDER(l)
|
SQLPP_ALIAS_PROVIDER(l)
|
||||||
SQLPP_ALIAS_PROVIDER(m)
|
SQLPP_ALIAS_PROVIDER(m)
|
||||||
SQLPP_ALIAS_PROVIDER(n)
|
SQLPP_ALIAS_PROVIDER(n)
|
||||||
SQLPP_ALIAS_PROVIDER(o)
|
SQLPP_ALIAS_PROVIDER(o)
|
||||||
SQLPP_ALIAS_PROVIDER(p)
|
SQLPP_ALIAS_PROVIDER(p)
|
||||||
SQLPP_ALIAS_PROVIDER(q)
|
SQLPP_ALIAS_PROVIDER(q)
|
||||||
SQLPP_ALIAS_PROVIDER(s)
|
SQLPP_ALIAS_PROVIDER(s)
|
||||||
SQLPP_ALIAS_PROVIDER(t)
|
SQLPP_ALIAS_PROVIDER(t)
|
||||||
SQLPP_ALIAS_PROVIDER(u)
|
SQLPP_ALIAS_PROVIDER(u)
|
||||||
SQLPP_ALIAS_PROVIDER(v)
|
SQLPP_ALIAS_PROVIDER(v)
|
||||||
SQLPP_ALIAS_PROVIDER(w)
|
SQLPP_ALIAS_PROVIDER(w)
|
||||||
SQLPP_ALIAS_PROVIDER(x)
|
SQLPP_ALIAS_PROVIDER(x)
|
||||||
SQLPP_ALIAS_PROVIDER(y)
|
SQLPP_ALIAS_PROVIDER(y)
|
||||||
SQLPP_ALIAS_PROVIDER(z)
|
SQLPP_ALIAS_PROVIDER(z)
|
||||||
SQLPP_ALIAS_PROVIDER(left)
|
SQLPP_ALIAS_PROVIDER(left)
|
||||||
SQLPP_ALIAS_PROVIDER(right)
|
SQLPP_ALIAS_PROVIDER(right)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -33,48 +33,46 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Table>
|
template <typename Table>
|
||||||
struct all_of_t
|
struct all_of_t
|
||||||
{
|
{
|
||||||
using _column_tuple_t = typename Table::_column_tuple_t;
|
using _column_tuple_t = typename Table::_column_tuple_t;
|
||||||
|
|
||||||
template<typename AliasProvider>
|
template <typename AliasProvider>
|
||||||
detail::copy_tuple_args_t<multi_column_alias_t, AliasProvider, _column_tuple_t> as(const AliasProvider& alias)
|
detail::copy_tuple_args_t<multi_column_alias_t, AliasProvider, _column_tuple_t> as(const AliasProvider& alias)
|
||||||
{
|
{
|
||||||
return multi_column(_column_tuple_t{}).as(alias);
|
return multi_column(_column_tuple_t{}).as(alias);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Table>
|
template <typename Table>
|
||||||
auto all_of(Table) -> all_of_t<Table>
|
auto all_of(Table) -> all_of_t<Table>
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct assert_no_stand_alone_all_of_t
|
struct assert_no_stand_alone_all_of_t
|
||||||
{
|
{
|
||||||
using type = std::false_type;
|
using type = std::false_type;
|
||||||
|
|
||||||
template<typename T = void>
|
template <typename T = void>
|
||||||
static void _()
|
static void _()
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "all_of(table) seems to be used outside of select");
|
static_assert(wrong_t<T>::value, "all_of(table) seems to be used outside of select");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Table>
|
template <typename Context, typename Table>
|
||||||
struct serializer_t<Context, all_of_t<Table>>
|
struct serializer_t<Context, all_of_t<Table>>
|
||||||
{
|
{
|
||||||
using _serialize_check = assert_no_stand_alone_all_of_t;
|
using _serialize_check = assert_no_stand_alone_all_of_t;
|
||||||
using T = all_of_t<Table>;
|
using T = all_of_t<Table>;
|
||||||
|
|
||||||
static Context& _(const T&, const Context&)
|
|
||||||
{
|
|
||||||
_serialize_check::_();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T&, const Context&)
|
||||||
|
{
|
||||||
|
_serialize_check::_();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -33,49 +33,49 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Select>
|
template <typename Select>
|
||||||
struct any_t
|
struct any_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<value_type_of<Select>, tag::is_multi_expression>;
|
using _traits = make_traits<value_type_of<Select>, tag::is_multi_expression>;
|
||||||
using _nodes = detail::type_vector<Select>;
|
using _nodes = detail::type_vector<Select>;
|
||||||
|
|
||||||
any_t(Select select):
|
any_t(Select select) : _select(select)
|
||||||
_select(select)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
any_t(const any_t&) = default;
|
any_t(const any_t&) = default;
|
||||||
any_t(any_t&&) = default;
|
any_t(any_t&&) = default;
|
||||||
any_t& operator=(const any_t&) = default;
|
any_t& operator=(const any_t&) = default;
|
||||||
any_t& operator=(any_t&&) = default;
|
any_t& operator=(any_t&&) = default;
|
||||||
~any_t() = default;
|
~any_t() = default;
|
||||||
|
|
||||||
Select _select;
|
Select _select;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Select>
|
template <typename Context, typename Select>
|
||||||
struct serializer_t<Context, any_t<Select>>
|
struct serializer_t<Context, any_t<Select>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Select>;
|
using _serialize_check = serialize_check_of<Context, Select>;
|
||||||
using T = any_t<Select>;
|
using T = any_t<Select>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "ANY(";
|
context << "ANY(";
|
||||||
serialize(t._select, context);
|
serialize(t._select, context);
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto any(T t) -> any_t<wrap_operand_t<T>>
|
|
||||||
{
|
|
||||||
static_assert(is_select_t<wrap_operand_t<T>>::value, "any() requires a select expression as argument");
|
|
||||||
static_assert(is_expression_t<wrap_operand_t<T>>::value, "any() requires a single column select expression as argument");
|
|
||||||
// FIXME: can we accept non-values like NULL here?
|
|
||||||
return { t };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto any(T t) -> any_t<wrap_operand_t<T>>
|
||||||
|
{
|
||||||
|
static_assert(is_select_t<wrap_operand_t<T>>::value, "any() requires a select expression as argument");
|
||||||
|
static_assert(is_expression_t<wrap_operand_t<T>>::value,
|
||||||
|
"any() requires a single column select expression as argument");
|
||||||
|
// FIXME: can we accept non-values like NULL here?
|
||||||
|
return {t};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,46 +37,46 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
struct assignment_t
|
struct assignment_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_assignment>;
|
using _traits = make_traits<no_value_t, tag::is_assignment>;
|
||||||
using _lhs_t = Lhs;
|
using _lhs_t = Lhs;
|
||||||
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
|
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
|
||||||
using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
|
using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
|
||||||
|
|
||||||
static_assert(can_be_null_t<_lhs_t>::value ? true : not (std::is_same<_rhs_t, null_t>::value or is_tvin_t<_rhs_t>::value), "column must not be null");
|
static_assert(can_be_null_t<_lhs_t>::value ? true
|
||||||
|
: not(std::is_same<_rhs_t, null_t>::value or is_tvin_t<_rhs_t>::value),
|
||||||
|
"column must not be null");
|
||||||
|
|
||||||
assignment_t(_lhs_t lhs, _rhs_t rhs):
|
assignment_t(_lhs_t lhs, _rhs_t rhs) : _lhs(lhs), _rhs(rhs)
|
||||||
_lhs(lhs),
|
{
|
||||||
_rhs(rhs)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
assignment_t(const assignment_t&) = default;
|
assignment_t(const assignment_t&) = default;
|
||||||
assignment_t(assignment_t&&) = default;
|
assignment_t(assignment_t&&) = default;
|
||||||
assignment_t& operator=(const assignment_t&) = default;
|
assignment_t& operator=(const assignment_t&) = default;
|
||||||
assignment_t& operator=(assignment_t&&) = default;
|
assignment_t& operator=(assignment_t&&) = default;
|
||||||
~assignment_t() = default;
|
~assignment_t() = default;
|
||||||
|
|
||||||
_lhs_t _lhs;
|
_lhs_t _lhs;
|
||||||
_rhs_t _rhs;
|
_rhs_t _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Lhs, typename Rhs>
|
template <typename Context, typename Lhs, typename Rhs>
|
||||||
struct serializer_t<Context, assignment_t<Lhs, Rhs>>
|
struct serializer_t<Context, assignment_t<Lhs, Rhs>>
|
||||||
{
|
{
|
||||||
using T = assignment_t<Lhs, Rhs>;
|
using T = assignment_t<Lhs, Rhs>;
|
||||||
using _serialize_check = serialize_check_of<Context, typename T::_lhs_t, typename T::_rhs_t>;
|
using _serialize_check = serialize_check_of<Context, typename T::_lhs_t, typename T::_rhs_t>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
serialize(simple_column(t._lhs), context);
|
|
||||||
context << "=";
|
|
||||||
serialize_operand(t._rhs, context);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
serialize(simple_column(t._lhs), context);
|
||||||
|
context << "=";
|
||||||
|
serialize_operand(t._rhs, context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,36 +31,35 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename T, typename Enable = void>
|
template <typename T, typename Enable = void>
|
||||||
struct has_auto_alias_t
|
struct has_auto_alias_t
|
||||||
{
|
{
|
||||||
static constexpr bool value = false;
|
static constexpr bool value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct has_auto_alias_t<T, typename std::enable_if<not wrong_t<typename T::_auto_alias_t>::value>::type>
|
struct has_auto_alias_t<T, typename std::enable_if<not wrong_t<typename T::_auto_alias_t>::value>::type>
|
||||||
{
|
{
|
||||||
static constexpr bool value = true;
|
static constexpr bool value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename T, typename Enable = void>
|
template <typename T, typename Enable = void>
|
||||||
struct auto_alias_impl
|
struct auto_alias_impl
|
||||||
{
|
{
|
||||||
using type = T;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct auto_alias_impl<T, typename std::enable_if<has_auto_alias_t<T>::value>::type>
|
struct auto_alias_impl<T, typename std::enable_if<has_auto_alias_t<T>::value>::type>
|
||||||
{
|
{
|
||||||
using type = expression_alias_t<T, typename T::_auto_alias_t>;
|
using type = expression_alias_t<T, typename T::_auto_alias_t>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
using auto_alias_t = typename detail::auto_alias_impl<T>::type;
|
using auto_alias_t = typename detail::auto_alias_impl<T>::type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,88 +32,95 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct avg_alias_t
|
struct avg_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "avg_";
|
static constexpr const char _literal[] = "avg_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T avg;
|
T avg;
|
||||||
T& operator()() { return avg; }
|
T& operator()()
|
||||||
const T& operator()() const { return avg; }
|
{
|
||||||
};
|
return avg;
|
||||||
};
|
}
|
||||||
};
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return avg;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Flag, typename Expr>
|
template <typename Flag, typename Expr>
|
||||||
struct avg_t:
|
struct avg_t : public expression_operators<avg_t<Flag, Expr>, floating_point>,
|
||||||
public expression_operators<avg_t<Flag, Expr>, floating_point>,
|
public alias_operators<avg_t<Flag, Expr>>
|
||||||
public alias_operators<avg_t<Flag, Expr>>
|
{
|
||||||
{
|
using _traits = make_traits<floating_point, tag::is_expression, tag::is_selectable>;
|
||||||
using _traits = make_traits<floating_point, tag::is_expression, tag::is_selectable>;
|
using _nodes = detail::type_vector<Expr, aggregate_function>;
|
||||||
using _nodes = detail::type_vector<Expr, aggregate_function>;
|
|
||||||
|
|
||||||
static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "avg() used with flag other than 'distinct'");
|
static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value,
|
||||||
static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument");
|
"avg() used with flag other than 'distinct'");
|
||||||
|
static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument");
|
||||||
|
|
||||||
using _auto_alias_t = avg_alias_t;
|
using _auto_alias_t = avg_alias_t;
|
||||||
|
|
||||||
avg_t(Expr expr):
|
avg_t(Expr expr) : _expr(expr)
|
||||||
_expr(expr)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
avg_t(const avg_t&) = default;
|
avg_t(const avg_t&) = default;
|
||||||
avg_t(avg_t&&) = default;
|
avg_t(avg_t&&) = default;
|
||||||
avg_t& operator=(const avg_t&) = default;
|
avg_t& operator=(const avg_t&) = default;
|
||||||
avg_t& operator=(avg_t&&) = default;
|
avg_t& operator=(avg_t&&) = default;
|
||||||
~avg_t() = default;
|
~avg_t() = default;
|
||||||
|
|
||||||
Expr _expr;
|
Expr _expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Flag, typename Expr>
|
template <typename Context, typename Flag, typename Expr>
|
||||||
struct serializer_t<Context, avg_t<Flag, Expr>>
|
struct serializer_t<Context, avg_t<Flag, Expr>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Flag, Expr>;
|
using _serialize_check = serialize_check_of<Context, Flag, Expr>;
|
||||||
using T = avg_t<Flag, Expr>;
|
using T = avg_t<Flag, Expr>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "AVG(";
|
context << "AVG(";
|
||||||
if (std::is_same<distinct_t, Flag>::value)
|
if (std::is_same<distinct_t, Flag>::value)
|
||||||
{
|
{
|
||||||
serialize(Flag(), context);
|
serialize(Flag(), context);
|
||||||
context << ' ';
|
context << ' ';
|
||||||
serialize_operand(t._expr, context);
|
serialize_operand(t._expr, context);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
serialize(t._expr, context);
|
serialize(t._expr, context);
|
||||||
}
|
}
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto avg(T t) -> avg_t<noop, wrap_operand_t<T>>
|
auto avg(T t) -> avg_t<noop, wrap_operand_t<T>>
|
||||||
{
|
{
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "avg() cannot be used on an aggregate function");
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
|
"avg() cannot be used on an aggregate function");
|
||||||
return { t };
|
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
|
||||||
}
|
return {t};
|
||||||
|
}
|
||||||
template<typename T>
|
|
||||||
auto avg(const distinct_t&, T t) -> avg_t<distinct_t, wrap_operand_t<T>>
|
|
||||||
{
|
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "avg() cannot be used on an aggregate function");
|
|
||||||
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
|
|
||||||
return { t };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto avg(const distinct_t&, T t) -> avg_t<distinct_t, wrap_operand_t<T>>
|
||||||
|
{
|
||||||
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
|
"avg() cannot be used on an aggregate function");
|
||||||
|
static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
|
||||||
|
return {t};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,13 +29,13 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct bad_statement
|
struct bad_statement
|
||||||
{
|
{
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
bad_statement(T&&...) {}
|
bad_statement(T&&...)
|
||||||
};
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,119 +38,122 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// basic operators
|
// basic operators
|
||||||
template<typename Expr, typename ValueType>
|
template <typename Expr, typename ValueType>
|
||||||
struct basic_expression_operators
|
struct basic_expression_operators
|
||||||
{
|
{
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _is_valid_comparison_operand
|
struct _is_valid_comparison_operand
|
||||||
{
|
{
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
(is_expression_t<T>::value // expressions are OK
|
(is_expression_t<T>::value // expressions are OK
|
||||||
or is_multi_expression_t<T>::value) // multi-expressions like ANY are OK for comparisons, too
|
or
|
||||||
and ValueType::template _is_valid_operand<T>::value // the correct value type is required, of course
|
is_multi_expression_t<T>::value) // multi-expressions like ANY are OK for comparisons, too
|
||||||
;
|
and
|
||||||
};
|
ValueType::template _is_valid_operand<T>::value // the correct value type is required, of course
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
equal_to_t<Expr, wrap_operand_t<T>> operator==(T t) const
|
equal_to_t<Expr, wrap_operand_t<T>> operator==(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), {rhs{t}} };
|
return {*static_cast<const Expr*>(this), {rhs{t}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
not_equal_to_t<Expr, wrap_operand_t<T>> operator!=(T t) const
|
not_equal_to_t<Expr, wrap_operand_t<T>> operator!=(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), {rhs{t}} };
|
return {*static_cast<const Expr*>(this), {rhs{t}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
less_than_t<Expr, wrap_operand_t<T>> operator<(T t) const
|
less_than_t<Expr, wrap_operand_t<T>> operator<(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), rhs{t} };
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
less_equal_t<Expr, wrap_operand_t<T>> operator<=(T t) const
|
less_equal_t<Expr, wrap_operand_t<T>> operator<=(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), rhs{t} };
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
greater_than_t<Expr, wrap_operand_t<T>> operator>(T t) const
|
greater_than_t<Expr, wrap_operand_t<T>> operator>(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), rhs{t} };
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
greater_equal_t<Expr, wrap_operand_t<T>> operator>=(T t) const
|
greater_equal_t<Expr, wrap_operand_t<T>> operator>=(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), rhs{t} };
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
is_null_t<Expr> is_null() const
|
is_null_t<Expr> is_null() const
|
||||||
{
|
{
|
||||||
return { *static_cast<const Expr*>(this) };
|
return {*static_cast<const Expr*>(this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
is_not_null_t<Expr> is_not_null() const
|
is_not_null_t<Expr> is_not_null() const
|
||||||
{
|
{
|
||||||
return { *static_cast<const Expr*>(this) };
|
return {*static_cast<const Expr*>(this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
sort_order_t<Expr, sort_type::asc> asc() const
|
sort_order_t<Expr, sort_type::asc> asc() const
|
||||||
{
|
{
|
||||||
return { *static_cast<const Expr*>(this) };
|
return {*static_cast<const Expr*>(this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
sort_order_t<Expr, sort_type::desc> desc() const
|
sort_order_t<Expr, sort_type::desc> desc() const
|
||||||
{
|
{
|
||||||
return { *static_cast<const Expr*>(this) };
|
return {*static_cast<const Expr*>(this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hint: use value_list wrapper for containers...
|
// Hint: use value_list wrapper for containers...
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
in_t<Expr, wrap_operand_t<T>...> in(T... t) const
|
in_t<Expr, wrap_operand_t<T>...> in(T... t) const
|
||||||
{
|
{
|
||||||
static_assert(logic::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid");
|
static_assert(logic::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value,
|
||||||
return { *static_cast<const Expr*>(this), wrap_operand_t<T>{t}... };
|
"at least one operand of in() is not valid");
|
||||||
}
|
return {*static_cast<const Expr*>(this), wrap_operand_t<T>{t}...};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
not_in_t<Expr, wrap_operand_t<T>...> not_in(T... t) const
|
not_in_t<Expr, wrap_operand_t<T>...> not_in(T... t) const
|
||||||
{
|
{
|
||||||
static_assert(logic::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid");
|
static_assert(logic::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value,
|
||||||
return { *static_cast<const Expr*>(this), wrap_operand_t<T>{t}... };
|
"at least one operand of in() is not valid");
|
||||||
}
|
return {*static_cast<const Expr*>(this), wrap_operand_t<T>{t}...};
|
||||||
};
|
}
|
||||||
|
};
|
||||||
template<typename Expr>
|
|
||||||
struct alias_operators
|
|
||||||
{
|
|
||||||
template<typename alias_provider>
|
|
||||||
expression_alias_t<Expr, alias_provider> as(const alias_provider&) const
|
|
||||||
{
|
|
||||||
return { *static_cast<const Expr*>(this) };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template <typename Expr>
|
||||||
|
struct alias_operators
|
||||||
|
{
|
||||||
|
template <typename alias_provider>
|
||||||
|
expression_alias_t<Expr, alias_provider> as(const alias_provider&) const
|
||||||
|
{
|
||||||
|
return {*static_cast<const Expr*>(this)};
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,199 +37,197 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// boolean value type
|
// boolean value type
|
||||||
struct boolean
|
struct boolean
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean, tag::is_value_type>;
|
using _traits = make_traits<boolean, tag::is_value_type>;
|
||||||
using _tag = tag::is_boolean;
|
using _tag = tag::is_boolean;
|
||||||
using _cpp_value_type = bool;
|
using _cpp_value_type = bool;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_boolean_t<T>;
|
using _is_valid_operand = is_boolean_t<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// boolean parameter type
|
// boolean parameter type
|
||||||
template<>
|
template <>
|
||||||
struct parameter_value_t<boolean>
|
struct parameter_value_t<boolean>
|
||||||
{
|
{
|
||||||
using _value_type = boolean; // FIXME
|
using _value_type = boolean; // FIXME
|
||||||
using _cpp_value_type = typename _value_type::_cpp_value_type;
|
using _cpp_value_type = typename _value_type::_cpp_value_type;
|
||||||
|
|
||||||
parameter_value_t():
|
parameter_value_t() : _value(false), _is_null(true)
|
||||||
_value(false),
|
{
|
||||||
_is_null(true)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
parameter_value_t(const _cpp_value_type& val):
|
parameter_value_t(const _cpp_value_type& val) : _value(val), _is_null(false)
|
||||||
_value(val),
|
{
|
||||||
_is_null(false)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
parameter_value_t& operator=(const _cpp_value_type& val)
|
parameter_value_t& operator=(const _cpp_value_type& val)
|
||||||
{
|
{
|
||||||
_value = val;
|
_value = val;
|
||||||
_is_null = false;
|
_is_null = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
|
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
|
||||||
{
|
{
|
||||||
if (t._is_trivial())
|
if (t._is_trivial())
|
||||||
{
|
{
|
||||||
_value = false;
|
_value = false;
|
||||||
_is_null = true;
|
_is_null = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_value = t._value._t;
|
_value = t._value._t;
|
||||||
_is_null = false;
|
_is_null = false;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_value_t& operator=(const std::nullptr_t&)
|
parameter_value_t& operator=(const std::nullptr_t&)
|
||||||
{
|
{
|
||||||
_value = false;
|
_value = false;
|
||||||
_is_null = true;
|
_is_null = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_null() const
|
bool is_null() const
|
||||||
{
|
{
|
||||||
return _is_null;
|
return _is_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cpp_value_type value() const
|
_cpp_value_type value() const
|
||||||
{
|
{
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator _cpp_value_type() const { return value(); }
|
operator _cpp_value_type() const
|
||||||
|
{
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Target>
|
template <typename Target>
|
||||||
void _bind(Target& target, size_t index) const
|
void _bind(Target& target, size_t index) const
|
||||||
{
|
{
|
||||||
target._bind_boolean_parameter(index, &_value, _is_null);
|
target._bind_boolean_parameter(index, &_value, _is_null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
signed char _value;
|
signed char _value;
|
||||||
bool _is_null;
|
bool _is_null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// boolean expression operators
|
// boolean expression operators
|
||||||
template<typename Base>
|
template <typename Base>
|
||||||
struct expression_operators<Base, boolean>: public basic_expression_operators<Base, boolean>
|
struct expression_operators<Base, boolean> : public basic_expression_operators<Base, boolean>
|
||||||
{
|
{
|
||||||
template<typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_valid_operand<boolean, T>;
|
using _is_valid_operand = is_valid_operand<boolean, T>;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
logical_and_t<Base, wrap_operand_t<T>> operator and(T t) const
|
logical_and_t<Base, wrap_operand_t<T>> operator and(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), rhs{t} };
|
return {*static_cast<const Base*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
logical_or_t<Base, wrap_operand_t<T>> operator or(T t) const
|
logical_or_t<Base, wrap_operand_t<T>> operator or(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), rhs{t} };
|
return {*static_cast<const Base*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
logical_not_t<Base> operator not() const
|
logical_not_t<Base> operator not() const
|
||||||
{
|
{
|
||||||
return { *static_cast<const Base*>(this) };
|
return {*static_cast<const Base*>(this)};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// boolean column operators
|
// boolean column operators
|
||||||
template<typename Base>
|
template <typename Base>
|
||||||
struct column_operators<Base, boolean>
|
struct column_operators<Base, boolean>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
// boolean result field
|
// boolean result field
|
||||||
template<typename Db, typename FieldSpec>
|
template <typename Db, typename FieldSpec>
|
||||||
struct result_field_t<boolean, Db, FieldSpec>: public result_field_methods_t<result_field_t<boolean, Db, FieldSpec>>
|
struct result_field_t<boolean, Db, FieldSpec> : public result_field_methods_t<result_field_t<boolean, Db, FieldSpec>>
|
||||||
{
|
{
|
||||||
static_assert(std::is_same<value_type_of<FieldSpec>, boolean>::value, "field type mismatch");
|
static_assert(std::is_same<value_type_of<FieldSpec>, boolean>::value, "field type mismatch");
|
||||||
using _cpp_value_type = typename boolean::_cpp_value_type;
|
using _cpp_value_type = typename boolean::_cpp_value_type;
|
||||||
|
|
||||||
result_field_t():
|
result_field_t() : _is_valid(false), _is_null(true), _value(false)
|
||||||
_is_valid(false),
|
{
|
||||||
_is_null(true),
|
}
|
||||||
_value(false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void _validate()
|
void _validate()
|
||||||
{
|
{
|
||||||
_is_valid = true;
|
_is_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _invalidate()
|
void _invalidate()
|
||||||
{
|
{
|
||||||
_is_valid = false;
|
_is_valid = false;
|
||||||
_is_null = true;
|
_is_null = true;
|
||||||
_value = 0;
|
_value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_null() const
|
bool is_null() const
|
||||||
{
|
{
|
||||||
if (not _is_valid)
|
if (not _is_valid)
|
||||||
throw exception("accessing is_null in non-existing row");
|
throw exception("accessing is_null in non-existing row");
|
||||||
return _is_null;
|
return _is_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _is_trivial() const
|
bool _is_trivial() const
|
||||||
{
|
{
|
||||||
if (not _is_valid)
|
if (not _is_valid)
|
||||||
throw exception("accessing is_null in non-existing row");
|
throw exception("accessing is_null in non-existing row");
|
||||||
|
|
||||||
return value() == false;
|
return value() == false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cpp_value_type value() const
|
_cpp_value_type value() const
|
||||||
{
|
{
|
||||||
if (not _is_valid)
|
if (not _is_valid)
|
||||||
throw exception("accessing value in non-existing row");
|
throw exception("accessing value in non-existing row");
|
||||||
|
|
||||||
if (_is_null)
|
if (_is_null)
|
||||||
{
|
{
|
||||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||||
{
|
{
|
||||||
throw exception("accessing value of NULL field");
|
throw exception("accessing value of NULL field");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Target>
|
template <typename Target>
|
||||||
void _bind(Target& target, size_t i)
|
void _bind(Target& target, size_t i)
|
||||||
{
|
{
|
||||||
target._bind_boolean_result(i, &_value, &_is_null);
|
target._bind_boolean_result(i, &_value, &_is_null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _is_valid;
|
bool _is_valid;
|
||||||
bool _is_null;
|
bool _is_null;
|
||||||
signed char _value;
|
signed char _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Db, typename FieldSpec>
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, const result_field_t<boolean, Db, FieldSpec>& e)
|
|
||||||
{
|
|
||||||
return serialize(e, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename Db, typename FieldSpec>
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const result_field_t<boolean, Db, FieldSpec>& e)
|
||||||
|
{
|
||||||
|
return serialize(e, os);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,54 +32,53 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Database>
|
template <typename Database>
|
||||||
struct boolean_expression_t: public expression_operators<boolean_expression_t<Database>, boolean>
|
struct boolean_expression_t : public expression_operators<boolean_expression_t<Database>, boolean>
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean, tag::is_expression>;
|
using _traits = make_traits<boolean, tag::is_expression>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
template<typename Expr>
|
template <typename Expr>
|
||||||
boolean_expression_t(Expr expr):
|
boolean_expression_t(Expr expr)
|
||||||
_expr(expr)
|
: _expr(expr)
|
||||||
{
|
{
|
||||||
static_assert(is_expression_t<Expr>::value, "boolean_expression requires a boolean expression argument");
|
static_assert(is_expression_t<Expr>::value, "boolean_expression requires a boolean expression argument");
|
||||||
static_assert(is_boolean_t<Expr>::value, "boolean_expression requires a boolean expression argument");
|
static_assert(is_boolean_t<Expr>::value, "boolean_expression requires a boolean expression argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean_expression_t(const boolean_expression_t&) = default;
|
boolean_expression_t(const boolean_expression_t&) = default;
|
||||||
boolean_expression_t(boolean_expression_t&&) = default;
|
boolean_expression_t(boolean_expression_t&&) = default;
|
||||||
boolean_expression_t& operator=(const boolean_expression_t&) = default;
|
boolean_expression_t& operator=(const boolean_expression_t&) = default;
|
||||||
boolean_expression_t& operator=(boolean_expression_t&&) = default;
|
boolean_expression_t& operator=(boolean_expression_t&&) = default;
|
||||||
~boolean_expression_t() = default;
|
~boolean_expression_t() = default;
|
||||||
|
|
||||||
interpretable_t<Database> _expr;
|
interpretable_t<Database> _expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Database, typename T>
|
template <typename Database, typename T>
|
||||||
boolean_expression_t<Database> boolean_expression(T t)
|
boolean_expression_t<Database> boolean_expression(T t)
|
||||||
{
|
{
|
||||||
using Expr = wrap_operand_t<T>;
|
using Expr = wrap_operand_t<T>;
|
||||||
return {Expr{t}};
|
return {Expr{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename T>
|
template <typename Database, typename T>
|
||||||
boolean_expression_t<Database> boolean_expression(const Database&, T t)
|
boolean_expression_t<Database> boolean_expression(const Database&, T t)
|
||||||
{
|
{
|
||||||
return boolean_expression<Database>(t);
|
return boolean_expression<Database>(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Context, typename Database>
|
template <typename Context, typename Database>
|
||||||
struct serializer_t<Context, boolean_expression_t<Database>>
|
struct serializer_t<Context, boolean_expression_t<Database>>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = boolean_expression_t<Database>;
|
using T = boolean_expression_t<Database>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
return serialize(t._expr, context);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
return serialize(t._expr, context);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,26 +31,28 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<char... Cs> struct char_sequence
|
template <char... Cs>
|
||||||
{
|
struct char_sequence
|
||||||
static const char* char_ptr()
|
{
|
||||||
{
|
static const char* char_ptr()
|
||||||
static char s[] = {Cs...};
|
{
|
||||||
return s;
|
static char s[] = {Cs...};
|
||||||
};
|
return s;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
template<std::size_t N, const char (&s) [N], typename T>
|
template <std::size_t N, const char(&s)[N], typename T>
|
||||||
struct make_char_sequence_impl;
|
struct make_char_sequence_impl;
|
||||||
|
|
||||||
template<std::size_t N, const char (&s) [N], std::size_t... i>
|
template <std::size_t N, const char(&s)[N], std::size_t... i>
|
||||||
struct make_char_sequence_impl<N, s, sqlpp::detail::index_sequence<i...>>
|
struct make_char_sequence_impl<N, s, sqlpp::detail::index_sequence<i...>>
|
||||||
{
|
{
|
||||||
using type = char_sequence<s[i]...>;
|
using type = char_sequence<s[i]...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::size_t N, const char (&Input) [N]>
|
template <std::size_t N, const char(&Input)[N]>
|
||||||
using make_char_sequence = typename make_char_sequence_impl<sizeof(Input), Input, sqlpp::detail::make_index_sequence<sizeof(Input)>>::type;
|
using make_char_sequence =
|
||||||
|
typename make_char_sequence_impl<sizeof(Input), Input, sqlpp::detail::make_index_sequence<sizeof(Input)>>::type;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -41,84 +41,81 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Table, typename ColumnSpec>
|
template <typename Table, typename ColumnSpec>
|
||||||
struct column_t:
|
struct column_t : public expression_operators<column_t<Table, ColumnSpec>, value_type_of<ColumnSpec>>,
|
||||||
public expression_operators<column_t<Table, ColumnSpec>, value_type_of<ColumnSpec>>,
|
public column_operators<column_t<Table, ColumnSpec>, value_type_of<ColumnSpec>>
|
||||||
public column_operators<column_t<Table, ColumnSpec>, value_type_of<ColumnSpec>>
|
{
|
||||||
{
|
struct _traits
|
||||||
struct _traits
|
{
|
||||||
{
|
using _value_type = value_type_of<ColumnSpec>;
|
||||||
using _value_type = value_type_of<ColumnSpec>;
|
using _tags = detail::make_joined_set_t<detail::type_set<tag::is_column, tag::is_expression, tag::is_selectable>,
|
||||||
using _tags = detail::make_joined_set_t<detail::type_set<tag::is_column, tag::is_expression, tag::is_selectable>, typename ColumnSpec::_traits::_tags>;
|
typename ColumnSpec::_traits::_tags>;
|
||||||
};
|
};
|
||||||
|
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _required_tables = detail::type_set<Table>;
|
using _required_tables = detail::type_set<Table>;
|
||||||
using _can_be_null = column_spec_can_be_null_t<ColumnSpec>;
|
using _can_be_null = column_spec_can_be_null_t<ColumnSpec>;
|
||||||
|
|
||||||
using _spec_t = ColumnSpec;
|
using _spec_t = ColumnSpec;
|
||||||
using _table = Table;
|
using _table = Table;
|
||||||
using _alias_t = typename _spec_t::_alias_t;
|
using _alias_t = typename _spec_t::_alias_t;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_valid_operand<value_type_of<ColumnSpec>, T>;
|
using _is_valid_operand = is_valid_operand<value_type_of<ColumnSpec>, T>;
|
||||||
|
|
||||||
column_t() = default;
|
column_t() = default;
|
||||||
column_t(const column_t&) = default;
|
column_t(const column_t&) = default;
|
||||||
column_t(column_t&&) = default;
|
column_t(column_t&&) = default;
|
||||||
column_t& operator=(const column_t&) = default;
|
column_t& operator=(const column_t&) = default;
|
||||||
column_t& operator=(column_t&&) = default;
|
column_t& operator=(column_t&&) = default;
|
||||||
~column_t() = default;
|
~column_t() = default;
|
||||||
|
|
||||||
template<typename T = _table>
|
template <typename T = _table>
|
||||||
auto table() const -> _table
|
auto table() const -> _table
|
||||||
{
|
{
|
||||||
static_assert(is_table_t<T>::value, "cannot call get_table for columns of a sub-selects or cte");
|
static_assert(is_table_t<T>::value, "cannot call get_table for columns of a sub-selects or cte");
|
||||||
return _table{};
|
return _table{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename alias_provider>
|
template <typename alias_provider>
|
||||||
expression_alias_t<column_t, alias_provider> as(const alias_provider&) const
|
expression_alias_t<column_t, alias_provider> as(const alias_provider&) const
|
||||||
{
|
{
|
||||||
return { *this };
|
return {*this};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto operator =(T t) const -> assignment_t<column_t, wrap_operand_t<T>>
|
auto operator=(T t) const -> assignment_t<column_t, wrap_operand_t<T>>
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||||
|
|
||||||
return { *this, {rhs{t}} };
|
return {*this, {rhs{t}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto operator =(null_t) const
|
auto operator=(null_t) const -> assignment_t<column_t, null_t>
|
||||||
->assignment_t<column_t, null_t>
|
{
|
||||||
{
|
static_assert(can_be_null_t<column_t>::value, "column cannot be null");
|
||||||
static_assert(can_be_null_t<column_t>::value, "column cannot be null");
|
return {*this, null_t{}};
|
||||||
return { *this, null_t{} };
|
}
|
||||||
}
|
|
||||||
|
|
||||||
auto operator =(default_value_t) const
|
auto operator=(default_value_t) const -> assignment_t<column_t, default_value_t>
|
||||||
->assignment_t<column_t, default_value_t>
|
{
|
||||||
{
|
return {*this, default_value_t{}};
|
||||||
return { *this, default_value_t{} };
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Context, typename... Args>
|
template <typename Context, typename... Args>
|
||||||
struct serializer_t<Context, column_t<Args...>>
|
struct serializer_t<Context, column_t<Args...>>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = column_t<Args...>;
|
using T = column_t<Args...>;
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
|
||||||
{
|
|
||||||
context << name_of<typename T::_table>::char_ptr() << '.' << name_of<T>::char_ptr();
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T&, Context& context)
|
||||||
|
{
|
||||||
|
context << name_of<typename T::_table>::char_ptr() << '.' << name_of<T>::char_ptr();
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,14 +24,13 @@
|
|||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef SQLPP_COLUMN_FWD_H
|
#ifndef SQLPP_COLUMN_FWD_H
|
||||||
#define SQLPP_COLUMN_FWD_H
|
#define SQLPP_COLUMN_FWD_H
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Table, typename ColumnSpec>
|
template <typename Table, typename ColumnSpec>
|
||||||
struct column_t;
|
struct column_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,69 +35,67 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct text;
|
struct text;
|
||||||
|
|
||||||
struct concat_alias_t
|
struct concat_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "concat_";
|
static constexpr const char _literal[] = "concat_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T concat;
|
T concat;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template <typename... Args>
|
||||||
struct concat_t:
|
struct concat_t : public expression_operators<concat_t<Args...>, text>, public alias_operators<concat_t<Args...>>
|
||||||
public expression_operators<concat_t<Args...>, text>,
|
{
|
||||||
public alias_operators<concat_t<Args...>>
|
using _traits = make_traits<text, tag::is_expression, tag::is_selectable>;
|
||||||
{
|
using _nodes = detail::type_vector<Args...>;
|
||||||
using _traits = make_traits<text, tag::is_expression, tag::is_selectable>;
|
|
||||||
using _nodes = detail::type_vector<Args...>;
|
|
||||||
|
|
||||||
using _auto_alias_t = concat_alias_t;
|
using _auto_alias_t = concat_alias_t;
|
||||||
|
|
||||||
concat_t(Args... args):
|
concat_t(Args... args) : _args(args...)
|
||||||
_args(args...)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
concat_t(const concat_t&) = default;
|
concat_t(const concat_t&) = default;
|
||||||
concat_t(concat_t&&) = default;
|
concat_t(concat_t&&) = default;
|
||||||
concat_t& operator=(const concat_t&) = default;
|
concat_t& operator=(const concat_t&) = default;
|
||||||
concat_t& operator=(concat_t&&) = default;
|
concat_t& operator=(concat_t&&) = default;
|
||||||
~concat_t() = default;
|
~concat_t() = default;
|
||||||
|
|
||||||
std::tuple<Args...> _args;
|
std::tuple<Args...> _args;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename... Args>
|
template <typename Context, typename... Args>
|
||||||
struct serializer_t<Context, concat_t<Args...>>
|
struct serializer_t<Context, concat_t<Args...>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Args...>;
|
using _serialize_check = serialize_check_of<Context, Args...>;
|
||||||
using T = concat_t<Args...>;
|
using T = concat_t<Args...>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "(";
|
context << "(";
|
||||||
interpret_tuple(t._args, "||", context);
|
interpret_tuple(t._args, "||", context);
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template <typename... Args>
|
||||||
auto concat(Args... args)
|
auto concat(Args... args) -> concat_t<Args...>
|
||||||
-> concat_t<Args...>
|
{
|
||||||
{
|
static_assert(sizeof...(Args) >= 2, "concat requires two arguments at least");
|
||||||
static_assert(sizeof...(Args) >= 2, "concat requires two arguments at least");
|
static_assert(logic::all_t<is_text_t<wrap_operand_t<Args>>::value...>::value,
|
||||||
static_assert(logic::all_t<is_text_t<wrap_operand_t<Args>>::value...>::value, "at least one non-text argument detected in concat()");
|
"at least one non-text argument detected in concat()");
|
||||||
|
|
||||||
return {args...};
|
return {args...};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,8 +29,9 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct connection {};
|
struct connection
|
||||||
|
{
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -33,89 +33,96 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct count_alias_t
|
struct count_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "count_";
|
static constexpr const char _literal[] = "count_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T count;
|
T count;
|
||||||
T& operator()() { return count; }
|
T& operator()()
|
||||||
const T& operator()() const { return count; }
|
{
|
||||||
};
|
return count;
|
||||||
};
|
}
|
||||||
};
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Flag, typename Expr>
|
template <typename Flag, typename Expr>
|
||||||
struct count_t:
|
struct count_t : public expression_operators<count_t<Flag, Expr>, integral>,
|
||||||
public expression_operators<count_t<Flag, Expr>, integral>,
|
public alias_operators<count_t<Flag, Expr>>
|
||||||
public alias_operators<count_t<Flag, Expr>>
|
{
|
||||||
{
|
using _traits = make_traits<integral, tag::is_expression /*, tag::is_selectable*/>;
|
||||||
using _traits = make_traits<integral, tag::is_expression/*, tag::is_selectable*/>;
|
|
||||||
|
|
||||||
using _nodes = detail::type_vector<Expr, aggregate_function>;
|
using _nodes = detail::type_vector<Expr, aggregate_function>;
|
||||||
using _can_be_null = std::false_type;
|
using _can_be_null = std::false_type;
|
||||||
|
|
||||||
static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value, "count() used with flag other than 'distinct'");
|
static_assert(is_noop<Flag>::value or std::is_same<distinct_t, Flag>::value,
|
||||||
|
"count() used with flag other than 'distinct'");
|
||||||
|
|
||||||
using _auto_alias_t = count_alias_t;
|
using _auto_alias_t = count_alias_t;
|
||||||
|
|
||||||
count_t(const Expr expr):
|
count_t(const Expr expr) : _expr(expr)
|
||||||
_expr(expr)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
count_t(const count_t&) = default;
|
count_t(const count_t&) = default;
|
||||||
count_t(count_t&&) = default;
|
count_t(count_t&&) = default;
|
||||||
count_t& operator=(const count_t&) = default;
|
count_t& operator=(const count_t&) = default;
|
||||||
count_t& operator=(count_t&&) = default;
|
count_t& operator=(count_t&&) = default;
|
||||||
~count_t() = default;
|
~count_t() = default;
|
||||||
|
|
||||||
Expr _expr;
|
Expr _expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Flag, typename Expr>
|
template <typename Context, typename Flag, typename Expr>
|
||||||
struct serializer_t<Context, count_t<Flag, Expr>>
|
struct serializer_t<Context, count_t<Flag, Expr>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Flag, Expr>;
|
using _serialize_check = serialize_check_of<Context, Flag, Expr>;
|
||||||
using T = count_t<Flag, Expr>;
|
using T = count_t<Flag, Expr>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "COUNT(";
|
context << "COUNT(";
|
||||||
if (std::is_same<distinct_t, Flag>::value)
|
if (std::is_same<distinct_t, Flag>::value)
|
||||||
{
|
{
|
||||||
serialize(Flag(), context);
|
serialize(Flag(), context);
|
||||||
context << ' ';
|
context << ' ';
|
||||||
serialize_operand(t._expr, context);
|
serialize_operand(t._expr, context);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
serialize(t._expr, context);
|
serialize(t._expr, context);
|
||||||
}
|
}
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto count(T t) -> count_t<noop, wrap_operand_t<T>>
|
auto count(T t) -> count_t<noop, wrap_operand_t<T>>
|
||||||
{
|
{
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "count() cannot be used on an aggregate function");
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
|
"count() cannot be used on an aggregate function");
|
||||||
return { t };
|
static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
|
||||||
}
|
return {t};
|
||||||
|
}
|
||||||
template<typename T>
|
|
||||||
auto count(const distinct_t&, T t) -> count_t<distinct_t, wrap_operand_t<T>>
|
|
||||||
{
|
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "count() cannot be used on an aggregate function");
|
|
||||||
static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
|
|
||||||
return { t };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto count(const distinct_t&, T t) -> count_t<distinct_t, wrap_operand_t<T>>
|
||||||
|
{
|
||||||
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
|
"count() cannot be used on an aggregate function");
|
||||||
|
static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
|
||||||
|
return {t};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,222 +40,226 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Flag, typename Lhs, typename Rhs>
|
template <typename Flag, typename Lhs, typename Rhs>
|
||||||
struct cte_union_t
|
struct cte_union_t
|
||||||
{
|
{
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Lhs>, required_ctes_of<Rhs>>;
|
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Lhs>, required_ctes_of<Rhs>>;
|
||||||
using _parameters = detail::type_vector_cat_t<parameters_of<Lhs>, parameters_of<Rhs>>;
|
using _parameters = detail::type_vector_cat_t<parameters_of<Lhs>, parameters_of<Rhs>>;
|
||||||
|
|
||||||
cte_union_t(Lhs lhs, Rhs rhs):
|
cte_union_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs)
|
||||||
_lhs(lhs),
|
{
|
||||||
_rhs(rhs)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
cte_union_t(const cte_union_t&) = default;
|
cte_union_t(const cte_union_t&) = default;
|
||||||
cte_union_t(cte_union_t&&) = default;
|
cte_union_t(cte_union_t&&) = default;
|
||||||
cte_union_t& operator=(const cte_union_t&) = default;
|
cte_union_t& operator=(const cte_union_t&) = default;
|
||||||
cte_union_t& operator=(cte_union_t&&) = default;
|
cte_union_t& operator=(cte_union_t&&) = default;
|
||||||
~cte_union_t() = default;
|
~cte_union_t() = default;
|
||||||
|
|
||||||
Lhs _lhs;
|
Lhs _lhs;
|
||||||
Rhs _rhs;
|
Rhs _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Interpreters
|
// Interpreters
|
||||||
template<typename Context, typename Flag, typename Lhs, typename Rhs>
|
template <typename Context, typename Flag, typename Lhs, typename Rhs>
|
||||||
struct serializer_t<Context, cte_union_t<Flag, Lhs, Rhs>>
|
struct serializer_t<Context, cte_union_t<Flag, Lhs, Rhs>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
|
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
|
||||||
using T = cte_union_t<Flag, Lhs, Rhs>;
|
using T = cte_union_t<Flag, Lhs, Rhs>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
serialize(t._lhs, context);
|
serialize(t._lhs, context);
|
||||||
context << " UNION ";
|
context << " UNION ";
|
||||||
serialize(Flag{}, context);
|
serialize(Flag{}, context);
|
||||||
context << " ";
|
context << " ";
|
||||||
serialize(t._rhs, context);
|
serialize(t._rhs, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
template <typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
struct cte_t;
|
struct cte_t;
|
||||||
|
|
||||||
template<typename AliasProvider>
|
template <typename AliasProvider>
|
||||||
struct cte_ref_t;
|
struct cte_ref_t;
|
||||||
|
|
||||||
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
template <typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
auto from_table(cte_t<AliasProvider, Statement, FieldSpecs...>) -> cte_ref_t<AliasProvider>
|
auto from_table(cte_t<AliasProvider, Statement, FieldSpecs...>) -> cte_ref_t<AliasProvider>
|
||||||
{
|
{
|
||||||
return cte_ref_t<AliasProvider>{};
|
return cte_ref_t<AliasProvider>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
template <typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
struct from_table_impl<cte_t<AliasProvider, Statement, FieldSpecs...>>
|
struct from_table_impl<cte_t<AliasProvider, Statement, FieldSpecs...>>
|
||||||
{
|
{
|
||||||
using type = cte_ref_t<AliasProvider>;
|
using type = cte_ref_t<AliasProvider>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename FieldSpec>
|
||||||
|
struct cte_column_spec_t
|
||||||
|
{
|
||||||
|
using _alias_t = typename FieldSpec::_alias_t;
|
||||||
|
|
||||||
template<typename FieldSpec>
|
using _traits = make_traits<value_type_of<FieldSpec>,
|
||||||
struct cte_column_spec_t
|
tag::must_not_insert,
|
||||||
{
|
tag::must_not_update,
|
||||||
using _alias_t = typename FieldSpec::_alias_t;
|
tag_if<tag::can_be_null, column_spec_can_be_null_t<FieldSpec>::value>>;
|
||||||
|
};
|
||||||
|
|
||||||
using _traits = make_traits<value_type_of<FieldSpec>,
|
template <typename AliasProvider, typename Statement, typename ResultRow>
|
||||||
tag::must_not_insert,
|
struct make_cte_impl
|
||||||
tag::must_not_update,
|
{
|
||||||
tag_if<tag::can_be_null, column_spec_can_be_null_t<FieldSpec>::value>
|
using type = void;
|
||||||
>;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename AliasProvider, typename Statement, typename ResultRow>
|
template <typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
struct make_cte_impl
|
struct make_cte_impl<AliasProvider, Statement, result_row_t<void, FieldSpecs...>>
|
||||||
{
|
{
|
||||||
using type = void;
|
using type = cte_t<AliasProvider, Statement, FieldSpecs...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
template <typename AliasProvider, typename Statement>
|
||||||
struct make_cte_impl<AliasProvider, Statement, result_row_t<void, FieldSpecs...>>
|
using make_cte_t = typename make_cte_impl<AliasProvider, Statement, get_result_row_t<Statement>>::type;
|
||||||
{
|
|
||||||
using type = cte_t<AliasProvider, Statement, FieldSpecs...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename AliasProvider, typename Statement>
|
template <typename AliasProvider, typename Statement, typename... FieldSpecs>
|
||||||
using make_cte_t = typename make_cte_impl<AliasProvider, Statement, get_result_row_t<Statement>>::type;
|
struct cte_t
|
||||||
|
: public member_t<cte_column_spec_t<FieldSpecs>, column_t<AliasProvider, cte_column_spec_t<FieldSpecs>>>...
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_cte, tag::is_table>; // FIXME: is table? really?
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
|
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Statement>, detail::type_set<AliasProvider>>;
|
||||||
|
using _parameters = parameters_of<Statement>;
|
||||||
|
|
||||||
template<typename AliasProvider, typename Statement, typename... FieldSpecs>
|
using _alias_t = typename AliasProvider::_alias_t;
|
||||||
struct cte_t: public member_t<cte_column_spec_t<FieldSpecs>, column_t<AliasProvider, cte_column_spec_t<FieldSpecs>>>...
|
constexpr static bool _is_recursive = detail::is_element_of<AliasProvider, required_ctes_of<Statement>>::value;
|
||||||
{
|
|
||||||
using _traits = make_traits<no_value_t, tag::is_cte, tag::is_table>; // FIXME: is table? really?
|
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Statement>, detail::type_set<AliasProvider>>;
|
|
||||||
using _parameters = parameters_of<Statement>;
|
|
||||||
|
|
||||||
using _alias_t = typename AliasProvider::_alias_t;
|
using _column_tuple_t = std::tuple<column_t<AliasProvider, cte_column_spec_t<FieldSpecs>>...>;
|
||||||
constexpr static bool _is_recursive = detail::is_element_of<AliasProvider, required_ctes_of<Statement>>::value;
|
|
||||||
|
|
||||||
using _column_tuple_t = std::tuple<column_t<AliasProvider, cte_column_spec_t<FieldSpecs>>...>;
|
template <typename... T>
|
||||||
|
using _check = logic::all_t<is_statement_t<T>::value...>;
|
||||||
|
|
||||||
template<typename... T>
|
using _result_row_t = result_row_t<void, FieldSpecs...>;
|
||||||
using _check = logic::all_t<is_statement_t<T>::value...>;
|
|
||||||
|
|
||||||
using _result_row_t = result_row_t<void, FieldSpecs...>;
|
template <typename Rhs>
|
||||||
|
auto union_distinct(Rhs rhs) const ->
|
||||||
|
typename std::conditional<_check<Rhs>::value,
|
||||||
|
cte_t<AliasProvider, cte_union_t<distinct_t, Statement, Rhs>, FieldSpecs...>,
|
||||||
|
bad_statement>::type
|
||||||
|
{
|
||||||
|
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
||||||
|
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
||||||
|
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
||||||
|
|
||||||
template<typename Rhs>
|
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value,
|
||||||
auto union_distinct(Rhs rhs) const
|
"both select statements in a union have to have the same result columns (type and name)");
|
||||||
-> typename std::conditional<_check<Rhs>::value, cte_t<AliasProvider, cte_union_t<distinct_t, Statement, Rhs>, FieldSpecs...>, bad_statement>::type
|
|
||||||
{
|
|
||||||
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
|
||||||
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
|
||||||
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
|
||||||
|
|
||||||
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
|
return _union_impl<void, distinct_t>(_check<Rhs>{}, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
return _union_impl<void, distinct_t>(_check<Rhs>{}, rhs);
|
template <typename Rhs>
|
||||||
}
|
auto union_all(Rhs rhs) const ->
|
||||||
|
typename std::conditional<_check<Rhs>::value,
|
||||||
|
cte_t<AliasProvider, cte_union_t<all_t, Statement, Rhs>, FieldSpecs...>,
|
||||||
|
bad_statement>::type
|
||||||
|
{
|
||||||
|
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
||||||
|
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
||||||
|
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
||||||
|
|
||||||
template<typename Rhs>
|
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value,
|
||||||
auto union_all(Rhs rhs) const
|
"both select statements in a union have to have the same result columns (type and name)");
|
||||||
-> typename std::conditional<_check<Rhs>::value, cte_t<AliasProvider, cte_union_t<all_t, Statement, Rhs>, FieldSpecs...>, bad_statement>::type
|
|
||||||
{
|
|
||||||
static_assert(is_statement_t<Rhs>::value, "argument of union call has to be a statement");
|
|
||||||
static_assert(has_policy_t<Rhs, is_select_t>::value, "argument of union call has to be a select");
|
|
||||||
static_assert(has_result_row_t<Rhs>::value, "argument of a union has to be a (complete) select statement");
|
|
||||||
|
|
||||||
static_assert(std::is_same<_result_row_t, get_result_row_t<Rhs>>::value, "both select statements in a union have to have the same result columns (type and name)");
|
return _union_impl<all_t>(_check<Rhs>{}, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
return _union_impl<all_t>(_check<Rhs>{}, rhs);
|
private:
|
||||||
}
|
template <typename Flag, typename Rhs>
|
||||||
|
auto _union_impl(const std::false_type&, Rhs rhs) const -> bad_statement;
|
||||||
|
|
||||||
private:
|
template <typename Flag, typename Rhs>
|
||||||
template<typename Flag, typename Rhs>
|
auto _union_impl(const std::true_type&, Rhs rhs) const
|
||||||
auto _union_impl(const std::false_type&, Rhs rhs) const
|
-> cte_t<AliasProvider, cte_union_t<Flag, Statement, Rhs>, FieldSpecs...>
|
||||||
-> bad_statement;
|
{
|
||||||
|
return cte_union_t<Flag, Statement, Rhs>{_statement, rhs};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Flag, typename Rhs>
|
public:
|
||||||
auto _union_impl(const std::true_type&, Rhs rhs) const
|
cte_t(Statement statement) : _statement(statement)
|
||||||
-> cte_t<AliasProvider, cte_union_t<Flag, Statement, Rhs>, FieldSpecs...>
|
{
|
||||||
{
|
}
|
||||||
return cte_union_t<Flag, Statement, Rhs>{_statement, rhs};
|
cte_t(const cte_t&) = default;
|
||||||
}
|
cte_t(cte_t&&) = default;
|
||||||
|
cte_t& operator=(const cte_t&) = default;
|
||||||
|
cte_t& operator=(cte_t&&) = default;
|
||||||
|
~cte_t() = default;
|
||||||
|
|
||||||
public:
|
Statement _statement;
|
||||||
|
};
|
||||||
|
|
||||||
cte_t(Statement statement): _statement(statement){}
|
template <typename Context, typename AliasProvider, typename Statement, typename... ColumnSpecs>
|
||||||
cte_t(const cte_t&) = default;
|
struct serializer_t<Context, cte_t<AliasProvider, Statement, ColumnSpecs...>>
|
||||||
cte_t(cte_t&&) = default;
|
{
|
||||||
cte_t& operator=(const cte_t&) = default;
|
using _serialize_check = serialize_check_of<Context, Statement>;
|
||||||
cte_t& operator=(cte_t&&) = default;
|
using T = cte_t<AliasProvider, Statement, ColumnSpecs...>;
|
||||||
~cte_t() = default;
|
|
||||||
|
|
||||||
Statement _statement;
|
static Context& _(const T& t, Context& context)
|
||||||
};
|
{
|
||||||
|
context << name_of<T>::char_ptr() << " AS (";
|
||||||
|
serialize(t._statement, context);
|
||||||
|
context << ")";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Context, typename AliasProvider, typename Statement, typename... ColumnSpecs>
|
// The cte_t is displayed as AliasProviderName except within the with:
|
||||||
struct serializer_t<Context, cte_t<AliasProvider, Statement, ColumnSpecs...>>
|
// - the with needs the
|
||||||
{
|
// AliasProviderName AS (ColumnNames) (select/union)
|
||||||
using _serialize_check = serialize_check_of<Context, Statement>;
|
// The result row of the select should not have dynamic parts
|
||||||
using T = cte_t<AliasProvider, Statement, ColumnSpecs...>;
|
template <typename AliasProvider>
|
||||||
|
struct cte_ref_t
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_cte, tag::is_table>; // FIXME: is table? really?
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
|
using _required_ctes = detail::make_type_set_t<AliasProvider>;
|
||||||
|
using _provided_tables = detail::type_set<AliasProvider>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
using _alias_t = typename AliasProvider::_alias_t;
|
||||||
{
|
|
||||||
context << name_of<T>::char_ptr() << " AS (";
|
|
||||||
serialize(t._statement, context);
|
|
||||||
context << ")";
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template <typename Statement>
|
||||||
|
auto as(Statement statement) -> make_cte_t<AliasProvider, Statement>
|
||||||
|
{
|
||||||
|
static_assert(required_tables_of<Statement>::size::value == 0,
|
||||||
|
"common table expression must not use unknown tables");
|
||||||
|
static_assert(not detail::is_element_of<AliasProvider, required_ctes_of<Statement>>::value,
|
||||||
|
"common table expression must not self-reference in the first part, use union_all/union_distinct "
|
||||||
|
"for recursion");
|
||||||
|
static_assert(is_static_result_row_t<get_result_row_t<Statement>>::value,
|
||||||
|
"ctes must not have dynamically added columns");
|
||||||
|
|
||||||
// The cte_t is displayed as AliasProviderName except within the with:
|
return {statement};
|
||||||
// - the with needs the
|
}
|
||||||
// AliasProviderName AS (ColumnNames) (select/union)
|
};
|
||||||
// The result row of the select should not have dynamic parts
|
|
||||||
template<typename AliasProvider>
|
|
||||||
struct cte_ref_t
|
|
||||||
{
|
|
||||||
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_cte, tag::is_table>; // FIXME: is table? really?
|
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
using _required_ctes = detail::make_type_set_t<AliasProvider>;
|
|
||||||
using _provided_tables = detail::type_set<AliasProvider>;
|
|
||||||
|
|
||||||
using _alias_t = typename AliasProvider::_alias_t;
|
template <typename Context, typename AliasProvider>
|
||||||
|
struct serializer_t<Context, cte_ref_t<AliasProvider>>
|
||||||
|
{
|
||||||
|
using _serialize_check = consistent_t;
|
||||||
|
using T = cte_ref_t<AliasProvider>;
|
||||||
|
|
||||||
template<typename Statement>
|
static Context& _(const T&, Context& context)
|
||||||
auto as(Statement statement)
|
{
|
||||||
-> make_cte_t<AliasProvider, Statement>
|
context << name_of<T>::char_ptr();
|
||||||
{
|
return context;
|
||||||
static_assert(required_tables_of<Statement>::size::value == 0, "common table expression must not use unknown tables");
|
}
|
||||||
static_assert(not detail::is_element_of<AliasProvider, required_ctes_of<Statement>>::value, "common table expression must not self-reference in the first part, use union_all/union_distinct for recursion");
|
};
|
||||||
static_assert(is_static_result_row_t<get_result_row_t<Statement>>::value, "ctes must not have dynamically added columns");
|
|
||||||
|
|
||||||
return { statement };
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Context, typename AliasProvider>
|
|
||||||
struct serializer_t<Context, cte_ref_t<AliasProvider>>
|
|
||||||
{
|
|
||||||
using _serialize_check = consistent_t;
|
|
||||||
using T = cte_ref_t<AliasProvider>;
|
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
|
||||||
{
|
|
||||||
context << name_of<T>::char_ptr();
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename AliasProvider>
|
|
||||||
auto cte(const AliasProvider&)
|
|
||||||
-> cte_ref_t<AliasProvider>
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename AliasProvider>
|
||||||
|
auto cte(const AliasProvider&) -> cte_ref_t<AliasProvider>
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,111 +34,108 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Database, typename... Parts>
|
template <typename Database, typename... Parts>
|
||||||
struct custom_query_t;
|
struct custom_query_t;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Db, typename... Parts>
|
template <typename Db, typename... Parts>
|
||||||
struct custom_parts_t
|
struct custom_parts_t
|
||||||
{
|
{
|
||||||
using _custom_query_t = custom_query_t<Db, Parts...>;
|
using _custom_query_t = custom_query_t<Db, Parts...>;
|
||||||
using _result_type_provider = detail::get_first_if<is_return_value_t, noop, Parts...>;
|
using _result_type_provider = detail::get_first_if<is_return_value_t, noop, Parts...>;
|
||||||
using _result_methods_t = typename _result_type_provider::template _result_methods_t<_result_type_provider>;
|
using _result_methods_t = typename _result_type_provider::template _result_methods_t<_result_type_provider>;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database, typename... Parts>
|
template <typename Database, typename... Parts>
|
||||||
struct custom_query_t:
|
struct custom_query_t : private detail::custom_parts_t<Database, Parts...>::_result_methods_t
|
||||||
private detail::custom_parts_t<Database, Parts...>::_result_methods_t
|
{
|
||||||
{
|
using _methods_t = typename detail::custom_parts_t<Database, Parts...>::_result_methods_t;
|
||||||
using _methods_t = typename detail::custom_parts_t<Database, Parts...>::_result_methods_t;
|
using _traits = make_traits<no_value_t, tag::is_statement>;
|
||||||
using _traits = make_traits<no_value_t, tag::is_statement>;
|
using _nodes = detail::type_vector<Parts...>;
|
||||||
using _nodes = detail::type_vector<Parts...>;
|
|
||||||
|
|
||||||
using _parameter_check = typename std::conditional<detail::type_vector_size<parameters_of<custom_query_t>>::value == 0,
|
using _parameter_check =
|
||||||
consistent_t, assert_no_parameters_t>::type;
|
typename std::conditional<detail::type_vector_size<parameters_of<custom_query_t>>::value == 0,
|
||||||
using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t,
|
consistent_t,
|
||||||
_parameter_check>;
|
assert_no_parameters_t>::type;
|
||||||
using _prepare_check = consistent_t;
|
using _run_check = detail::get_first_if<is_inconsistent_t, consistent_t, _parameter_check>;
|
||||||
|
using _prepare_check = consistent_t;
|
||||||
|
|
||||||
custom_query_t(Parts... parts):
|
custom_query_t(Parts... parts) : _parts(parts...)
|
||||||
_parts(parts...)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
custom_query_t(std::tuple<Parts...> parts):
|
custom_query_t(std::tuple<Parts...> parts) : _parts(parts)
|
||||||
_parts(parts)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
custom_query_t(const custom_query_t&) = default;
|
custom_query_t(const custom_query_t&) = default;
|
||||||
custom_query_t(custom_query_t&&) = default;
|
custom_query_t(custom_query_t&&) = default;
|
||||||
custom_query_t& operator=(const custom_query_t&) = default;
|
custom_query_t& operator=(const custom_query_t&) = default;
|
||||||
custom_query_t& operator=(custom_query_t&&) = default;
|
custom_query_t& operator=(custom_query_t&&) = default;
|
||||||
~custom_query_t() = default;
|
~custom_query_t() = default;
|
||||||
|
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
auto _run(Db& db) const -> decltype(std::declval<_methods_t>()._run(db, *this))
|
auto _run(Db& db) const -> decltype(std::declval<_methods_t>()._run(db, *this))
|
||||||
{
|
{
|
||||||
_run_check::_();
|
_run_check::_();
|
||||||
return _methods_t::_run(db, *this);
|
return _methods_t::_run(db, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
auto _prepare(Db& db) const -> decltype(std::declval<_methods_t>()._prepare(db, *this))
|
auto _prepare(Db& db) const -> decltype(std::declval<_methods_t>()._prepare(db, *this))
|
||||||
{
|
{
|
||||||
_prepare_check::_();
|
_prepare_check::_();
|
||||||
return _methods_t::_prepare(db, *this);
|
return _methods_t::_prepare(db, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr size_t _get_static_no_of_parameters()
|
static constexpr size_t _get_static_no_of_parameters()
|
||||||
{
|
{
|
||||||
return std::tuple_size<parameters_of<custom_query_t>>::value;
|
return std::tuple_size<parameters_of<custom_query_t>>::value;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t _get_no_of_parameters() const
|
size_t _get_no_of_parameters() const
|
||||||
{
|
{
|
||||||
return _get_static_no_of_parameters();
|
return _get_static_no_of_parameters();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Part>
|
template <typename Part>
|
||||||
auto with_result_type_of(Part part)
|
auto with_result_type_of(Part part) -> custom_query_t<Database, Part, Parts...>
|
||||||
-> custom_query_t<Database, Part, Parts...>
|
{
|
||||||
{
|
return {tuple_cat(std::make_tuple(part), _parts)};
|
||||||
return {tuple_cat(std::make_tuple(part), _parts)};
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<Parts...> _parts;
|
std::tuple<Parts...> _parts;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Database, typename... Parts>
|
template <typename Context, typename Database, typename... Parts>
|
||||||
struct serializer_t<Context, custom_query_t<Database, Parts...>>
|
struct serializer_t<Context, custom_query_t<Database, Parts...>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Parts...>;
|
using _serialize_check = serialize_check_of<Context, Parts...>;
|
||||||
using T = custom_query_t<Database, Parts...>;
|
using T = custom_query_t<Database, Parts...>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
interpret_tuple_without_braces(t._parts, " ", context);
|
interpret_tuple_without_braces(t._parts, " ", context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Parts>
|
template <typename... Parts>
|
||||||
auto custom_query(Parts... parts)
|
auto custom_query(Parts... parts) -> custom_query_t<void, wrap_operand_t<Parts>...>
|
||||||
-> custom_query_t<void, wrap_operand_t<Parts>...>
|
{
|
||||||
{
|
static_assert(sizeof...(Parts) > 0, "custom query requires at least one argument");
|
||||||
static_assert(sizeof...(Parts) > 0, "custom query requires at least one argument");
|
return custom_query_t<void, wrap_operand_t<Parts>...>(parts...);
|
||||||
return custom_query_t<void, wrap_operand_t<Parts>...>(parts...);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Database, typename... Parts>
|
template <typename Database, typename... Parts>
|
||||||
auto dynamic_custom_query(const Database&, Parts... parts)
|
auto dynamic_custom_query(const Database&, Parts... parts) -> custom_query_t<Database, wrap_operand_t<Parts>...>
|
||||||
-> custom_query_t<Database, wrap_operand_t<Parts>...>
|
{
|
||||||
{
|
static_assert(sizeof...(Parts) > 0, "custom query requires at least one query argument");
|
||||||
static_assert(sizeof...(Parts) > 0, "custom query requires at least one query argument");
|
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
||||||
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
|
||||||
|
|
||||||
return custom_query_t<Database, wrap_operand_t<Parts>...>(parts...);
|
return custom_query_t<Database, wrap_operand_t<Parts>...>(parts...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,29 +31,31 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct default_value_t
|
struct default_value_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_expression>;
|
using _traits = make_traits<no_value_t, tag::is_expression>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
static constexpr bool _is_trivial() { return false; }
|
static constexpr bool _is_trivial()
|
||||||
};
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Context>
|
template <typename Context>
|
||||||
struct serializer_t<Context, default_value_t>
|
struct serializer_t<Context, default_value_t>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using Operand = default_value_t;
|
using Operand = default_value_t;
|
||||||
|
|
||||||
static Context& _(const Operand&, Context& context)
|
static Context& _(const Operand&, Context& context)
|
||||||
{
|
{
|
||||||
context << "DEFAULT";
|
context << "DEFAULT";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr default_value_t default_value = {};
|
|
||||||
|
|
||||||
|
constexpr default_value_t default_value = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,52 +32,59 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Table>
|
template <typename Table>
|
||||||
struct all_of_t;
|
struct all_of_t;
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct as_column_tuple
|
struct as_column_tuple
|
||||||
{
|
{
|
||||||
static std::tuple<auto_alias_t<T>> _(T t) { return std::tuple<auto_alias_t<T>>(auto_alias_t<T>{t}); }
|
static std::tuple<auto_alias_t<T>> _(T t)
|
||||||
};
|
{
|
||||||
|
return std::tuple<auto_alias_t<T>>(auto_alias_t<T>{t});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct as_column_tuple<all_of_t<T>>
|
struct as_column_tuple<all_of_t<T>>
|
||||||
{
|
{
|
||||||
static typename all_of_t<T>::_column_tuple_t _(all_of_t<T>) { return { }; }
|
static typename all_of_t<T>::_column_tuple_t _(all_of_t<T>)
|
||||||
};
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... Args>
|
template <typename... Args>
|
||||||
struct as_column_tuple<std::tuple<Args...>>
|
struct as_column_tuple<std::tuple<Args...>>
|
||||||
{
|
{
|
||||||
static std::tuple<auto_alias_t<Args>...> _(std::tuple<Args...> t) { return t; }
|
static std::tuple<auto_alias_t<Args>...> _(std::tuple<Args...> t)
|
||||||
};
|
{
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<template<typename, typename...> class Target, typename First, typename T>
|
template <template <typename, typename...> class Target, typename First, typename T>
|
||||||
struct copy_tuple_args_impl
|
struct copy_tuple_args_impl
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<copy_tuple_args_impl>::value, "copy_tuple_args must be called with a tuple");
|
static_assert(wrong_t<copy_tuple_args_impl>::value, "copy_tuple_args must be called with a tuple");
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<typename First, typename...> class Target, typename First, typename... Args>
|
template <template <typename First, typename...> class Target, typename First, typename... Args>
|
||||||
struct copy_tuple_args_impl<Target, First, std::tuple<Args...>>
|
struct copy_tuple_args_impl<Target, First, std::tuple<Args...>>
|
||||||
{
|
{
|
||||||
using type = Target<First, Args...>;
|
using type = Target<First, Args...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<typename First, typename...> class Target, typename First, typename T>
|
template <template <typename First, typename...> class Target, typename First, typename T>
|
||||||
using copy_tuple_args_t = typename copy_tuple_args_impl<Target, First, T>::type;
|
using copy_tuple_args_t = typename copy_tuple_args_impl<Target, First, T>::type;
|
||||||
|
|
||||||
template<typename... Columns>
|
template <typename... Columns>
|
||||||
auto column_tuple_merge(Columns... columns) -> decltype(std::tuple_cat(as_column_tuple<Columns>::_(columns)...))
|
auto column_tuple_merge(Columns... columns) -> decltype(std::tuple_cat(as_column_tuple<Columns>::_(columns)...))
|
||||||
{
|
{
|
||||||
return std::tuple_cat(as_column_tuple<Columns>::_(columns)...);
|
return std::tuple_cat(as_column_tuple<Columns>::_(columns)...);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,43 +32,55 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<std::size_t NextIndex, std::size_t... Ints>
|
template <std::size_t NextIndex, std::size_t... Ints>
|
||||||
struct field_index_sequence
|
struct field_index_sequence
|
||||||
{
|
{
|
||||||
static constexpr std::size_t _next_index = NextIndex;
|
static constexpr std::size_t _next_index = NextIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename... Fields>
|
template <typename T, typename... Fields>
|
||||||
struct make_field_index_sequence_impl
|
struct make_field_index_sequence_impl
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<make_field_index_sequence_impl>::value, "invalid field index sequence arguments");
|
static_assert(wrong_t<make_field_index_sequence_impl>::value, "invalid field index sequence arguments");
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::size_t NextIndex, std::size_t... Ints, typename NameType, typename ValueType, bool CanBeNull, bool NullIsTrivialValue, typename... Rest>
|
template <std::size_t NextIndex,
|
||||||
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>, field_spec_t<NameType, ValueType, CanBeNull, NullIsTrivialValue>, Rest...>
|
std::size_t... Ints,
|
||||||
{
|
typename NameType,
|
||||||
using type = typename make_field_index_sequence_impl<field_index_sequence<NextIndex + 1, Ints..., NextIndex>, Rest...>::type;
|
typename ValueType,
|
||||||
};
|
bool CanBeNull,
|
||||||
|
bool NullIsTrivialValue,
|
||||||
|
typename... Rest>
|
||||||
|
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>,
|
||||||
|
field_spec_t<NameType, ValueType, CanBeNull, NullIsTrivialValue>,
|
||||||
|
Rest...>
|
||||||
|
{
|
||||||
|
using type = typename make_field_index_sequence_impl<field_index_sequence<NextIndex + 1, Ints..., NextIndex>,
|
||||||
|
Rest...>::type;
|
||||||
|
};
|
||||||
|
|
||||||
template<std::size_t NextIndex, std::size_t... Ints, typename AliasProvider, typename FieldTuple, typename... Rest>
|
template <std::size_t NextIndex, std::size_t... Ints, typename AliasProvider, typename FieldTuple, typename... Rest>
|
||||||
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>, multi_field_spec_t<AliasProvider, FieldTuple>, Rest...>
|
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>,
|
||||||
{
|
multi_field_spec_t<AliasProvider, FieldTuple>,
|
||||||
using type = typename make_field_index_sequence_impl<field_index_sequence<NextIndex + std::tuple_size<FieldTuple>::value, Ints..., NextIndex>, Rest...>::type;
|
Rest...>
|
||||||
};
|
{
|
||||||
|
using type = typename make_field_index_sequence_impl<
|
||||||
|
field_index_sequence<NextIndex + std::tuple_size<FieldTuple>::value, Ints..., NextIndex>,
|
||||||
|
Rest...>::type;
|
||||||
|
};
|
||||||
|
|
||||||
template<std::size_t NextIndex, std::size_t... Ints>
|
template <std::size_t NextIndex, std::size_t... Ints>
|
||||||
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>>
|
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>>
|
||||||
{
|
{
|
||||||
using type = field_index_sequence<NextIndex, Ints...>;
|
using type = field_index_sequence<NextIndex, Ints...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::size_t StartIndex, typename... Fields>
|
template <std::size_t StartIndex, typename... Fields>
|
||||||
using make_field_index_sequence = typename make_field_index_sequence_impl<field_index_sequence<StartIndex>, Fields...>::type;
|
using make_field_index_sequence =
|
||||||
|
typename make_field_index_sequence_impl<field_index_sequence<StartIndex>, Fields...>::type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,30 +31,27 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<template<typename> class Predicate, typename Default, typename... T>
|
template <template <typename> class Predicate, typename Default, typename... T>
|
||||||
struct get_first_if_impl;
|
struct get_first_if_impl;
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename Default>
|
template <template <typename> class Predicate, typename Default>
|
||||||
struct get_first_if_impl<Predicate, Default>
|
struct get_first_if_impl<Predicate, Default>
|
||||||
{
|
{
|
||||||
using type = Default;
|
using type = Default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename Default, typename T, typename... Rest>
|
template <template <typename> class Predicate, typename Default, typename T, typename... Rest>
|
||||||
struct get_first_if_impl<Predicate, Default, T, Rest...>
|
struct get_first_if_impl<Predicate, Default, T, Rest...>
|
||||||
{
|
{
|
||||||
using rest = typename get_first_if_impl<Predicate, Default, Rest...>::type;
|
using rest = typename get_first_if_impl<Predicate, Default, Rest...>::type;
|
||||||
using type = typename std::conditional<Predicate<T>::value,
|
using type = typename std::conditional<Predicate<T>::value, T, rest>::type;
|
||||||
T,
|
};
|
||||||
rest>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename Default, typename... T>
|
template <template <typename> class Predicate, typename Default, typename... T>
|
||||||
using get_first_if = typename get_first_if_impl<Predicate, Default, T...>::type;
|
using get_first_if = typename get_first_if_impl<Predicate, Default, T...>::type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,30 +31,27 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<template<typename> class Predicate, typename Default, typename... T>
|
template <template <typename> class Predicate, typename Default, typename... T>
|
||||||
struct get_last_if_impl;
|
struct get_last_if_impl;
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename Default>
|
template <template <typename> class Predicate, typename Default>
|
||||||
struct get_last_if_impl<Predicate, Default>
|
struct get_last_if_impl<Predicate, Default>
|
||||||
{
|
{
|
||||||
using type = Default;
|
using type = Default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename Default, typename T, typename... Rest>
|
template <template <typename> class Predicate, typename Default, typename T, typename... Rest>
|
||||||
struct get_last_if_impl<Predicate, Default, T, Rest...>
|
struct get_last_if_impl<Predicate, Default, T, Rest...>
|
||||||
{
|
{
|
||||||
using rest = typename get_last_if_impl<Predicate, Default, Rest...>::type;
|
using rest = typename get_last_if_impl<Predicate, Default, Rest...>::type;
|
||||||
using type = typename std::conditional<std::is_same<rest, Default>::value and Predicate<T>::value,
|
using type = typename std::conditional<std::is_same<rest, Default>::value and Predicate<T>::value, T, rest>::type;
|
||||||
T,
|
};
|
||||||
rest>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename Default, typename... T>
|
template <template <typename> class Predicate, typename Default, typename... T>
|
||||||
using get_last_if = typename get_last_if_impl<Predicate, Default, T...>::type;
|
using get_last_if = typename get_last_if_impl<Predicate, Default, T...>::type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,34 +31,33 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
// Note: This is a minimalistic implementation of index_sequence available in C++14
|
// Note: This is a minimalistic implementation of index_sequence available in C++14
|
||||||
// It should be replaced once the project is moved to C++14 or beyond
|
// It should be replaced once the project is moved to C++14 or beyond
|
||||||
template<std::size_t... Ints>
|
template <std::size_t... Ints>
|
||||||
struct index_sequence
|
struct index_sequence
|
||||||
{};
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
struct make_index_sequence_impl;
|
struct make_index_sequence_impl;
|
||||||
|
|
||||||
template<std::size_t N, std::size_t... Ints>
|
template <std::size_t N, std::size_t... Ints>
|
||||||
struct make_index_sequence_impl<index_sequence<Ints...>, N>
|
struct make_index_sequence_impl<index_sequence<Ints...>, N>
|
||||||
{
|
{
|
||||||
using type = typename make_index_sequence_impl<index_sequence<Ints..., sizeof...(Ints)>, N - 1>::type;
|
using type = typename make_index_sequence_impl<index_sequence<Ints..., sizeof...(Ints)>, N - 1>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::size_t... Ints>
|
template <std::size_t... Ints>
|
||||||
struct make_index_sequence_impl<index_sequence<Ints...>, 0>
|
struct make_index_sequence_impl<index_sequence<Ints...>, 0>
|
||||||
{
|
{
|
||||||
using type = index_sequence<Ints...>;
|
using type = index_sequence<Ints...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::size_t N>
|
template <std::size_t N>
|
||||||
using make_index_sequence = typename make_index_sequence_impl<index_sequence<>, N>::type;
|
using make_index_sequence = typename make_index_sequence_impl<index_sequence<>, N>::type;
|
||||||
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,28 +31,27 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Target, typename Statement, typename Term>
|
template <typename Target, typename Statement, typename Term>
|
||||||
typename Target::_data_t pick_arg_impl(Statement /* statement */, Term term, const std::true_type&)
|
typename Target::_data_t pick_arg_impl(Statement /* statement */, Term term, const std::true_type&)
|
||||||
{
|
{
|
||||||
return term;
|
return term;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Target, typename Statement, typename Term>
|
template <typename Target, typename Statement, typename Term>
|
||||||
typename Target::_data_t pick_arg_impl(Statement statement, Term /* term */, const std::false_type&)
|
typename Target::_data_t pick_arg_impl(Statement statement, Term /* term */, const std::false_type&)
|
||||||
{
|
{
|
||||||
return Target::_get_member(statement)._data;
|
return Target::_get_member(statement)._data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a statement's term either by picking the term from the statement or using the new term
|
// Returns a statement's term either by picking the term from the statement or using the new term
|
||||||
template<typename Target, typename Statement, typename Term>
|
template <typename Target, typename Statement, typename Term>
|
||||||
typename Target::_data_t pick_arg(Statement statement, Term term)
|
typename Target::_data_t pick_arg(Statement statement, Term term)
|
||||||
{
|
{
|
||||||
return pick_arg_impl<Target>(statement, term, std::is_same<typename Target::_data_t, Term>());
|
return pick_arg_impl<Target>(statement, term, std::is_same<typename Target::_data_t, Term>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,34 +29,32 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
/** a non-recursive C++14 version
|
||||||
|
template<typename... Args>
|
||||||
|
constexpr std::size_t sum(Args... args)
|
||||||
|
{
|
||||||
|
std::size_t result = 0;
|
||||||
|
|
||||||
/** a non-recursive C++14 version
|
using swallow = int[];
|
||||||
template<typename... Args>
|
(void) swallow{(result += args, 0)...};
|
||||||
constexpr std::size_t sum(Args... args)
|
|
||||||
{
|
|
||||||
std::size_t result = 0;
|
|
||||||
|
|
||||||
using swallow = int[];
|
return result;
|
||||||
(void) swallow{(result += args, 0)...};
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
return result;
|
constexpr std::size_t sum()
|
||||||
}
|
{
|
||||||
*/
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr std::size_t sum()
|
template <typename Arg, typename... Rest>
|
||||||
{
|
constexpr std::size_t sum(Arg arg, Rest... rest)
|
||||||
return 0;
|
{
|
||||||
}
|
return arg + sum(rest...);
|
||||||
|
}
|
||||||
template<typename Arg, typename... Rest>
|
}
|
||||||
constexpr std::size_t sum(Arg arg, Rest... rest)
|
|
||||||
{
|
|
||||||
return arg + sum(rest...);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -33,223 +33,220 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
// some forward declarations and helpers
|
// some forward declarations and helpers
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
struct make_type_set;
|
struct make_type_set;
|
||||||
|
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
using make_type_set_t = typename make_type_set<T...>::type;
|
using make_type_set_t = typename make_type_set<T...>::type;
|
||||||
|
|
||||||
template<typename E, typename SET>
|
template <typename E, typename SET>
|
||||||
struct is_element_of;
|
struct is_element_of;
|
||||||
|
|
||||||
// A type set
|
// A type set
|
||||||
template<typename... Elements>
|
template <typename... Elements>
|
||||||
struct type_set
|
struct type_set
|
||||||
{
|
{
|
||||||
using size = std::integral_constant<size_t, sizeof...(Elements)>;
|
using size = std::integral_constant<size_t, sizeof...(Elements)>;
|
||||||
using _is_type_set = std::true_type;
|
using _is_type_set = std::true_type;
|
||||||
|
|
||||||
static_assert(std::is_same<type_set, make_type_set_t<Elements...>>::value, "use make_type_set to construct a typeset");
|
static_assert(std::is_same<type_set, make_type_set_t<Elements...>>::value,
|
||||||
|
"use make_type_set to construct a typeset");
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct insert
|
struct insert
|
||||||
{
|
{
|
||||||
using type = typename std::conditional<not is_element_of<T, type_set>::value,
|
using type =
|
||||||
type_set<T, Elements...>,
|
typename std::conditional<not is_element_of<T, type_set>::value, type_set<T, Elements...>, type_set>::type;
|
||||||
type_set>::type;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<template<typename A> class Predicate, typename T>
|
template <template <typename A> class Predicate, typename T>
|
||||||
struct insert_if
|
struct insert_if
|
||||||
{
|
{
|
||||||
using type = typename std::conditional<Predicate<T>::value and not is_element_of<T, type_set>::value,
|
using type = typename std::conditional<Predicate<T>::value and not is_element_of<T, type_set>::value,
|
||||||
type_set<Elements..., T>,
|
type_set<Elements..., T>,
|
||||||
type_set>::type;
|
type_set>::type;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename E, typename SET>
|
||||||
|
struct is_element_of
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<is_element_of>::value, "SET has to be a type set");
|
||||||
|
};
|
||||||
|
|
||||||
template<typename E, typename SET>
|
template <typename E, typename... Elements>
|
||||||
struct is_element_of
|
struct is_element_of<E, type_set<Elements...>>
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<is_element_of>::value, "SET has to be a type set");
|
static constexpr bool value = ::sqlpp::logic::any_t<std::is_same<E, Elements>::value...>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename E, typename... Elements>
|
template <typename L, typename R>
|
||||||
struct is_element_of<E, type_set<Elements...>>
|
struct joined_set
|
||||||
{
|
{
|
||||||
static constexpr bool value = ::sqlpp::logic::any_t<std::is_same<E, Elements>::value...>::value;
|
static_assert(wrong_t<joined_set>::value, "L and R have to be type sets");
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename L, typename R>
|
template <typename... LElements, typename... RElements>
|
||||||
struct joined_set
|
struct joined_set<type_set<LElements...>, type_set<RElements...>>
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<joined_set>::value, "L and R have to be type sets");
|
using type = make_type_set_t<LElements..., RElements...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... LElements, typename... RElements>
|
template <typename L, typename R>
|
||||||
struct joined_set<type_set<LElements...>, type_set<RElements...>>
|
using joined_set_t = typename joined_set<L, R>::type;
|
||||||
{
|
|
||||||
using type = make_type_set_t<LElements..., RElements...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename L, typename R>
|
template <typename L, typename R>
|
||||||
using joined_set_t = typename joined_set<L, R>::type;
|
struct is_superset_of
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<is_superset_of>::value, "L and R have to be type sets");
|
||||||
|
};
|
||||||
|
|
||||||
template<typename L, typename R>
|
template <typename... LElements, typename... RElements>
|
||||||
struct is_superset_of
|
struct is_superset_of<type_set<LElements...>, type_set<RElements...>>
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<is_superset_of>::value, "L and R have to be type sets");
|
static constexpr bool value =
|
||||||
};
|
joined_set_t<type_set<LElements...>, type_set<RElements...>>::size::value == sizeof...(LElements);
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... LElements, typename... RElements>
|
template <typename L, typename R>
|
||||||
struct is_superset_of<type_set<LElements...>, type_set<RElements...>>
|
struct is_subset_of
|
||||||
{
|
{
|
||||||
static constexpr bool value = joined_set_t<type_set<LElements...>, type_set<RElements...>>::size::value == sizeof...(LElements);
|
static constexpr bool value = is_superset_of<R, L>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename L, typename R>
|
template <typename L, typename R>
|
||||||
struct is_subset_of
|
struct is_disjunct_from
|
||||||
{
|
{
|
||||||
static constexpr bool value = is_superset_of<R, L>::value;
|
static_assert(wrong_t<is_disjunct_from>::value, "invalid argument for is_disjunct_from");
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename L, typename R>
|
template <typename... LElements, typename... RElements>
|
||||||
struct is_disjunct_from
|
struct is_disjunct_from<type_set<LElements...>, type_set<RElements...>>
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<is_disjunct_from>::value, "invalid argument for is_disjunct_from");
|
static constexpr bool value = joined_set_t<type_set<LElements...>, type_set<RElements...>>::size::value ==
|
||||||
};
|
sizeof...(LElements) + sizeof...(RElements);
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... LElements, typename... RElements>
|
template <>
|
||||||
struct is_disjunct_from<type_set<LElements...>, type_set<RElements...>>
|
struct make_type_set<>
|
||||||
{
|
{
|
||||||
static constexpr bool value = joined_set_t<type_set<LElements...>, type_set<RElements...>>::size::value == sizeof...(LElements) + sizeof...(RElements);
|
using type = type_set<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template <typename T, typename... Rest>
|
||||||
struct make_type_set<>
|
struct make_type_set<T, Rest...>
|
||||||
{
|
{
|
||||||
using type = type_set<>;
|
using type = typename make_type_set<Rest...>::type::template insert<T>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename... Rest>
|
template <template <typename> class Predicate, typename... T>
|
||||||
struct make_type_set<T, Rest...>
|
struct make_type_set_if;
|
||||||
{
|
|
||||||
using type = typename make_type_set<Rest...>::type::template insert<T>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename... T>
|
template <template <typename> class Predicate>
|
||||||
struct make_type_set_if;
|
struct make_type_set_if<Predicate>
|
||||||
|
{
|
||||||
|
using type = type_set<>;
|
||||||
|
};
|
||||||
|
|
||||||
template<template<typename> class Predicate>
|
template <template <typename> class Predicate, typename T, typename... Rest>
|
||||||
struct make_type_set_if<Predicate>
|
struct make_type_set_if<Predicate, T, Rest...>
|
||||||
{
|
{
|
||||||
using type = type_set<>;
|
using type = typename make_type_set_if<Predicate, Rest...>::type::template insert_if<Predicate, T>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename T, typename... Rest>
|
template <template <typename> class Predicate, typename... T>
|
||||||
struct make_type_set_if<Predicate, T, Rest...>
|
using make_type_set_if_t = typename make_type_set_if<Predicate, T...>::type;
|
||||||
{
|
|
||||||
using type = typename make_type_set_if<Predicate, Rest...>::type::template insert_if<Predicate, T>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename... T>
|
template <template <typename> class Predicate, typename... T>
|
||||||
using make_type_set_if_t = typename make_type_set_if<Predicate, T...>::type;
|
struct make_type_set_if_not
|
||||||
|
{
|
||||||
|
template <typename X>
|
||||||
|
using InversePredicate = std::integral_constant<bool, not Predicate<X>::value>;
|
||||||
|
using type = typename make_type_set_if<InversePredicate, T...>::type;
|
||||||
|
};
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename... T>
|
template <template <typename> class Predicate, typename... T>
|
||||||
struct make_type_set_if_not
|
using make_type_set_if_not_t = typename make_type_set_if_not<Predicate, T...>::type;
|
||||||
{
|
|
||||||
template<typename X>
|
|
||||||
using InversePredicate = std::integral_constant<bool, not Predicate<X>::value>;
|
|
||||||
using type = typename make_type_set_if<InversePredicate, T...>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename... T>
|
template <typename... T>
|
||||||
using make_type_set_if_not_t = typename make_type_set_if_not<Predicate, T...>::type;
|
using has_duplicates = std::integral_constant<bool, make_type_set_t<T...>::size::value != sizeof...(T)>;
|
||||||
|
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
using has_duplicates = std::integral_constant<bool, make_type_set_t<T...>::size::value != sizeof...(T)>;
|
struct make_joined_set
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<make_joined_set>::value, "invalid argument for joined set");
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... T>
|
template <>
|
||||||
struct make_joined_set
|
struct make_joined_set<>
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<make_joined_set>::value, "invalid argument for joined set");
|
using type = type_set<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template <typename... E, typename... T>
|
||||||
struct make_joined_set<>
|
struct make_joined_set<type_set<E...>, T...>
|
||||||
{
|
{
|
||||||
using type = type_set<>;
|
using _rest = typename make_joined_set<T...>::type;
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... E, typename... T>
|
using type = joined_set_t<type_set<E...>, _rest>;
|
||||||
struct make_joined_set<type_set<E...>, T...>
|
};
|
||||||
{
|
|
||||||
using _rest = typename make_joined_set<T...>::type;
|
|
||||||
|
|
||||||
using type = joined_set_t<type_set<E...>, _rest>;
|
template <typename... Sets>
|
||||||
};
|
using make_joined_set_t = typename make_joined_set<Sets...>::type;
|
||||||
|
|
||||||
template<typename... Sets>
|
template <typename Minuend, typename Subtrahend>
|
||||||
using make_joined_set_t = typename make_joined_set<Sets...>::type;
|
struct make_difference_set
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<make_difference_set>::value, "invalid argument for difference set");
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Minuend, typename Subtrahend>
|
template <typename... Minuends, typename... Subtrahends>
|
||||||
struct make_difference_set
|
struct make_difference_set<type_set<Minuends...>, type_set<Subtrahends...>>
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<make_difference_set>::value, "invalid argument for difference set");
|
template <typename E>
|
||||||
};
|
using is_subtrahend = is_element_of<E, type_set<Subtrahends...>>;
|
||||||
|
using type = make_type_set_if_not_t<is_subtrahend, Minuends...>;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... Minuends, typename... Subtrahends>
|
template <typename Minuend, typename Subtrahend>
|
||||||
struct make_difference_set<type_set<Minuends...>, type_set<Subtrahends...>>
|
using make_difference_set_t = typename make_difference_set<Minuend, Subtrahend>::type;
|
||||||
{
|
|
||||||
template<typename E>
|
|
||||||
using is_subtrahend = is_element_of<E, type_set<Subtrahends...>>;
|
|
||||||
using type = make_type_set_if_not_t<is_subtrahend, Minuends...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Minuend, typename Subtrahend>
|
template <typename Lhs, typename Rhs>
|
||||||
using make_difference_set_t = typename make_difference_set<Minuend, Subtrahend>::type;
|
struct make_intersect_set
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<make_intersect_set>::value, "invalid argument for intersect set");
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename... LhsElements, typename... RhsElements>
|
||||||
struct make_intersect_set
|
struct make_intersect_set<type_set<LhsElements...>, type_set<RhsElements...>>
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<make_intersect_set>::value, "invalid argument for intersect set");
|
template <typename E>
|
||||||
};
|
using is_in_both = ::sqlpp::logic::all_t<is_element_of<E, type_set<LhsElements...>>::value,
|
||||||
|
is_element_of<E, type_set<RhsElements...>>::value>;
|
||||||
|
using type = make_type_set_if_t<is_in_both, LhsElements...>;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... LhsElements, typename... RhsElements>
|
template <typename Lhs, typename Rhs>
|
||||||
struct make_intersect_set<type_set<LhsElements...>, type_set<RhsElements...>>
|
using make_intersect_set_t = typename make_intersect_set<Lhs, Rhs>::type;
|
||||||
{
|
|
||||||
template<typename E>
|
|
||||||
using is_in_both = ::sqlpp::logic::all_t<is_element_of<E, type_set<LhsElements...>>::value, is_element_of<E, type_set<RhsElements...>>::value>;
|
|
||||||
using type = make_type_set_if_t<is_in_both, LhsElements...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <template <typename> class Transformation, typename T>
|
||||||
using make_intersect_set_t = typename make_intersect_set<Lhs, Rhs>::type;
|
struct transform_set
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<transform_set>::value, "invalid argument for transform_set");
|
||||||
|
};
|
||||||
|
|
||||||
|
template <template <typename> class Transformation, typename... E>
|
||||||
|
struct transform_set<Transformation, type_set<E...>>
|
||||||
|
{
|
||||||
|
using type = make_type_set_t<Transformation<E>...>;
|
||||||
|
};
|
||||||
|
|
||||||
template<template<typename> class Transformation, typename T>
|
template <template <typename> class Transformation, typename T>
|
||||||
struct transform_set
|
using transform_set_t = typename transform_set<Transformation, T>::type;
|
||||||
{
|
}
|
||||||
static_assert(wrong_t<transform_set>::value, "invalid argument for transform_set");
|
|
||||||
};
|
|
||||||
|
|
||||||
template<template<typename> class Transformation, typename... E>
|
|
||||||
struct transform_set<Transformation, type_set<E...>>
|
|
||||||
{
|
|
||||||
using type = make_type_set_t<Transformation<E>...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<template<typename> class Transformation, typename T>
|
|
||||||
using transform_set_t = typename transform_set<Transformation, T>::type;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,58 +31,59 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
struct type_vector
|
struct type_vector
|
||||||
{};
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template<typename...T>
|
template <typename... T>
|
||||||
struct type_vector_cat_impl
|
struct type_vector_cat_impl
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<type_vector_cat_impl>::value, "type_vector_cat must be called with type_vector arguments");
|
static_assert(wrong_t<type_vector_cat_impl>::value, "type_vector_cat must be called with type_vector arguments");
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
struct type_vector_cat_impl<>
|
struct type_vector_cat_impl<>
|
||||||
{
|
{
|
||||||
using type = type_vector<>;
|
using type = type_vector<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
struct type_vector_cat_impl<type_vector<T...>>
|
struct type_vector_cat_impl<type_vector<T...>>
|
||||||
{
|
{
|
||||||
using type = type_vector<T...>;
|
using type = type_vector<T...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... L, typename... R>
|
template <typename... L, typename... R>
|
||||||
struct type_vector_cat_impl<type_vector<L...>, type_vector<R...>>
|
struct type_vector_cat_impl<type_vector<L...>, type_vector<R...>>
|
||||||
{
|
{
|
||||||
using type = type_vector<L..., R...>;
|
using type = type_vector<L..., R...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... L, typename... Rest>
|
template <typename... L, typename... Rest>
|
||||||
struct type_vector_cat_impl<type_vector<L...>, Rest...>
|
struct type_vector_cat_impl<type_vector<L...>, Rest...>
|
||||||
{
|
{
|
||||||
using type = typename type_vector_cat_impl<type_vector<L...>, typename type_vector_cat_impl<Rest...>::type>::type;
|
using type = typename type_vector_cat_impl<type_vector<L...>, typename type_vector_cat_impl<Rest...>::type>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
using type_vector_cat_t = typename type_vector_cat_impl<T...>::type;
|
using type_vector_cat_t = typename type_vector_cat_impl<T...>::type;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct type_vector_size
|
struct type_vector_size
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<type_vector_size>::value, "type_vector_size needs to be called with a type_vector argument");
|
static_assert(wrong_t<type_vector_size>::value,
|
||||||
};
|
"type_vector_size needs to be called with a type_vector argument");
|
||||||
|
};
|
||||||
|
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
struct type_vector_size<type_vector<T...>>
|
struct type_vector_size<type_vector<T...>>
|
||||||
{
|
{
|
||||||
static constexpr std::size_t value = sizeof...(T);
|
static constexpr std::size_t value = sizeof...(T);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,29 +34,33 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db, typename Expr>
|
template <typename Db, typename Expr>
|
||||||
struct eval_t
|
struct eval_t
|
||||||
{
|
{
|
||||||
static_assert(is_database<Db>::value, "Db parameter of eval has to be a database connection");
|
static_assert(is_database<Db>::value, "Db parameter of eval has to be a database connection");
|
||||||
static_assert(is_expression_t<Expr>::value, "Expression parameter of eval has to be an sqlpp expression or a string");
|
static_assert(is_expression_t<Expr>::value,
|
||||||
static_assert(required_tables_of<Expr>::size::value == 0, "Expression cannot be used in eval because it requires tables");
|
"Expression parameter of eval has to be an sqlpp expression or a string");
|
||||||
using _name_type = alias::a_t::_alias_t;
|
static_assert(required_tables_of<Expr>::size::value == 0,
|
||||||
using _value_type = value_type_of<Expr>;
|
"Expression cannot be used in eval because it requires tables");
|
||||||
using _field_spec = field_spec_t<_name_type, _value_type, true, false>;
|
using _name_type = alias::a_t::_alias_t;
|
||||||
using type = result_field_t<_value_type, Db, _field_spec>;
|
using _value_type = value_type_of<Expr>;
|
||||||
};
|
using _field_spec = field_spec_t<_name_type, _value_type, true, false>;
|
||||||
|
using type = result_field_t<_value_type, Db, _field_spec>;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Db, typename Expr, typename std::enable_if<not std::is_convertible<Expr, std::string>::value, int>::type = 0>
|
template <typename Db,
|
||||||
auto eval(Db& db, Expr expr) -> typename eval_t<Db, Expr>::type
|
typename Expr,
|
||||||
{
|
typename std::enable_if<not std::is_convertible<Expr, std::string>::value, int>::type = 0>
|
||||||
return db(select(expr.as(alias::a))).front().a;
|
auto eval(Db& db, Expr expr) -> typename eval_t<Db, Expr>::type
|
||||||
}
|
{
|
||||||
|
return db(select(expr.as(alias::a))).front().a;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ValueType, typename Db>
|
template <typename ValueType, typename Db>
|
||||||
auto eval(Db& db, std::string sql_code) -> decltype(eval(db, verbatim<ValueType>(sql_code)))
|
auto eval(Db& db, std::string sql_code) -> decltype(eval(db, verbatim<ValueType>(sql_code)))
|
||||||
{
|
{
|
||||||
return eval(db, verbatim<ValueType>(sql_code));
|
return eval(db, verbatim<ValueType>(sql_code));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,13 +31,16 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
class exception: public std::runtime_error
|
class exception : public std::runtime_error
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
exception(const std::string& what_arg): std::runtime_error(what_arg) {}
|
exception(const std::string& what_arg) : std::runtime_error(what_arg)
|
||||||
exception(const char* what_arg): std::runtime_error(what_arg) {}
|
{
|
||||||
};
|
}
|
||||||
|
exception(const char* what_arg) : std::runtime_error(what_arg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -32,70 +32,72 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct exists_alias_t
|
struct exists_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "exists_";
|
static constexpr const char _literal[] = "exists_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T exists;
|
T exists;
|
||||||
T& operator()() { return exists; }
|
T& operator()()
|
||||||
const T& operator()() const { return exists; }
|
{
|
||||||
};
|
return exists;
|
||||||
};
|
}
|
||||||
};
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Select>
|
template <typename Select>
|
||||||
struct exists_t:
|
struct exists_t : public expression_operators<exists_t<Select>, boolean>, public alias_operators<exists_t<Select>>
|
||||||
public expression_operators<exists_t<Select>, boolean>,
|
{
|
||||||
public alias_operators<exists_t<Select>>
|
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
||||||
{
|
using _nodes = detail::type_vector<Select>;
|
||||||
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
|
||||||
using _nodes = detail::type_vector<Select>;
|
|
||||||
|
|
||||||
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");
|
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");
|
||||||
|
|
||||||
using _auto_alias_t = exists_alias_t;
|
using _auto_alias_t = exists_alias_t;
|
||||||
|
|
||||||
exists_t(Select select):
|
exists_t(Select select) : _select(select)
|
||||||
_select(select)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
exists_t(const exists_t&) = default;
|
exists_t(const exists_t&) = default;
|
||||||
exists_t(exists_t&&) = default;
|
exists_t(exists_t&&) = default;
|
||||||
exists_t& operator=(const exists_t&) = default;
|
exists_t& operator=(const exists_t&) = default;
|
||||||
exists_t& operator=(exists_t&&) = default;
|
exists_t& operator=(exists_t&&) = default;
|
||||||
~exists_t() = default;
|
~exists_t() = default;
|
||||||
|
|
||||||
Select _select;
|
Select _select;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Select>
|
template <typename Context, typename Select>
|
||||||
struct serializer_t<Context, exists_t<Select>>
|
struct serializer_t<Context, exists_t<Select>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Select>;
|
using _serialize_check = serialize_check_of<Context, Select>;
|
||||||
using T = exists_t<Select>;
|
using T = exists_t<Select>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "EXISTS(";
|
context << "EXISTS(";
|
||||||
serialize(t._select, context);
|
serialize(t._select, context);
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto exists(T t) -> exists_t<wrap_operand_t<T>>
|
|
||||||
{
|
|
||||||
static_assert(is_select_t<wrap_operand_t<T>>::value, "exists() requires a select expression as argument");
|
|
||||||
return { t };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto exists(T t) -> exists_t<wrap_operand_t<T>>
|
||||||
|
{
|
||||||
|
static_assert(is_select_t<wrap_operand_t<T>>::value, "exists() requires a select expression as argument");
|
||||||
|
return {t};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,226 +38,221 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
struct binary_expression_t<Lhs, op::equal_to, Rhs>:
|
struct binary_expression_t<Lhs, op::equal_to, Rhs>
|
||||||
public expression_operators<binary_expression_t<Lhs, op::equal_to, Rhs>, boolean>,
|
: public expression_operators<binary_expression_t<Lhs, op::equal_to, Rhs>, boolean>,
|
||||||
public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>
|
public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean, tag::is_expression>;
|
using _traits = make_traits<boolean, tag::is_expression>;
|
||||||
using _lhs_t = Lhs;
|
using _lhs_t = Lhs;
|
||||||
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
|
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
|
||||||
using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
|
using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
|
||||||
|
|
||||||
binary_expression_t(_lhs_t lhs, _rhs_t rhs):
|
binary_expression_t(_lhs_t lhs, _rhs_t rhs) : _lhs(lhs), _rhs(rhs)
|
||||||
_lhs(lhs),
|
{
|
||||||
_rhs(rhs)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
binary_expression_t(const binary_expression_t&) = default;
|
binary_expression_t(const binary_expression_t&) = default;
|
||||||
binary_expression_t(binary_expression_t&&) = default;
|
binary_expression_t(binary_expression_t&&) = default;
|
||||||
binary_expression_t& operator=(const binary_expression_t&) = default;
|
binary_expression_t& operator=(const binary_expression_t&) = default;
|
||||||
binary_expression_t& operator=(binary_expression_t&&) = default;
|
binary_expression_t& operator=(binary_expression_t&&) = default;
|
||||||
~binary_expression_t() = default;
|
~binary_expression_t() = default;
|
||||||
|
|
||||||
_lhs_t _lhs;
|
_lhs_t _lhs;
|
||||||
_rhs_t _rhs;
|
_rhs_t _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Lhs, typename Rhs>
|
template <typename Context, typename Lhs, typename Rhs>
|
||||||
struct serializer_t<Context, binary_expression_t<Lhs, op::equal_to, Rhs>>
|
struct serializer_t<Context, binary_expression_t<Lhs, op::equal_to, Rhs>>
|
||||||
{
|
{
|
||||||
using T = binary_expression_t<Lhs, op::equal_to, Rhs>;
|
using T = binary_expression_t<Lhs, op::equal_to, Rhs>;
|
||||||
using _serialize_check = serialize_check_of<Context, typename T::_lhs_t, typename T::_rhs_t>;
|
using _serialize_check = serialize_check_of<Context, typename T::_lhs_t, typename T::_rhs_t>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "(";
|
context << "(";
|
||||||
serialize_operand(t._lhs, context);
|
serialize_operand(t._lhs, context);
|
||||||
if (t._rhs._is_null())
|
if (t._rhs._is_null())
|
||||||
{
|
{
|
||||||
context << " IS NULL";
|
context << " IS NULL";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context << "=";
|
context << "=";
|
||||||
serialize_operand(t._rhs, context);
|
serialize_operand(t._rhs, context);
|
||||||
}
|
}
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
struct binary_expression_t<Lhs, op::not_equal_to, Rhs>:
|
struct binary_expression_t<Lhs, op::not_equal_to, Rhs>
|
||||||
public expression_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>, boolean>,
|
: public expression_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>, boolean>,
|
||||||
public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>
|
public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean, tag::is_expression>;
|
using _traits = make_traits<boolean, tag::is_expression>;
|
||||||
using _lhs_t = Lhs;
|
using _lhs_t = Lhs;
|
||||||
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
|
using _rhs_t = rhs_wrap_t<allow_tvin_t<Rhs>, trivial_value_is_null_t<_lhs_t>::value>;
|
||||||
using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
|
using _nodes = detail::type_vector<_lhs_t, _rhs_t>;
|
||||||
|
|
||||||
binary_expression_t(Lhs lhs, _rhs_t rhs):
|
binary_expression_t(Lhs lhs, _rhs_t rhs) : _lhs(lhs), _rhs(rhs)
|
||||||
_lhs(lhs),
|
{
|
||||||
_rhs(rhs)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
binary_expression_t(const binary_expression_t&) = default;
|
binary_expression_t(const binary_expression_t&) = default;
|
||||||
binary_expression_t(binary_expression_t&&) = default;
|
binary_expression_t(binary_expression_t&&) = default;
|
||||||
binary_expression_t& operator=(const binary_expression_t&) = default;
|
binary_expression_t& operator=(const binary_expression_t&) = default;
|
||||||
binary_expression_t& operator=(binary_expression_t&&) = default;
|
binary_expression_t& operator=(binary_expression_t&&) = default;
|
||||||
~binary_expression_t() = default;
|
~binary_expression_t() = default;
|
||||||
|
|
||||||
_lhs_t _lhs;
|
_lhs_t _lhs;
|
||||||
_rhs_t _rhs;
|
_rhs_t _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Lhs, typename Rhs>
|
template <typename Context, typename Lhs, typename Rhs>
|
||||||
struct serializer_t<Context, binary_expression_t<Lhs, op::not_equal_to, Rhs>>
|
struct serializer_t<Context, binary_expression_t<Lhs, op::not_equal_to, Rhs>>
|
||||||
{
|
{
|
||||||
using T = binary_expression_t<Lhs, op::not_equal_to, Rhs>;
|
using T = binary_expression_t<Lhs, op::not_equal_to, Rhs>;
|
||||||
using _serialize_check = serialize_check_of<Context, typename T::_lhs_t, typename T::_rhs_t>;
|
using _serialize_check = serialize_check_of<Context, typename T::_lhs_t, typename T::_rhs_t>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "(";
|
context << "(";
|
||||||
serialize_operand(t._lhs, context);
|
serialize_operand(t._lhs, context);
|
||||||
if (t._rhs._is_null())
|
if (t._rhs._is_null())
|
||||||
{
|
{
|
||||||
context << " IS NOT NULL";
|
context << " IS NOT NULL";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context << "!=";
|
context << "!=";
|
||||||
serialize_operand(t._rhs, context);
|
serialize_operand(t._rhs, context);
|
||||||
}
|
}
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Rhs>
|
template <typename Rhs>
|
||||||
struct unary_expression_t<op::logical_not, Rhs>:
|
struct unary_expression_t<op::logical_not, Rhs>
|
||||||
public expression_operators<unary_expression_t<op::logical_not, Rhs>, boolean>,
|
: public expression_operators<unary_expression_t<op::logical_not, Rhs>, boolean>,
|
||||||
public alias_operators<unary_expression_t<op::logical_not, Rhs>>
|
public alias_operators<unary_expression_t<op::logical_not, Rhs>>
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean, tag::is_expression>;
|
using _traits = make_traits<boolean, tag::is_expression>;
|
||||||
using _nodes = detail::type_vector<Rhs>;
|
using _nodes = detail::type_vector<Rhs>;
|
||||||
|
|
||||||
unary_expression_t(Rhs rhs):
|
unary_expression_t(Rhs rhs) : _rhs(rhs)
|
||||||
_rhs(rhs)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
unary_expression_t(const unary_expression_t&) = default;
|
unary_expression_t(const unary_expression_t&) = default;
|
||||||
unary_expression_t(unary_expression_t&&) = default;
|
unary_expression_t(unary_expression_t&&) = default;
|
||||||
unary_expression_t& operator=(const unary_expression_t&) = default;
|
unary_expression_t& operator=(const unary_expression_t&) = default;
|
||||||
unary_expression_t& operator=(unary_expression_t&&) = default;
|
unary_expression_t& operator=(unary_expression_t&&) = default;
|
||||||
~unary_expression_t() = default;
|
~unary_expression_t() = default;
|
||||||
|
|
||||||
Rhs _rhs;
|
Rhs _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Rhs>
|
template <typename Context, typename Rhs>
|
||||||
struct serializer_t<Context, unary_expression_t<op::logical_not, Rhs>>
|
struct serializer_t<Context, unary_expression_t<op::logical_not, Rhs>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Rhs>;
|
using _serialize_check = serialize_check_of<Context, Rhs>;
|
||||||
using T = unary_expression_t<op::logical_not, Rhs>;
|
using T = unary_expression_t<op::logical_not, Rhs>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "(";
|
context << "(";
|
||||||
if (trivial_value_is_null_t<Rhs>::value)
|
if (trivial_value_is_null_t<Rhs>::value)
|
||||||
{
|
{
|
||||||
serialize_operand(t._rhs, context);
|
serialize_operand(t._rhs, context);
|
||||||
context << " IS NULL ";
|
context << " IS NULL ";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context << "NOT ";
|
context << "NOT ";
|
||||||
serialize_operand(t._rhs, context);
|
serialize_operand(t._rhs, context);
|
||||||
}
|
}
|
||||||
context << ")";
|
context << ")";
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Lhs, typename O, typename Rhs>
|
template <typename Lhs, typename O, typename Rhs>
|
||||||
struct binary_expression_t:
|
struct binary_expression_t : public expression_operators<binary_expression_t<Lhs, O, Rhs>, value_type_of<O>>,
|
||||||
public expression_operators<binary_expression_t<Lhs, O, Rhs>, value_type_of<O>>,
|
public alias_operators<binary_expression_t<Lhs, O, Rhs>>
|
||||||
public alias_operators<binary_expression_t<Lhs, O, Rhs>>
|
{
|
||||||
{
|
using _traits = make_traits<value_type_of<O>, tag::is_expression>;
|
||||||
using _traits = make_traits<value_type_of<O>, tag::is_expression>;
|
using _nodes = detail::type_vector<Lhs, Rhs>;
|
||||||
using _nodes = detail::type_vector<Lhs, Rhs>;
|
|
||||||
|
|
||||||
binary_expression_t(Lhs lhs, Rhs rhs):
|
binary_expression_t(Lhs lhs, Rhs rhs) : _lhs(lhs), _rhs(rhs)
|
||||||
_lhs(lhs),
|
{
|
||||||
_rhs(rhs)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
binary_expression_t(const binary_expression_t&) = default;
|
binary_expression_t(const binary_expression_t&) = default;
|
||||||
binary_expression_t(binary_expression_t&&) = default;
|
binary_expression_t(binary_expression_t&&) = default;
|
||||||
binary_expression_t& operator=(const binary_expression_t&) = default;
|
binary_expression_t& operator=(const binary_expression_t&) = default;
|
||||||
binary_expression_t& operator=(binary_expression_t&&) = default;
|
binary_expression_t& operator=(binary_expression_t&&) = default;
|
||||||
~binary_expression_t() = default;
|
~binary_expression_t() = default;
|
||||||
|
|
||||||
Lhs _lhs;
|
Lhs _lhs;
|
||||||
Rhs _rhs;
|
Rhs _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Lhs, typename O, typename Rhs>
|
template <typename Context, typename Lhs, typename O, typename Rhs>
|
||||||
struct serializer_t<Context, binary_expression_t<Lhs, O, Rhs>>
|
struct serializer_t<Context, binary_expression_t<Lhs, O, Rhs>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
|
using _serialize_check = serialize_check_of<Context, Lhs, Rhs>;
|
||||||
using T = binary_expression_t<Lhs, O, Rhs>;
|
using T = binary_expression_t<Lhs, O, Rhs>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "(";
|
context << "(";
|
||||||
serialize_operand(t._lhs, context);
|
serialize_operand(t._lhs, context);
|
||||||
context << O::_name;
|
context << O::_name;
|
||||||
serialize_operand(t._rhs, context);
|
serialize_operand(t._rhs, context);
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename O, typename Rhs>
|
template <typename O, typename Rhs>
|
||||||
struct unary_expression_t:
|
struct unary_expression_t : public expression_operators<unary_expression_t<O, Rhs>, value_type_of<O>>,
|
||||||
public expression_operators<unary_expression_t<O, Rhs>, value_type_of<O>>,
|
public alias_operators<unary_expression_t<O, Rhs>>
|
||||||
public alias_operators<unary_expression_t<O, Rhs>>
|
{
|
||||||
{
|
using _traits = make_traits<value_type_of<O>, tag::is_expression>;
|
||||||
using _traits = make_traits<value_type_of<O>, tag::is_expression>;
|
using _nodes = detail::type_vector<Rhs>;
|
||||||
using _nodes = detail::type_vector<Rhs>;
|
|
||||||
|
|
||||||
unary_expression_t(Rhs rhs):
|
unary_expression_t(Rhs rhs) : _rhs(rhs)
|
||||||
_rhs(rhs)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
unary_expression_t(const unary_expression_t&) = default;
|
unary_expression_t(const unary_expression_t&) = default;
|
||||||
unary_expression_t(unary_expression_t&&) = default;
|
unary_expression_t(unary_expression_t&&) = default;
|
||||||
unary_expression_t& operator=(const unary_expression_t&) = default;
|
unary_expression_t& operator=(const unary_expression_t&) = default;
|
||||||
unary_expression_t& operator=(unary_expression_t&&) = default;
|
unary_expression_t& operator=(unary_expression_t&&) = default;
|
||||||
~unary_expression_t() = default;
|
~unary_expression_t() = default;
|
||||||
|
|
||||||
Rhs _rhs;
|
Rhs _rhs;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename O, typename Rhs>
|
template <typename Context, typename O, typename Rhs>
|
||||||
struct serializer_t<Context, unary_expression_t<O, Rhs>>
|
struct serializer_t<Context, unary_expression_t<O, Rhs>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Rhs>;
|
using _serialize_check = serialize_check_of<Context, Rhs>;
|
||||||
using T = unary_expression_t<O, Rhs>;
|
using T = unary_expression_t<O, Rhs>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "(";
|
context << "(";
|
||||||
context << O::_name;
|
context << O::_name;
|
||||||
serialize_operand(t._rhs, context);
|
serialize_operand(t._rhs, context);
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,191 +29,190 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct boolean;
|
struct boolean;
|
||||||
struct integral;
|
struct integral;
|
||||||
struct floating_point;
|
struct floating_point;
|
||||||
|
|
||||||
namespace op
|
namespace op
|
||||||
{
|
{
|
||||||
struct less
|
struct less
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean>;
|
using _traits = make_traits<boolean>;
|
||||||
static constexpr const char* _name = "<";
|
static constexpr const char* _name = "<";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct less_equal
|
struct less_equal
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean>;
|
using _traits = make_traits<boolean>;
|
||||||
static constexpr const char* _name = "<=";
|
static constexpr const char* _name = "<=";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct equal_to
|
struct equal_to
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean>;
|
using _traits = make_traits<boolean>;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct not_equal_to
|
struct not_equal_to
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean>;
|
using _traits = make_traits<boolean>;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct greater_equal
|
struct greater_equal
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean>;
|
using _traits = make_traits<boolean>;
|
||||||
static constexpr const char* _name = ">=";
|
static constexpr const char* _name = ">=";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct greater
|
struct greater
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean>;
|
using _traits = make_traits<boolean>;
|
||||||
static constexpr const char* _name = ">";
|
static constexpr const char* _name = ">";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct logical_or
|
struct logical_or
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean>;
|
using _traits = make_traits<boolean>;
|
||||||
static constexpr const char* _name = " OR ";
|
static constexpr const char* _name = " OR ";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct logical_and
|
struct logical_and
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean>;
|
using _traits = make_traits<boolean>;
|
||||||
static constexpr const char* _name = " AND ";
|
static constexpr const char* _name = " AND ";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct logical_not
|
struct logical_not
|
||||||
{
|
{
|
||||||
using _traits = make_traits<boolean>;
|
using _traits = make_traits<boolean>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template <typename ValueType>
|
||||||
struct plus
|
struct plus
|
||||||
{
|
{
|
||||||
using _traits = make_traits<ValueType>;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "+";
|
static constexpr const char* _name = "+";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template <typename ValueType>
|
||||||
struct minus
|
struct minus
|
||||||
{
|
{
|
||||||
using _traits = make_traits<ValueType>;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "-";
|
static constexpr const char* _name = "-";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template <typename ValueType>
|
||||||
struct multiplies
|
struct multiplies
|
||||||
{
|
{
|
||||||
using _traits = make_traits<ValueType>;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "*";
|
static constexpr const char* _name = "*";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct divides
|
struct divides
|
||||||
{
|
{
|
||||||
using _traits = make_traits<floating_point>;
|
using _traits = make_traits<floating_point>;
|
||||||
static constexpr const char* _name = "/";
|
static constexpr const char* _name = "/";
|
||||||
};
|
};
|
||||||
|
|
||||||
struct modulus
|
struct modulus
|
||||||
{
|
{
|
||||||
using _traits = make_traits<integral>;
|
using _traits = make_traits<integral>;
|
||||||
static constexpr const char* _name = "%";
|
static constexpr const char* _name = "%";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template <typename ValueType>
|
||||||
struct unary_minus
|
struct unary_minus
|
||||||
{
|
{
|
||||||
using _traits = make_traits<ValueType>;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "-";
|
static constexpr const char* _name = "-";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template <typename ValueType>
|
||||||
struct unary_plus
|
struct unary_plus
|
||||||
{
|
{
|
||||||
using _traits = make_traits<ValueType>;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "+";
|
static constexpr const char* _name = "+";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template <typename ValueType>
|
||||||
struct bitwise_and
|
struct bitwise_and
|
||||||
{
|
{
|
||||||
using _traits = make_traits<ValueType>;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "&";
|
static constexpr const char* _name = "&";
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ValueType>
|
template <typename ValueType>
|
||||||
struct bitwise_or
|
struct bitwise_or
|
||||||
{
|
{
|
||||||
using _traits = make_traits<ValueType>;
|
using _traits = make_traits<ValueType>;
|
||||||
static constexpr const char* _name = "|";
|
static constexpr const char* _name = "|";
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
template <typename Lhs, typename O, typename Rhs>
|
||||||
|
struct binary_expression_t;
|
||||||
|
|
||||||
template<typename Lhs, typename O, typename Rhs>
|
template <typename O, typename Rhs>
|
||||||
struct binary_expression_t;
|
struct unary_expression_t;
|
||||||
|
|
||||||
template<typename O, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
struct unary_expression_t;
|
using less_than_t = binary_expression_t<Lhs, op::less, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using less_than_t = binary_expression_t<Lhs, op::less, Rhs>;
|
using less_equal_t = binary_expression_t<Lhs, op::less_equal, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using less_equal_t = binary_expression_t<Lhs, op::less_equal, Rhs>;
|
using equal_to_t = binary_expression_t<Lhs, op::equal_to, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using equal_to_t = binary_expression_t<Lhs, op::equal_to, Rhs>;
|
using not_equal_to_t = binary_expression_t<Lhs, op::not_equal_to, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using not_equal_to_t = binary_expression_t<Lhs, op::not_equal_to, Rhs>;
|
using greater_than_t = binary_expression_t<Lhs, op::greater, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using greater_than_t = binary_expression_t<Lhs, op::greater, Rhs>;
|
using greater_equal_t = binary_expression_t<Lhs, op::greater_equal, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using greater_equal_t = binary_expression_t<Lhs, op::greater_equal, Rhs>;
|
using logical_and_t = binary_expression_t<Lhs, op::logical_and, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using logical_and_t = binary_expression_t<Lhs, op::logical_and, Rhs>;
|
using logical_or_t = binary_expression_t<Lhs, op::logical_or, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename ValueType, typename Rhs>
|
||||||
using logical_or_t = binary_expression_t<Lhs, op::logical_or, Rhs>;
|
using plus_t = binary_expression_t<Lhs, op::plus<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename ValueType, typename Rhs>
|
template <typename Lhs, typename ValueType, typename Rhs>
|
||||||
using plus_t = binary_expression_t<Lhs, op::plus<ValueType>, Rhs>;
|
using minus_t = binary_expression_t<Lhs, op::minus<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename ValueType, typename Rhs>
|
template <typename Lhs, typename ValueType, typename Rhs>
|
||||||
using minus_t = binary_expression_t<Lhs, op::minus<ValueType>, Rhs>;
|
using multiplies_t = binary_expression_t<Lhs, op::multiplies<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename ValueType, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using multiplies_t = binary_expression_t<Lhs, op::multiplies<ValueType>, Rhs>;
|
using divides_t = binary_expression_t<Lhs, op::divides, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using divides_t = binary_expression_t<Lhs, op::divides, Rhs>;
|
using modulus_t = binary_expression_t<Lhs, op::modulus, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Rhs>
|
||||||
using modulus_t = binary_expression_t<Lhs, op::modulus, Rhs>;
|
using logical_not_t = unary_expression_t<op::logical_not, Rhs>;
|
||||||
|
|
||||||
template<typename Rhs>
|
template <typename ValueType, typename Rhs>
|
||||||
using logical_not_t = unary_expression_t<op::logical_not, Rhs>;
|
using unary_plus_t = unary_expression_t<op::unary_plus<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename ValueType, typename Rhs>
|
template <typename ValueType, typename Rhs>
|
||||||
using unary_plus_t = unary_expression_t<op::unary_plus<ValueType>, Rhs>;
|
using unary_minus_t = unary_expression_t<op::unary_minus<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename ValueType, typename Rhs>
|
template <typename Lhs, typename ValueType, typename Rhs>
|
||||||
using unary_minus_t = unary_expression_t<op::unary_minus<ValueType>, Rhs>;
|
using bitwise_and_t = binary_expression_t<Lhs, op::bitwise_and<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename ValueType, typename Rhs>
|
template <typename Lhs, typename ValueType, typename Rhs>
|
||||||
using bitwise_and_t = binary_expression_t<Lhs, op::bitwise_and<ValueType>, Rhs>;
|
using bitwise_or_t = binary_expression_t<Lhs, op::bitwise_or<ValueType>, Rhs>;
|
||||||
|
|
||||||
template<typename Lhs, typename ValueType, typename Rhs>
|
template <typename Expr>
|
||||||
using bitwise_or_t = binary_expression_t<Lhs, op::bitwise_or<ValueType>, Rhs>;
|
using lhs_t = typename Expr::_lhs_t;
|
||||||
|
|
||||||
template<typename Expr>
|
template <typename Expr>
|
||||||
using lhs_t = typename Expr::_lhs_t;
|
using rhs_t = typename Expr::_rhs_t;
|
||||||
|
|
||||||
template<typename Expr>
|
|
||||||
using rhs_t = typename Expr::_rhs_t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,143 +33,155 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename... Tables>
|
template <typename... Tables>
|
||||||
struct extra_tables_data_t
|
struct extra_tables_data_t
|
||||||
{
|
{
|
||||||
extra_tables_data_t()
|
extra_tables_data_t()
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
extra_tables_data_t(const extra_tables_data_t&) = default;
|
extra_tables_data_t(const extra_tables_data_t&) = default;
|
||||||
extra_tables_data_t(extra_tables_data_t&&) = default;
|
extra_tables_data_t(extra_tables_data_t&&) = default;
|
||||||
extra_tables_data_t& operator=(const extra_tables_data_t&) = default;
|
extra_tables_data_t& operator=(const extra_tables_data_t&) = default;
|
||||||
extra_tables_data_t& operator=(extra_tables_data_t&&) = default;
|
extra_tables_data_t& operator=(extra_tables_data_t&&) = default;
|
||||||
~extra_tables_data_t() = default;
|
~extra_tables_data_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
};
|
// EXTRA_TABLES
|
||||||
|
template <typename... Tables>
|
||||||
|
struct extra_tables_t
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_extra_tables>;
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
|
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Tables>...>;
|
||||||
|
using _extra_tables = detail::type_set<Tables...>;
|
||||||
|
|
||||||
// EXTRA_TABLES
|
// Data
|
||||||
template<typename... Tables>
|
using _data_t = extra_tables_data_t<Tables...>;
|
||||||
struct extra_tables_t
|
|
||||||
{
|
|
||||||
using _traits = make_traits<no_value_t, tag::is_extra_tables>;
|
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
using _required_ctes = detail::make_joined_set_t<required_ctes_of<Tables>...>;
|
|
||||||
using _extra_tables = detail::type_set<Tables...>;
|
|
||||||
|
|
||||||
// Data
|
// Member implementation with data and methods
|
||||||
using _data_t = extra_tables_data_t<Tables...>;
|
template <typename Policies>
|
||||||
|
struct _impl_t
|
||||||
|
{
|
||||||
|
_data_t _data;
|
||||||
|
};
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Base template to be inherited by the statement
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
_data_t _data;
|
using _data_t = extra_tables_data_t<Tables...>;
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
_impl_t<Policies> extra_tables;
|
||||||
template<typename Policies>
|
_impl_t<Policies>& operator()()
|
||||||
struct _base_t
|
{
|
||||||
{
|
return extra_tables;
|
||||||
using _data_t = extra_tables_data_t<Tables...>;
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return extra_tables;
|
||||||
|
}
|
||||||
|
|
||||||
_impl_t<Policies> extra_tables;
|
template <typename T>
|
||||||
_impl_t<Policies>& operator()() { return extra_tables; }
|
static auto _get_member(T t) -> decltype(t.extra_tables)
|
||||||
const _impl_t<Policies>& operator()() const { return extra_tables; }
|
{
|
||||||
|
return t.extra_tables;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
using _consistency_check = consistent_t;
|
||||||
static auto _get_member(T t) -> decltype(t.extra_tables)
|
};
|
||||||
{
|
};
|
||||||
return t.extra_tables;
|
|
||||||
}
|
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
// NO EXTRA TABLES YET
|
||||||
};
|
struct no_extra_tables_t
|
||||||
};
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// NO EXTRA TABLES YET
|
// Data
|
||||||
struct no_extra_tables_t
|
using _data_t = no_data_t;
|
||||||
{
|
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
|
|
||||||
// Data
|
// Member implementation with data and methods
|
||||||
using _data_t = no_data_t;
|
template <typename Policies>
|
||||||
|
struct _impl_t
|
||||||
|
{
|
||||||
|
_data_t _data;
|
||||||
|
};
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Base template to be inherited by the statement
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
_data_t _data;
|
using _data_t = no_data_t;
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
_impl_t<Policies> no_extra_tables;
|
||||||
template<typename Policies>
|
_impl_t<Policies>& operator()()
|
||||||
struct _base_t
|
{
|
||||||
{
|
return no_extra_tables;
|
||||||
using _data_t = no_data_t;
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return no_extra_tables;
|
||||||
|
}
|
||||||
|
|
||||||
_impl_t<Policies> no_extra_tables;
|
template <typename T>
|
||||||
_impl_t<Policies>& operator()() { return no_extra_tables; }
|
static auto _get_member(T t) -> decltype(t.no_extra_tables)
|
||||||
const _impl_t<Policies>& operator()() const { return no_extra_tables; }
|
{
|
||||||
|
return t.no_extra_tables;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename Check, typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.no_extra_tables)
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_extra_tables_t, T>;
|
||||||
{
|
|
||||||
return t.no_extra_tables;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Check, typename T>
|
template <typename... T>
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_extra_tables_t, T>;
|
using _check = logic::all_t<is_table_t<T>::value...>;
|
||||||
|
|
||||||
template<typename... T>
|
using _consistency_check = consistent_t;
|
||||||
using _check = logic::all_t<is_table_t<T>::value...>;
|
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
template <typename... Tables>
|
||||||
|
auto extra_tables(Tables... tables) const -> _new_statement_t<_check<Tables...>, extra_tables_t<Tables...>>
|
||||||
|
{
|
||||||
|
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in extra_tables()");
|
||||||
|
|
||||||
template<typename... Tables>
|
return _extra_tables_impl<void>(_check<Tables...>{}, tables...);
|
||||||
auto extra_tables(Tables... tables) const
|
}
|
||||||
-> _new_statement_t<_check<Tables...>, extra_tables_t<Tables...>>
|
|
||||||
{
|
|
||||||
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in extra_tables()");
|
|
||||||
|
|
||||||
return _extra_tables_impl<void>(_check<Tables...>{}, tables...);
|
private:
|
||||||
}
|
template <typename Database, typename... Tables>
|
||||||
|
auto _extra_tables_impl(const std::false_type&, Tables... tables) const -> bad_statement;
|
||||||
|
|
||||||
private:
|
template <typename Database, typename... Tables>
|
||||||
template<typename Database, typename... Tables>
|
auto _extra_tables_impl(const std::true_type&, Tables...) const
|
||||||
auto _extra_tables_impl(const std::false_type&, Tables... tables) const
|
-> _new_statement_t<std::true_type, extra_tables_t<Tables...>>
|
||||||
-> bad_statement;
|
{
|
||||||
|
static_assert(required_tables_of<extra_tables_t<Tables...>>::size::value == 0,
|
||||||
|
"at least one table depends on another table in extra_tables()");
|
||||||
|
|
||||||
template<typename Database, typename... Tables>
|
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
|
||||||
auto _extra_tables_impl(const std::true_type&, Tables...) const
|
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
|
||||||
-> _new_statement_t<std::true_type, extra_tables_t<Tables...>>
|
using _unique_table_names = detail::transform_set_t<name_of, _unique_tables>;
|
||||||
{
|
static_assert(_number_of_tables == _unique_tables::size::value,
|
||||||
static_assert(required_tables_of<extra_tables_t<Tables...>>::size::value == 0, "at least one table depends on another table in extra_tables()");
|
"at least one duplicate table detected in extra_tables()");
|
||||||
|
static_assert(_number_of_tables == _unique_table_names::size::value,
|
||||||
|
"at least one duplicate table name detected in extra_tables()");
|
||||||
|
|
||||||
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
|
return {static_cast<const derived_statement_t<Policies>&>(*this), extra_tables_data_t<Tables...>{}};
|
||||||
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
|
}
|
||||||
using _unique_table_names = detail::transform_set_t<name_of, _unique_tables>;
|
};
|
||||||
static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in extra_tables()");
|
};
|
||||||
static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in extra_tables()");
|
|
||||||
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), extra_tables_data_t<Tables...>{} };
|
// Interpreters
|
||||||
}
|
template <typename Context, typename Database, typename... Tables>
|
||||||
};
|
struct serializer_t<Context, extra_tables_data_t<Database, Tables...>>
|
||||||
};
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, Tables...>;
|
||||||
// Interpreters
|
using T = extra_tables_data_t<Database, Tables...>;
|
||||||
template<typename Context, typename Database, typename... Tables>
|
|
||||||
struct serializer_t<Context, extra_tables_data_t<Database, Tables...>>
|
|
||||||
{
|
|
||||||
using _serialize_check = serialize_check_of<Context, Tables...>;
|
|
||||||
using T = extra_tables_data_t<Database, Tables...>;
|
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
|
||||||
{
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T&, Context& context)
|
||||||
|
{
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,47 +31,49 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename NameType, typename ValueType, bool CanBeNull, bool NullIsTrivialValue>
|
template <typename NameType, typename ValueType, bool CanBeNull, bool NullIsTrivialValue>
|
||||||
struct field_spec_t
|
struct field_spec_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<ValueType, tag::is_noop,
|
using _traits = make_traits<ValueType,
|
||||||
tag_if<tag::can_be_null, CanBeNull>,
|
tag::is_noop,
|
||||||
tag_if<tag::null_is_trivial_value, NullIsTrivialValue>
|
tag_if<tag::can_be_null, CanBeNull>,
|
||||||
>;
|
tag_if<tag::null_is_trivial_value, NullIsTrivialValue>>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
using _alias_t = NameType;
|
using _alias_t = NameType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename AliasProvider, typename FieldSpecTuple>
|
template <typename AliasProvider, typename FieldSpecTuple>
|
||||||
struct multi_field_spec_t
|
struct multi_field_spec_t
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Select, typename NamedExpr>
|
template <typename Select, typename NamedExpr>
|
||||||
struct make_field_spec_impl
|
struct make_field_spec_impl
|
||||||
{
|
{
|
||||||
static constexpr bool _can_be_null = can_be_null_t<NamedExpr>::value;
|
static constexpr bool _can_be_null = can_be_null_t<NamedExpr>::value;
|
||||||
static constexpr bool _depends_on_outer_table = detail::make_intersect_set_t<required_tables_of<NamedExpr>, typename Select::_used_outer_tables>::size::value > 0;
|
static constexpr bool _depends_on_outer_table =
|
||||||
|
detail::make_intersect_set_t<required_tables_of<NamedExpr>,
|
||||||
|
typename Select::_used_outer_tables>::size::value > 0;
|
||||||
|
|
||||||
using type = field_spec_t<typename NamedExpr::_alias_t,
|
using type = field_spec_t<typename NamedExpr::_alias_t,
|
||||||
value_type_of<NamedExpr>,
|
value_type_of<NamedExpr>,
|
||||||
logic::any_t<_can_be_null, _depends_on_outer_table>::value,
|
logic::any_t<_can_be_null, _depends_on_outer_table>::value,
|
||||||
null_is_trivial_value_t<NamedExpr>::value>;
|
null_is_trivial_value_t<NamedExpr>::value>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Select, typename AliasProvider, typename... NamedExprs>
|
template <typename Select, typename AliasProvider, typename... NamedExprs>
|
||||||
struct make_field_spec_impl<Select, multi_column_alias_t<AliasProvider, NamedExprs...>>
|
struct make_field_spec_impl<Select, multi_column_alias_t<AliasProvider, NamedExprs...>>
|
||||||
{
|
{
|
||||||
using type = multi_field_spec_t<AliasProvider, std::tuple<typename make_field_spec_impl<Select, NamedExprs>::type...>>;
|
using type =
|
||||||
};
|
multi_field_spec_t<AliasProvider, std::tuple<typename make_field_spec_impl<Select, NamedExprs>::type...>>;
|
||||||
}
|
};
|
||||||
|
}
|
||||||
template<typename Select, typename NamedExpr>
|
|
||||||
using make_field_spec_t = typename detail::make_field_spec_impl<Select, NamedExpr>::type;
|
|
||||||
|
|
||||||
|
template <typename Select, typename NamedExpr>
|
||||||
|
using make_field_spec_t = typename detail::make_field_spec_impl<Select, NamedExpr>::type;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,258 +35,256 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// floating_point value type
|
// floating_point value type
|
||||||
struct floating_point
|
struct floating_point
|
||||||
{
|
{
|
||||||
using _traits = make_traits<floating_point, tag::is_value_type>;
|
using _traits = make_traits<floating_point, tag::is_value_type>;
|
||||||
using _tag = tag::is_floating_point;
|
using _tag = tag::is_floating_point;
|
||||||
using _cpp_value_type = double;
|
using _cpp_value_type = double;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_numeric_t<T>;
|
using _is_valid_operand = is_numeric_t<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// floating_point parameter type
|
// floating_point parameter type
|
||||||
template<>
|
template <>
|
||||||
struct parameter_value_t<floating_point>
|
struct parameter_value_t<floating_point>
|
||||||
{
|
{
|
||||||
using _value_type = floating_point;
|
using _value_type = floating_point;
|
||||||
using _cpp_value_type = typename _value_type::_cpp_value_type;
|
using _cpp_value_type = typename _value_type::_cpp_value_type;
|
||||||
|
|
||||||
parameter_value_t():
|
parameter_value_t() : _value(0), _is_null(true)
|
||||||
_value(0),
|
{
|
||||||
_is_null(true)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
parameter_value_t(const _cpp_value_type& val):
|
parameter_value_t(const _cpp_value_type& val) : _value(val), _is_null(false)
|
||||||
_value(val),
|
{
|
||||||
_is_null(false)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
parameter_value_t& operator=(const _cpp_value_type& val)
|
parameter_value_t& operator=(const _cpp_value_type& val)
|
||||||
{
|
{
|
||||||
_value = val;
|
_value = val;
|
||||||
_is_null = false;
|
_is_null = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
|
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
|
||||||
{
|
{
|
||||||
if (t._is_trivial())
|
if (t._is_trivial())
|
||||||
{
|
{
|
||||||
_value = 0;
|
_value = 0;
|
||||||
_is_null = true;
|
_is_null = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_value = t._value._t;
|
_value = t._value._t;
|
||||||
_is_null = false;
|
_is_null = false;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_value_t& operator=(const std::nullptr_t&)
|
parameter_value_t& operator=(const std::nullptr_t&)
|
||||||
{
|
{
|
||||||
_value = 0;
|
_value = 0;
|
||||||
_is_null = true;
|
_is_null = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_null() const
|
bool is_null() const
|
||||||
{
|
{
|
||||||
return _is_null;
|
return _is_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _cpp_value_type& value() const
|
const _cpp_value_type& value() const
|
||||||
{
|
{
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator _cpp_value_type() const { return _value; }
|
operator _cpp_value_type() const
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Target>
|
template <typename Target>
|
||||||
void _bind(Target& target, size_t index) const
|
void _bind(Target& target, size_t index) const
|
||||||
{
|
{
|
||||||
target._bind_floating_point_parameter(index, &_value, _is_null);
|
target._bind_floating_point_parameter(index, &_value, _is_null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_cpp_value_type _value;
|
_cpp_value_type _value;
|
||||||
bool _is_null;
|
bool _is_null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// floating_point expression operators
|
// floating_point expression operators
|
||||||
template<typename Expr>
|
template <typename Expr>
|
||||||
struct expression_operators<Expr, floating_point>:
|
struct expression_operators<Expr, floating_point> : public basic_expression_operators<Expr, floating_point>
|
||||||
public basic_expression_operators<Expr, floating_point>
|
{
|
||||||
{
|
template <typename T>
|
||||||
template<typename T>
|
using _is_valid_operand = is_valid_operand<floating_point, T>;
|
||||||
using _is_valid_operand = is_valid_operand<floating_point, T>;
|
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
plus_t<Expr, floating_point, wrap_operand_t<T>> operator +(T t) const
|
plus_t<Expr, floating_point, wrap_operand_t<T>> operator+(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), rhs{t} };
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
minus_t<Expr, floating_point, wrap_operand_t<T>> operator -(T t) const
|
minus_t<Expr, floating_point, wrap_operand_t<T>> operator-(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), rhs{t} };
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
multiplies_t<Expr, floating_point, wrap_operand_t<T>> operator *(T t) const
|
multiplies_t<Expr, floating_point, wrap_operand_t<T>> operator*(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), rhs{t} };
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
divides_t<Expr, wrap_operand_t<T>> operator /(T t) const
|
divides_t<Expr, wrap_operand_t<T>> operator/(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
|
|
||||||
return { *static_cast<const Expr*>(this), rhs{t} };
|
return {*static_cast<const Expr*>(this), rhs{t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
unary_plus_t<floating_point, Expr> operator +() const
|
unary_plus_t<floating_point, Expr> operator+() const
|
||||||
{
|
{
|
||||||
return { *static_cast<const Expr*>(this) };
|
return {*static_cast<const Expr*>(this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
unary_minus_t<floating_point, Expr> operator -() const
|
unary_minus_t<floating_point, Expr> operator-() const
|
||||||
{
|
{
|
||||||
return { *static_cast<const Expr*>(this) };
|
return {*static_cast<const Expr*>(this)};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// floating_point column operators
|
// floating_point column operators
|
||||||
template<typename Column>
|
template <typename Column>
|
||||||
struct column_operators<Column, floating_point>
|
struct column_operators<Column, floating_point>
|
||||||
{
|
{
|
||||||
template<typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_valid_operand<floating_point, T>;
|
using _is_valid_operand = is_valid_operand<floating_point, T>;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto operator +=(T t) const -> assignment_t<Column, plus_t<Column, floating_point, wrap_operand_t<T>>>
|
auto operator+=(T t) const -> assignment_t<Column, plus_t<Column, floating_point, wrap_operand_t<T>>>
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||||
|
|
||||||
return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
|
return {*static_cast<const Column*>(this), {*static_cast<const Column*>(this), rhs{t}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto operator -=(T t) const -> assignment_t<Column, minus_t<Column, floating_point, wrap_operand_t<T>>>
|
auto operator-=(T t) const -> assignment_t<Column, minus_t<Column, floating_point, wrap_operand_t<T>>>
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||||
|
|
||||||
return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
|
return {*static_cast<const Column*>(this), {*static_cast<const Column*>(this), rhs{t}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto operator /=(T t) const -> assignment_t<Column, divides_t<Column, wrap_operand_t<T>>>
|
auto operator/=(T t) const -> assignment_t<Column, divides_t<Column, wrap_operand_t<T>>>
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||||
|
|
||||||
return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
|
return {*static_cast<const Column*>(this), {*static_cast<const Column*>(this), rhs{t}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto operator *=(T t) const -> assignment_t<Column, multiplies_t<Column, floating_point, wrap_operand_t<T>>>
|
auto operator*=(T t) const -> assignment_t<Column, multiplies_t<Column, floating_point, wrap_operand_t<T>>>
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||||
|
|
||||||
return { *static_cast<const Column*>(this), { *static_cast<const Column*>(this), rhs{t} } };
|
return {*static_cast<const Column*>(this), {*static_cast<const Column*>(this), rhs{t}}};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// floating_point result field
|
// floating_point result field
|
||||||
template<typename Db, typename FieldSpec>
|
template <typename Db, typename FieldSpec>
|
||||||
struct result_field_t<floating_point, Db, FieldSpec>: public result_field_methods_t<result_field_t<floating_point, Db, FieldSpec>>
|
struct result_field_t<floating_point, Db, FieldSpec>
|
||||||
{
|
: public result_field_methods_t<result_field_t<floating_point, Db, FieldSpec>>
|
||||||
static_assert(std::is_same<value_type_of<FieldSpec>, floating_point>::value, "field type mismatch");
|
{
|
||||||
using _cpp_value_type = typename floating_point::_cpp_value_type;
|
static_assert(std::is_same<value_type_of<FieldSpec>, floating_point>::value, "field type mismatch");
|
||||||
|
using _cpp_value_type = typename floating_point::_cpp_value_type;
|
||||||
|
|
||||||
result_field_t():
|
result_field_t() : _is_valid(false), _is_null(true), _value(0)
|
||||||
_is_valid(false),
|
{
|
||||||
_is_null(true),
|
}
|
||||||
_value(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void _validate()
|
void _validate()
|
||||||
{
|
{
|
||||||
_is_valid = true;
|
_is_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _invalidate()
|
void _invalidate()
|
||||||
{
|
{
|
||||||
_is_valid = false;
|
_is_valid = false;
|
||||||
_is_null = true;
|
_is_null = true;
|
||||||
_value = 0;
|
_value = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_null() const
|
bool is_null() const
|
||||||
{
|
{
|
||||||
if (not _is_valid)
|
if (not _is_valid)
|
||||||
throw exception("accessing is_null in non-existing row");
|
throw exception("accessing is_null in non-existing row");
|
||||||
return _is_null;
|
return _is_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _is_trivial() const
|
bool _is_trivial() const
|
||||||
{
|
{
|
||||||
if (not _is_valid)
|
if (not _is_valid)
|
||||||
throw exception("accessing is_null in non-existing row");
|
throw exception("accessing is_null in non-existing row");
|
||||||
|
|
||||||
return value() == 0;
|
return value() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
_cpp_value_type value() const
|
_cpp_value_type value() const
|
||||||
{
|
{
|
||||||
if (not _is_valid)
|
if (not _is_valid)
|
||||||
throw exception("accessing value in non-existing row");
|
throw exception("accessing value in non-existing row");
|
||||||
|
|
||||||
if (_is_null)
|
if (_is_null)
|
||||||
{
|
{
|
||||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||||
{
|
{
|
||||||
throw exception("accessing value of NULL field");
|
throw exception("accessing value of NULL field");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Target>
|
template <typename Target>
|
||||||
void _bind(Target& target, size_t i)
|
void _bind(Target& target, size_t i)
|
||||||
{
|
{
|
||||||
target._bind_floating_point_result(i, &_value, &_is_null);
|
target._bind_floating_point_result(i, &_value, &_is_null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _is_valid;
|
bool _is_valid;
|
||||||
bool _is_null;
|
bool _is_null;
|
||||||
_cpp_value_type _value;
|
_cpp_value_type _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Db, typename FieldSpec>
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, const result_field_t<floating_point, Db, FieldSpec>& e)
|
|
||||||
{
|
|
||||||
return serialize(e, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename Db, typename FieldSpec>
|
||||||
|
inline std::ostream& operator<<(std::ostream& os, const result_field_t<floating_point, Db, FieldSpec>& e)
|
||||||
|
{
|
||||||
|
return serialize(e, os);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,197 +38,213 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// FROM DATA
|
// FROM DATA
|
||||||
template<typename Database, typename... Tables>
|
template <typename Database, typename... Tables>
|
||||||
struct from_data_t
|
struct from_data_t
|
||||||
{
|
{
|
||||||
from_data_t(Tables... tables):
|
from_data_t(Tables... tables) : _tables(tables...)
|
||||||
_tables(tables...)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
from_data_t(const from_data_t&) = default;
|
from_data_t(const from_data_t&) = default;
|
||||||
from_data_t(from_data_t&&) = default;
|
from_data_t(from_data_t&&) = default;
|
||||||
from_data_t& operator=(const from_data_t&) = default;
|
from_data_t& operator=(const from_data_t&) = default;
|
||||||
from_data_t& operator=(from_data_t&&) = default;
|
from_data_t& operator=(from_data_t&&) = default;
|
||||||
~from_data_t() = default;
|
~from_data_t() = default;
|
||||||
|
|
||||||
std::tuple<Tables...> _tables;
|
std::tuple<Tables...> _tables;
|
||||||
interpretable_list_t<Database> _dynamic_tables;
|
interpretable_list_t<Database> _dynamic_tables;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FROM
|
// FROM
|
||||||
template<typename Database, typename... Tables>
|
template <typename Database, typename... Tables>
|
||||||
struct from_t
|
struct from_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_from>;
|
using _traits = make_traits<no_value_t, tag::is_from>;
|
||||||
using _nodes = detail::type_vector<Tables...>;
|
using _nodes = detail::type_vector<Tables...>;
|
||||||
using _is_dynamic = is_database<Database>;
|
using _is_dynamic = is_database<Database>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = from_data_t<Database, Tables...>;
|
using _data_t = from_data_t<Database, Tables...>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
template<typename Table>
|
template <typename Table>
|
||||||
void add(Table table)
|
void add(Table table)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "from::add() must not be called for static from()");
|
static_assert(_is_dynamic::value, "from::add() must not be called for static from()");
|
||||||
static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
|
static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
|
||||||
using _known_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table
|
using _known_tables =
|
||||||
using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
|
detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table
|
||||||
static_assert(not detail::is_element_of<typename Table::_alias_t, _known_table_names>::value, "Must not use the same table name twice in from()");
|
using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
|
||||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Table>;
|
static_assert(not detail::is_element_of<typename Table::_alias_t, _known_table_names>::value,
|
||||||
_serialize_check::_();
|
"Must not use the same table name twice in from()");
|
||||||
|
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Table>;
|
||||||
|
_serialize_check::_();
|
||||||
|
|
||||||
using ok = logic::all_t<_is_dynamic::value, is_table_t<Table>::value, _serialize_check::type::value>;
|
using ok = logic::all_t<_is_dynamic::value, is_table_t<Table>::value, _serialize_check::type::value>;
|
||||||
|
|
||||||
_add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
|
_add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Table>
|
template <typename Table>
|
||||||
void _add_impl(Table table, const std::true_type&)
|
void _add_impl(Table table, const std::true_type&)
|
||||||
{
|
{
|
||||||
return _data._dynamic_tables.emplace_back(from_table(table));
|
return _data._dynamic_tables.emplace_back(from_table(table));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Table>
|
template <typename Table>
|
||||||
void _add_impl(Table table, const std::false_type&);
|
void _add_impl(Table table, const std::false_type&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Base template to be inherited by the statement
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
using _data_t = from_data_t<Database, Tables...>;
|
using _data_t = from_data_t<Database, Tables...>;
|
||||||
|
|
||||||
_impl_t<Policies> from;
|
_impl_t<Policies> from;
|
||||||
_impl_t<Policies>& operator()() { return from; }
|
_impl_t<Policies>& operator()()
|
||||||
const _impl_t<Policies>& operator()() const { return from; }
|
{
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.from)
|
static auto _get_member(T t) -> decltype(t.from)
|
||||||
{
|
{
|
||||||
return t.from;
|
return t.from;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: We might want to check if we have too many tables define in the FROM
|
// FIXME: We might want to check if we have too many tables define in the FROM
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = consistent_t;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct no_from_t
|
struct no_from_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = no_data_t;
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Base template to be inherited by the statement
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
using _data_t = no_data_t;
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
_impl_t<Policies> no_from;
|
_impl_t<Policies> no_from;
|
||||||
_impl_t<Policies>& operator()() { return no_from; }
|
_impl_t<Policies>& operator()()
|
||||||
const _impl_t<Policies>& operator()() const { return no_from; }
|
{
|
||||||
|
return no_from;
|
||||||
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return no_from;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.no_from)
|
static auto _get_member(T t) -> decltype(t.no_from)
|
||||||
{
|
{
|
||||||
return t.no_from;
|
return t.no_from;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _database_t = typename Policies::_database_t;
|
using _database_t = typename Policies::_database_t;
|
||||||
|
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
using _check = logic::all_t<is_table_t<T>::value...>;
|
using _check = logic::all_t<is_table_t<T>::value...>;
|
||||||
|
|
||||||
template<typename Check, typename T>
|
template <typename Check, typename T>
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_from_t, T>;
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_from_t, T>;
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = consistent_t;
|
||||||
|
|
||||||
template<typename... Tables>
|
template <typename... Tables>
|
||||||
auto from(Tables... tables) const
|
auto from(Tables... tables) const -> _new_statement_t<_check<Tables...>, from_t<void, from_table_t<Tables>...>>
|
||||||
-> _new_statement_t<_check<Tables...>, from_t<void, from_table_t<Tables>...>>
|
{
|
||||||
{
|
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
|
||||||
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
|
static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
|
||||||
static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
|
return _from_impl<void>(_check<Tables...>{}, tables...);
|
||||||
return _from_impl<void>(_check<Tables...>{}, tables...);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Tables>
|
template <typename... Tables>
|
||||||
auto dynamic_from(Tables... tables) const
|
auto dynamic_from(Tables... tables) const
|
||||||
-> _new_statement_t<_check<Tables...>, from_t<_database_t, from_table_t<Tables>...>>
|
-> _new_statement_t<_check<Tables...>, from_t<_database_t, from_table_t<Tables>...>>
|
||||||
{
|
{
|
||||||
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
|
static_assert(not std::is_same<_database_t, void>::value,
|
||||||
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
|
"dynamic_from must not be called in a static statement");
|
||||||
return _from_impl<_database_t>(_check<Tables...>{}, tables...);
|
static_assert(_check<Tables...>::value, "at least one argument is not a table or join in from()");
|
||||||
}
|
return _from_impl<_database_t>(_check<Tables...>{}, tables...);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Database, typename... Tables>
|
template <typename Database, typename... Tables>
|
||||||
auto _from_impl(const std::false_type&, Tables... tables) const
|
auto _from_impl(const std::false_type&, Tables... tables) const -> bad_statement;
|
||||||
-> bad_statement;
|
|
||||||
|
|
||||||
template<typename Database, typename... Tables>
|
template <typename Database, typename... Tables>
|
||||||
auto _from_impl(const std::true_type&, Tables... tables) const
|
auto _from_impl(const std::true_type&, Tables... tables) const
|
||||||
-> _new_statement_t<std::true_type, from_t<Database, from_table_t<Tables>...>>
|
-> _new_statement_t<std::true_type, from_t<Database, from_table_t<Tables>...>>
|
||||||
{
|
{
|
||||||
static_assert(required_tables_of<from_t<Database, Tables...>>::size::value == 0, "at least one table depends on another table in from()");
|
static_assert(required_tables_of<from_t<Database, Tables...>>::size::value == 0,
|
||||||
|
"at least one table depends on another table in from()");
|
||||||
|
|
||||||
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
|
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
|
||||||
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
|
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
|
||||||
using _unique_table_names = detail::transform_set_t<name_of, _unique_tables>;
|
using _unique_table_names = detail::transform_set_t<name_of, _unique_tables>;
|
||||||
static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()");
|
static_assert(_number_of_tables == _unique_tables::size::value,
|
||||||
static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()");
|
"at least one duplicate table detected in from()");
|
||||||
|
static_assert(_number_of_tables == _unique_table_names::size::value,
|
||||||
|
"at least one duplicate table name detected in from()");
|
||||||
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), from_data_t<Database, from_table_t<Tables>...>{from_table(tables)...} };
|
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
||||||
}
|
from_data_t<Database, from_table_t<Tables>...>{from_table(tables)...}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
// Interpreters
|
||||||
};
|
template <typename Context, typename Database, typename... Tables>
|
||||||
|
struct serializer_t<Context, from_data_t<Database, Tables...>>
|
||||||
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, Tables...>;
|
||||||
|
using T = from_data_t<Database, Tables...>;
|
||||||
|
|
||||||
// Interpreters
|
static Context& _(const T& t, Context& context)
|
||||||
template<typename Context, typename Database, typename... Tables>
|
{
|
||||||
struct serializer_t<Context, from_data_t<Database, Tables...>>
|
if (sizeof...(Tables) == 0 and t._dynamic_tables.empty())
|
||||||
{
|
return context;
|
||||||
using _serialize_check = serialize_check_of<Context, Tables...>;
|
context << " FROM ";
|
||||||
using T = from_data_t<Database, Tables...>;
|
interpret_tuple(t._tables, ',', context);
|
||||||
|
if (sizeof...(Tables) and not t._dynamic_tables.empty())
|
||||||
|
context << ',';
|
||||||
|
interpret_list(t._dynamic_tables, ',', context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
template <typename... T>
|
||||||
{
|
auto from(T&&... t) -> decltype(statement_t<void, no_from_t>().from(std::forward<T>(t)...))
|
||||||
if (sizeof...(Tables) == 0 and t._dynamic_tables.empty())
|
{
|
||||||
return context;
|
return statement_t<void, no_from_t>().from(std::forward<T>(t)...);
|
||||||
context << " FROM ";
|
}
|
||||||
interpret_tuple(t._tables, ',', context);
|
|
||||||
if (sizeof...(Tables) and not t._dynamic_tables.empty())
|
|
||||||
context << ',';
|
|
||||||
interpret_list(t._dynamic_tables, ',', context);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... T>
|
|
||||||
auto from(T&&... t) -> decltype(statement_t<void, no_from_t>().from(std::forward<T>(t)...))
|
|
||||||
{
|
|
||||||
return statement_t<void, no_from_t>().from(std::forward<T>(t)...);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,103 +44,105 @@
|
|||||||
#include <sqlpp11/avg.h>
|
#include <sqlpp11/avg.h>
|
||||||
#include <sqlpp11/sum.h>
|
#include <sqlpp11/sum.h>
|
||||||
#include <sqlpp11/value_type.h>
|
#include <sqlpp11/value_type.h>
|
||||||
#include <sqlpp11/verbatim.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim
|
#include <sqlpp11/verbatim.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim
|
||||||
#include <sqlpp11/verbatim_table.h>
|
#include <sqlpp11/verbatim_table.h>
|
||||||
#include <sqlpp11/value_or_null.h>
|
#include <sqlpp11/value_or_null.h>
|
||||||
#include <sqlpp11/eval.h>
|
#include <sqlpp11/eval.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename T>
|
template <typename T>
|
||||||
auto value(T t) -> wrap_operand_t<T>
|
auto value(T t) -> wrap_operand_t<T>
|
||||||
{
|
{
|
||||||
static_assert(is_wrapped_value_t<wrap_operand_t<T>>::value, "value() is to be called with non-sql-type like int, or string");
|
static_assert(is_wrapped_value_t<wrap_operand_t<T>>::value,
|
||||||
return { t };
|
"value() is to be called with non-sql-type like int, or string");
|
||||||
}
|
return {t};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Expression, typename Db>
|
template <typename Expression, typename Db>
|
||||||
auto flatten(const Expression& exp, Db& db) -> verbatim_t<value_type_of<Expression>>
|
auto flatten(const Expression& exp, Db& db) -> verbatim_t<value_type_of<Expression>>
|
||||||
{
|
{
|
||||||
static_assert(not make_parameter_list_t<Expression>::size::value, "parameters are not allowed in flattened expressions");
|
static_assert(not make_parameter_list_t<Expression>::size::value,
|
||||||
auto context = db.get_serializer_context();
|
"parameters are not allowed in flattened expressions");
|
||||||
serialize(exp, context);
|
auto context = db.get_serializer_context();
|
||||||
return { context.str() };
|
serialize(exp, context);
|
||||||
}
|
return {context.str()};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
auto is_null(Expression e) -> decltype(e.is_null())
|
auto is_null(Expression e) -> decltype(e.is_null())
|
||||||
{
|
{
|
||||||
return e.is_null();
|
return e.is_null();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
auto is_not_null(Expression e) -> decltype(e.is_not_null())
|
auto is_not_null(Expression e) -> decltype(e.is_not_null())
|
||||||
{
|
{
|
||||||
return e.is_not_null();
|
return e.is_not_null();
|
||||||
}
|
}
|
||||||
|
|
||||||
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 _traits = make_traits<value_type_t<typename Container::value_type>, tag::is_expression>;
|
using _traits = make_traits<value_type_t<typename Container::value_type>, tag::is_expression>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
using _container_t = Container;
|
using _container_t = Container;
|
||||||
|
|
||||||
value_list_t(_container_t container):
|
value_list_t(_container_t container) : _container(container)
|
||||||
_container(container)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
value_list_t(const value_list_t&) = default;
|
value_list_t(const value_list_t&) = default;
|
||||||
value_list_t(value_list_t&&) = default;
|
value_list_t(value_list_t&&) = default;
|
||||||
value_list_t& operator=(const value_list_t&) = default;
|
value_list_t& operator=(const value_list_t&) = default;
|
||||||
value_list_t& operator=(value_list_t&&) = default;
|
value_list_t& operator=(value_list_t&&) = default;
|
||||||
~value_list_t() = default;
|
~value_list_t() = default;
|
||||||
|
|
||||||
_container_t _container;
|
_container_t _container;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Container>
|
template <typename Context, typename Container>
|
||||||
struct serializer_t<Context, value_list_t<Container>>
|
struct serializer_t<Context, value_list_t<Container>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, wrap_operand_t<typename Container::value_type>>;
|
using _serialize_check = serialize_check_of<Context, wrap_operand_t<typename Container::value_type>>;
|
||||||
using T = value_list_t<Container>;
|
using T = value_list_t<Container>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if (t._container.size() == 1)
|
if (t._container.size() == 1)
|
||||||
{
|
{
|
||||||
return serialize(value(*begin(t._container)), context);
|
return serialize(value(*begin(t._container)), context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (const auto& entry: t._container)
|
for (const auto& entry : t._container)
|
||||||
{
|
{
|
||||||
if (first)
|
if (first)
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else
|
||||||
context << ',';
|
context << ',';
|
||||||
|
|
||||||
serialize_operand(value(entry), context);
|
serialize_operand(value(entry), context);
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Container>
|
|
||||||
auto value_list(Container c) -> value_list_t<Container>
|
|
||||||
{
|
|
||||||
static_assert(is_wrapped_value_t<wrap_operand_t<typename Container::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 { c };
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
constexpr const char* get_sql_name(const T&)
|
|
||||||
{
|
|
||||||
return name_of<T>::char_ptr();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
auto value_list(Container c) -> value_list_t<Container>
|
||||||
|
{
|
||||||
|
static_assert(
|
||||||
|
is_wrapped_value_t<wrap_operand_t<typename Container::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 {c};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr const char* get_sql_name(const T&)
|
||||||
|
{
|
||||||
|
return name_of<T>::char_ptr();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,203 +37,220 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// GROUP BY DATA
|
// GROUP BY DATA
|
||||||
template<typename Database, typename... Expressions>
|
template <typename Database, typename... Expressions>
|
||||||
struct group_by_data_t
|
struct group_by_data_t
|
||||||
{
|
{
|
||||||
group_by_data_t(Expressions... expressions):
|
group_by_data_t(Expressions... expressions) : _expressions(expressions...)
|
||||||
_expressions(expressions...)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
group_by_data_t(const group_by_data_t&) = default;
|
group_by_data_t(const group_by_data_t&) = default;
|
||||||
group_by_data_t(group_by_data_t&&) = default;
|
group_by_data_t(group_by_data_t&&) = default;
|
||||||
group_by_data_t& operator=(const group_by_data_t&) = default;
|
group_by_data_t& operator=(const group_by_data_t&) = default;
|
||||||
group_by_data_t& operator=(group_by_data_t&&) = default;
|
group_by_data_t& operator=(group_by_data_t&&) = default;
|
||||||
~group_by_data_t() = default;
|
~group_by_data_t() = default;
|
||||||
|
|
||||||
std::tuple<Expressions...> _expressions;
|
std::tuple<Expressions...> _expressions;
|
||||||
interpretable_list_t<Database> _dynamic_expressions;
|
interpretable_list_t<Database> _dynamic_expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct assert_no_unknown_tables_in_group_by_t
|
struct assert_no_unknown_tables_in_group_by_t
|
||||||
{
|
{
|
||||||
using type = std::false_type;
|
using type = std::false_type;
|
||||||
|
|
||||||
template<typename T = void>
|
template <typename T = void>
|
||||||
static void _()
|
static void _()
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "at least one group-by expression requires a table which is otherwise not known in the statement");
|
static_assert(wrong_t<T>::value,
|
||||||
}
|
"at least one group-by expression requires a table which is otherwise not known in the statement");
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// GROUP BY
|
// GROUP BY
|
||||||
template<typename Database, typename... Expressions>
|
template <typename Database, typename... Expressions>
|
||||||
struct group_by_t
|
struct group_by_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_group_by>;
|
using _traits = make_traits<no_value_t, tag::is_group_by>;
|
||||||
using _nodes = detail::type_vector<Expressions...>;
|
using _nodes = detail::type_vector<Expressions...>;
|
||||||
|
|
||||||
using _is_dynamic = is_database<Database>;
|
using _is_dynamic = is_database<Database>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = group_by_data_t<Database, Expressions...>;
|
using _data_t = group_by_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
void add_ntc(Expression expression)
|
void add_ntc(Expression expression)
|
||||||
{
|
{
|
||||||
add<Expression, std::false_type>(expression);
|
add<Expression, std::false_type>(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression, typename TableCheckRequired = std::true_type>
|
template <typename Expression, typename TableCheckRequired = std::true_type>
|
||||||
void add(Expression expression)
|
void add(Expression expression)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "add() must not be called for static group_by");
|
static_assert(_is_dynamic::value, "add() must not be called for static group_by");
|
||||||
static_assert(is_expression_t<Expression>::value, "invalid expression argument in group_by::add()");
|
static_assert(is_expression_t<Expression>::value, "invalid expression argument in group_by::add()");
|
||||||
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in group_by::add()");
|
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value,
|
||||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
|
"expression uses tables unknown to this statement in group_by::add()");
|
||||||
_serialize_check::_();
|
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
|
||||||
|
_serialize_check::_();
|
||||||
|
|
||||||
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expression>::value, _serialize_check::type::value>;
|
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expression>::value, _serialize_check::type::value>;
|
||||||
|
|
||||||
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
|
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
void _add_impl(Expression expression, const std::true_type&)
|
void _add_impl(Expression expression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return _data._dynamic_expressions.emplace_back(expression);
|
return _data._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
void _add_impl(Expression expression, const std::false_type&);
|
void _add_impl(Expression expression, const std::false_type&);
|
||||||
public:
|
|
||||||
_data_t _data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
public:
|
||||||
template<typename Policies>
|
_data_t _data;
|
||||||
struct _base_t
|
};
|
||||||
{
|
|
||||||
using _data_t = group_by_data_t<Database, Expressions...>;
|
|
||||||
|
|
||||||
_impl_t<Policies> group_by;
|
// Base template to be inherited by the statement
|
||||||
_impl_t<Policies>& operator()() { return group_by; }
|
template <typename Policies>
|
||||||
const _impl_t<Policies>& operator()() const { return group_by; }
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = group_by_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
template<typename T>
|
_impl_t<Policies> group_by;
|
||||||
static auto _get_member(T t) -> decltype(t.group_by)
|
_impl_t<Policies>& operator()()
|
||||||
{
|
{
|
||||||
return t.group_by;
|
return group_by;
|
||||||
}
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return group_by;
|
||||||
|
}
|
||||||
|
|
||||||
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<group_by_t>::value,
|
template <typename T>
|
||||||
consistent_t,
|
static auto _get_member(T t) -> decltype(t.group_by)
|
||||||
assert_no_unknown_tables_in_group_by_t>::type;
|
{
|
||||||
};
|
return t.group_by;
|
||||||
};
|
}
|
||||||
|
|
||||||
// NO GROUP BY YET
|
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<group_by_t>::value,
|
||||||
struct no_group_by_t
|
consistent_t,
|
||||||
{
|
assert_no_unknown_tables_in_group_by_t>::type;
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
};
|
||||||
using _nodes = detail::type_vector<>;
|
};
|
||||||
|
|
||||||
// Data
|
// NO GROUP BY YET
|
||||||
using _data_t = no_data_t;
|
struct no_group_by_t
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Data
|
||||||
template<typename Policies>
|
using _data_t = no_data_t;
|
||||||
struct _impl_t
|
|
||||||
{
|
|
||||||
_data_t _data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Member implementation with data and methods
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
using _data_t = no_data_t;
|
_data_t _data;
|
||||||
|
};
|
||||||
|
|
||||||
_impl_t<Policies> no_group_by;
|
// Base template to be inherited by the statement
|
||||||
_impl_t<Policies>& operator()() { return no_group_by; }
|
template <typename Policies>
|
||||||
const _impl_t<Policies>& operator()() const { return no_group_by; }
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
template<typename T>
|
_impl_t<Policies> no_group_by;
|
||||||
static auto _get_member(T t) -> decltype(t.no_group_by)
|
_impl_t<Policies>& operator()()
|
||||||
{
|
{
|
||||||
return t.no_group_by;
|
return no_group_by;
|
||||||
}
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return no_group_by;
|
||||||
|
}
|
||||||
|
|
||||||
using _database_t = typename Policies::_database_t;
|
template <typename T>
|
||||||
|
static auto _get_member(T t) -> decltype(t.no_group_by)
|
||||||
|
{
|
||||||
|
return t.no_group_by;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... T>
|
using _database_t = typename Policies::_database_t;
|
||||||
using _check = logic::all_t<is_expression_t<T>::value...>;
|
|
||||||
|
|
||||||
template<typename Check, typename T>
|
template <typename... T>
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_group_by_t, T>;
|
using _check = logic::all_t<is_expression_t<T>::value...>;
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
template <typename Check, typename T>
|
||||||
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_group_by_t, T>;
|
||||||
|
|
||||||
template<typename... Expressions>
|
using _consistency_check = consistent_t;
|
||||||
auto group_by(Expressions... expressions) const
|
|
||||||
-> _new_statement_t<_check<Expressions...>, group_by_t<void, Expressions...>>
|
|
||||||
{
|
|
||||||
static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
|
|
||||||
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in group_by()");
|
|
||||||
|
|
||||||
return _group_by_impl<void>(_check<Expressions...>{}, expressions...);
|
template <typename... Expressions>
|
||||||
}
|
auto group_by(Expressions... expressions) const
|
||||||
|
-> _new_statement_t<_check<Expressions...>, group_by_t<void, Expressions...>>
|
||||||
|
{
|
||||||
|
static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
|
||||||
|
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in group_by()");
|
||||||
|
|
||||||
template<typename... Expressions>
|
return _group_by_impl<void>(_check<Expressions...>{}, expressions...);
|
||||||
auto dynamic_group_by(Expressions... expressions) const
|
}
|
||||||
-> _new_statement_t<_check<Expressions...>, group_by_t<_database_t, Expressions...>>
|
|
||||||
{
|
|
||||||
static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement");
|
|
||||||
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in group_by()");
|
|
||||||
|
|
||||||
return _group_by_impl<_database_t>(_check<Expressions...>{}, expressions...);
|
template <typename... Expressions>
|
||||||
}
|
auto dynamic_group_by(Expressions... expressions) const
|
||||||
|
-> _new_statement_t<_check<Expressions...>, group_by_t<_database_t, Expressions...>>
|
||||||
|
{
|
||||||
|
static_assert(not std::is_same<_database_t, void>::value,
|
||||||
|
"dynamic_group_by must not be called in a static statement");
|
||||||
|
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in group_by()");
|
||||||
|
|
||||||
private:
|
return _group_by_impl<_database_t>(_check<Expressions...>{}, expressions...);
|
||||||
template<typename Database, typename... Expressions>
|
}
|
||||||
auto _group_by_impl(const std::false_type&, Expressions... expressions) const
|
|
||||||
-> bad_statement;
|
|
||||||
|
|
||||||
template<typename Database, typename... Expressions>
|
private:
|
||||||
auto _group_by_impl(const std::true_type&, Expressions... expressions) const
|
template <typename Database, typename... Expressions>
|
||||||
-> _new_statement_t<std::true_type, group_by_t<_database_t, Expressions...>>
|
auto _group_by_impl(const std::false_type&, Expressions... expressions) const -> bad_statement;
|
||||||
{
|
|
||||||
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
|
|
||||||
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), group_by_data_t<Database, Expressions...>{expressions...} };
|
template <typename Database, typename... Expressions>
|
||||||
}
|
auto _group_by_impl(const std::true_type&, Expressions... expressions) const
|
||||||
};
|
-> _new_statement_t<std::true_type, group_by_t<_database_t, Expressions...>>
|
||||||
};
|
{
|
||||||
|
static_assert(not detail::has_duplicates<Expressions...>::value,
|
||||||
|
"at least one duplicate argument detected in group_by()");
|
||||||
|
|
||||||
// Interpreters
|
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
||||||
template<typename Context, typename Database, typename... Expressions>
|
group_by_data_t<Database, Expressions...>{expressions...}};
|
||||||
struct serializer_t<Context, group_by_data_t<Database, Expressions...>>
|
}
|
||||||
{
|
};
|
||||||
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
};
|
||||||
using T = group_by_data_t<Database, Expressions...>;
|
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
// Interpreters
|
||||||
{
|
template <typename Context, typename Database, typename... Expressions>
|
||||||
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
struct serializer_t<Context, group_by_data_t<Database, Expressions...>>
|
||||||
return context;
|
{
|
||||||
context << " GROUP BY ";
|
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
||||||
interpret_tuple(t._expressions, ',', context);
|
using T = group_by_data_t<Database, Expressions...>;
|
||||||
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
|
||||||
context << ',';
|
static Context& _(const T& t, Context& context)
|
||||||
interpret_list(t._dynamic_expressions, ',', context);
|
{
|
||||||
return context;
|
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
||||||
}
|
return context;
|
||||||
};
|
context << " GROUP BY ";
|
||||||
|
interpret_tuple(t._expressions, ',', context);
|
||||||
|
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
||||||
|
context << ',';
|
||||||
|
interpret_list(t._dynamic_expressions, ',', context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,202 +36,216 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// HAVING DATA
|
// HAVING DATA
|
||||||
template<typename Database, typename... Expressions>
|
template <typename Database, typename... Expressions>
|
||||||
struct having_data_t
|
struct having_data_t
|
||||||
{
|
{
|
||||||
having_data_t(Expressions... expressions):
|
having_data_t(Expressions... expressions) : _expressions(expressions...)
|
||||||
_expressions(expressions...)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
having_data_t(const having_data_t&) = default;
|
having_data_t(const having_data_t&) = default;
|
||||||
having_data_t(having_data_t&&) = default;
|
having_data_t(having_data_t&&) = default;
|
||||||
having_data_t& operator=(const having_data_t&) = default;
|
having_data_t& operator=(const having_data_t&) = default;
|
||||||
having_data_t& operator=(having_data_t&&) = default;
|
having_data_t& operator=(having_data_t&&) = default;
|
||||||
~having_data_t() = default;
|
~having_data_t() = default;
|
||||||
|
|
||||||
std::tuple<Expressions...> _expressions;
|
std::tuple<Expressions...> _expressions;
|
||||||
interpretable_list_t<Database> _dynamic_expressions;
|
interpretable_list_t<Database> _dynamic_expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct assert_no_unknown_tables_in_having_t
|
struct assert_no_unknown_tables_in_having_t
|
||||||
{
|
{
|
||||||
using type = std::false_type;
|
using type = std::false_type;
|
||||||
|
|
||||||
template<typename T = void>
|
template <typename T = void>
|
||||||
static void _()
|
static void _()
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "at least one having-expression requires a table which is otherwise not known in the statement");
|
static_assert(wrong_t<T>::value,
|
||||||
}
|
"at least one having-expression requires a table which is otherwise not known in the statement");
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// HAVING
|
// HAVING
|
||||||
template<typename Database, typename... Expressions>
|
template <typename Database, typename... Expressions>
|
||||||
struct having_t
|
struct having_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_having>;
|
using _traits = make_traits<no_value_t, tag::is_having>;
|
||||||
using _nodes = detail::type_vector<Expressions...>;
|
using _nodes = detail::type_vector<Expressions...>;
|
||||||
|
|
||||||
using _is_dynamic = is_database<Database>;
|
using _is_dynamic = is_database<Database>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = having_data_t<Database, Expressions...>;
|
using _data_t = having_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
void add_ntc(Expression expression)
|
void add_ntc(Expression expression)
|
||||||
{
|
{
|
||||||
add<Expression, std::false_type>(expression);
|
add<Expression, std::false_type>(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression, typename TableCheckRequired = std::true_type>
|
template <typename Expression, typename TableCheckRequired = std::true_type>
|
||||||
void add(Expression expression)
|
void add(Expression expression)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having");
|
static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having");
|
||||||
static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()");
|
static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()");
|
||||||
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in having::add()");
|
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value,
|
||||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
|
"expression uses tables unknown to this statement in having::add()");
|
||||||
_serialize_check::_();
|
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
|
||||||
|
_serialize_check::_();
|
||||||
|
|
||||||
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expression>::value, _serialize_check::type::value>;
|
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expression>::value, _serialize_check::type::value>;
|
||||||
|
|
||||||
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
|
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
void _add_impl(Expression expression, const std::true_type&)
|
void _add_impl(Expression expression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return _data._dynamic_expressions.emplace_back(expression);
|
return _data._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
void _add_impl(Expression expression, const std::false_type&);
|
void _add_impl(Expression expression, const std::false_type&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Base template to be inherited by the statement
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
using _data_t = having_data_t<Database, Expressions...>;
|
using _data_t = having_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
_impl_t<Policies> having;
|
_impl_t<Policies> having;
|
||||||
_impl_t<Policies>& operator()() { return having; }
|
_impl_t<Policies>& operator()()
|
||||||
const _impl_t<Policies>& operator()() const { return having; }
|
{
|
||||||
|
return having;
|
||||||
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return having;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.having)
|
static auto _get_member(T t) -> decltype(t.having)
|
||||||
{
|
{
|
||||||
return t.having;
|
return t.having;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<having_t>::value,
|
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<having_t>::value,
|
||||||
consistent_t,
|
consistent_t,
|
||||||
assert_no_unknown_tables_in_having_t>::type;
|
assert_no_unknown_tables_in_having_t>::type;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// NO HAVING YET
|
// NO HAVING YET
|
||||||
struct no_having_t
|
struct no_having_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = no_data_t;
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Base template to be inherited by the statement
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
using _data_t = no_data_t;
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
_impl_t<Policies> no_having;
|
_impl_t<Policies> no_having;
|
||||||
_impl_t<Policies>& operator()() { return no_having; }
|
_impl_t<Policies>& operator()()
|
||||||
const _impl_t<Policies>& operator()() const { return no_having; }
|
{
|
||||||
|
return no_having;
|
||||||
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return no_having;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.no_having)
|
static auto _get_member(T t) -> decltype(t.no_having)
|
||||||
{
|
{
|
||||||
return t.no_having;
|
return t.no_having;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _database_t = typename Policies::_database_t;
|
using _database_t = typename Policies::_database_t;
|
||||||
|
|
||||||
template<typename... T>
|
template <typename... T>
|
||||||
using _check = logic::all_t<is_expression_t<T>::value...>;
|
using _check = logic::all_t<is_expression_t<T>::value...>;
|
||||||
|
|
||||||
template<typename Check, typename T>
|
template <typename Check, typename T>
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_having_t, T>;
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_having_t, T>;
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = consistent_t;
|
||||||
|
|
||||||
template<typename... Expressions>
|
template <typename... Expressions>
|
||||||
auto having(Expressions... expressions) const
|
auto having(Expressions... expressions) const
|
||||||
-> _new_statement_t<_check<Expressions...>, having_t<void, Expressions...>>
|
-> _new_statement_t<_check<Expressions...>, having_t<void, Expressions...>>
|
||||||
{
|
{
|
||||||
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in having()");
|
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in having()");
|
||||||
static_assert(sizeof...(Expressions), "at least one expression argument required in having()");
|
static_assert(sizeof...(Expressions), "at least one expression argument required in having()");
|
||||||
|
|
||||||
return _having_impl<void>(_check<Expressions...>{}, expressions...);
|
return _having_impl<void>(_check<Expressions...>{}, expressions...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Expressions>
|
template <typename... Expressions>
|
||||||
auto dynamic_having(Expressions... expressions) const
|
auto dynamic_having(Expressions... expressions) const
|
||||||
-> _new_statement_t<_check<Expressions...>, having_t<_database_t, Expressions...>>
|
-> _new_statement_t<_check<Expressions...>, having_t<_database_t, Expressions...>>
|
||||||
{
|
{
|
||||||
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in having()");
|
static_assert(_check<Expressions...>::value, "at least one argument is not an expression in having()");
|
||||||
static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement");
|
static_assert(not std::is_same<_database_t, void>::value,
|
||||||
return _having_impl<_database_t>(_check<Expressions...>{}, expressions...);
|
"dynamic_having must not be called in a static statement");
|
||||||
}
|
return _having_impl<_database_t>(_check<Expressions...>{}, expressions...);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Database, typename... Expressions>
|
template <typename Database, typename... Expressions>
|
||||||
auto _having_impl(const std::false_type&, Expressions... expressions) const
|
auto _having_impl(const std::false_type&, Expressions... expressions) const -> bad_statement;
|
||||||
-> bad_statement;
|
|
||||||
|
|
||||||
template<typename Database, typename... Expressions>
|
template <typename Database, typename... Expressions>
|
||||||
auto _having_impl(const std::true_type&, Expressions... expressions) const
|
auto _having_impl(const std::true_type&, Expressions... expressions) const
|
||||||
-> _new_statement_t<std::true_type, having_t<Database, Expressions...>>
|
-> _new_statement_t<std::true_type, having_t<Database, Expressions...>>
|
||||||
{
|
{
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), having_data_t<_database_t, Expressions...>{expressions...} };
|
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
||||||
}
|
having_data_t<_database_t, Expressions...>{expressions...}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
// Interpreters
|
||||||
};
|
template <typename Context, typename Database, typename... Expressions>
|
||||||
|
struct serializer_t<Context, having_data_t<Database, Expressions...>>
|
||||||
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
||||||
|
using T = having_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
// Interpreters
|
static Context& _(const T& t, Context& context)
|
||||||
template<typename Context, typename Database, typename... Expressions>
|
{
|
||||||
struct serializer_t<Context, having_data_t<Database, Expressions...>>
|
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
||||||
{
|
return context;
|
||||||
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
context << " HAVING ";
|
||||||
using T = having_data_t<Database, Expressions...>;
|
interpret_tuple(t._expressions, " AND ", context);
|
||||||
|
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
||||||
static Context& _(const T& t, Context& context)
|
context << " AND ";
|
||||||
{
|
interpret_list(t._dynamic_expressions, " AND ", context);
|
||||||
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
return context;
|
||||||
return context;
|
}
|
||||||
context << " HAVING ";
|
};
|
||||||
interpret_tuple(t._expressions, " AND ", context);
|
|
||||||
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
|
||||||
context << " AND ";
|
|
||||||
interpret_list(t._dynamic_expressions, " AND ", context);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,38 +29,36 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Part>
|
template <typename Part>
|
||||||
struct hidden_t:
|
struct hidden_t : public Part
|
||||||
public Part
|
{
|
||||||
{
|
hidden_t(Part part) : Part(part)
|
||||||
hidden_t(Part part):
|
{
|
||||||
Part(part)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
hidden_t(const hidden_t&) = default;
|
hidden_t(const hidden_t&) = default;
|
||||||
hidden_t(hidden_t&&) = default;
|
hidden_t(hidden_t&&) = default;
|
||||||
hidden_t& operator=(const hidden_t&) = default;
|
hidden_t& operator=(const hidden_t&) = default;
|
||||||
hidden_t& operator=(hidden_t&&) = default;
|
hidden_t& operator=(hidden_t&&) = default;
|
||||||
~hidden_t() = default;
|
~hidden_t() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Part>
|
template <typename Context, typename Part>
|
||||||
struct serializer_t<Context, hidden_t<Part>>
|
struct serializer_t<Context, hidden_t<Part>>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = hidden_t<Part>;
|
using T = hidden_t<Part>;
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
static Context& _(const T&, Context& context)
|
||||||
{
|
{
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Part>
|
template <typename Part>
|
||||||
auto hidden(Part part)
|
auto hidden(Part part) -> hidden_t<Part>
|
||||||
-> hidden_t<Part>
|
{
|
||||||
{
|
return {part};
|
||||||
return {part};
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,93 +35,90 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct in_alias_t
|
struct in_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "in_";
|
static constexpr const char _literal[] = "in_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T in;
|
T in;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Operand, typename... Args>
|
template <typename Operand, typename... Args>
|
||||||
struct in_t:
|
struct in_t : public expression_operators<in_t<Operand, Args...>, boolean>,
|
||||||
public expression_operators<in_t<Operand, Args...>, boolean>,
|
public alias_operators<in_t<Operand, Args...>>
|
||||||
public alias_operators<in_t<Operand, Args...>>
|
{
|
||||||
{
|
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
||||||
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
using _nodes = detail::type_vector<Operand, Args...>;
|
||||||
using _nodes = detail::type_vector<Operand, Args...>;
|
|
||||||
|
|
||||||
static_assert(sizeof...(Args) > 0, "in() requires at least one argument");
|
static_assert(sizeof...(Args) > 0, "in() requires at least one argument");
|
||||||
|
|
||||||
using _auto_alias_t = in_alias_t;
|
using _auto_alias_t = in_alias_t;
|
||||||
|
|
||||||
in_t(Operand operand, Args... args):
|
in_t(Operand operand, Args... args) : _operand(operand), _args(args...)
|
||||||
_operand(operand),
|
{
|
||||||
_args(args...)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
in_t(const in_t&) = default;
|
in_t(const in_t&) = default;
|
||||||
in_t(in_t&&) = default;
|
in_t(in_t&&) = default;
|
||||||
in_t& operator=(const in_t&) = default;
|
in_t& operator=(const in_t&) = default;
|
||||||
in_t& operator=(in_t&&) = default;
|
in_t& operator=(in_t&&) = default;
|
||||||
~in_t() = default;
|
~in_t() = default;
|
||||||
|
|
||||||
Operand _operand;
|
Operand _operand;
|
||||||
std::tuple<Args...> _args;
|
std::tuple<Args...> _args;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Operand, typename... Args>
|
template <typename Context, typename Operand, typename... Args>
|
||||||
struct serializer_t<Context, in_t<Operand, Args...>>
|
struct serializer_t<Context, in_t<Operand, Args...>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Args...>;
|
using _serialize_check = serialize_check_of<Context, Args...>;
|
||||||
using T = in_t<Operand, Args...>;
|
using T = in_t<Operand, Args...>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
serialize(t._operand, context);
|
serialize(t._operand, context);
|
||||||
context << " IN(";
|
context << " IN(";
|
||||||
if (sizeof...(Args) == 1)
|
if (sizeof...(Args) == 1)
|
||||||
serialize(std::get<0>(t._args), context);
|
serialize(std::get<0>(t._args), context);
|
||||||
else
|
else
|
||||||
interpret_tuple(t._args, ',', context);
|
interpret_tuple(t._args, ',', context);
|
||||||
context << ')';
|
context << ')';
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Container>
|
template <typename Container>
|
||||||
struct value_list_t;
|
struct value_list_t;
|
||||||
|
|
||||||
template<typename Context, typename Operand, typename Container>
|
template <typename Context, typename Operand, typename Container>
|
||||||
struct serializer_t<Context, in_t<Operand, value_list_t<Container>>>
|
struct serializer_t<Context, in_t<Operand, value_list_t<Container>>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, value_list_t<Container>>;
|
using _serialize_check = serialize_check_of<Context, value_list_t<Container>>;
|
||||||
using T = in_t<Operand, value_list_t<Container>>;
|
using T = in_t<Operand, value_list_t<Container>>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
const auto& value_list = std::get<0>(t._args);
|
|
||||||
if (value_list._container.empty())
|
|
||||||
{
|
|
||||||
context << " 'operand in empty list' = 'false' ";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serialize(t._operand, context);
|
|
||||||
context << " IN(";
|
|
||||||
serialize(value_list, context);
|
|
||||||
context << ')';
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
const auto& value_list = std::get<0>(t._args);
|
||||||
|
if (value_list._container.empty())
|
||||||
|
{
|
||||||
|
context << " 'operand in empty list' = 'false' ";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serialize(t._operand, context);
|
||||||
|
context << " IN(";
|
||||||
|
serialize(value_list, context);
|
||||||
|
context << ')';
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,11 +29,10 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Operand, typename... Args>
|
template <typename Operand, typename... Args>
|
||||||
struct in_t;
|
struct in_t;
|
||||||
template<typename Operand, typename... Args>
|
template <typename Operand, typename... Args>
|
||||||
struct not_in_t;
|
struct not_in_t;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,102 +39,96 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct insert_name_t {};
|
struct insert_name_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
struct insert_t: public statement_name_t<insert_name_t>
|
struct insert_t : public statement_name_t<insert_name_t>
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_return_value>;
|
using _traits = make_traits<no_value_t, tag::is_return_value>;
|
||||||
struct _alias_t {};
|
struct _alias_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Statement>
|
template <typename Statement>
|
||||||
struct _result_methods_t
|
struct _result_methods_t
|
||||||
{
|
{
|
||||||
using _statement_t = Statement;
|
using _statement_t = Statement;
|
||||||
|
|
||||||
const _statement_t& _get_statement() const
|
const _statement_t& _get_statement() const
|
||||||
{
|
{
|
||||||
return static_cast<const _statement_t&>(*this);
|
return static_cast<const _statement_t&>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
template<typename Db, typename Composite>
|
template <typename Db, typename Composite>
|
||||||
auto _run(Db& db, const Composite& composite) const
|
auto _run(Db& db, const Composite& composite) const -> decltype(db.insert(composite))
|
||||||
-> decltype(db.insert(composite))
|
{
|
||||||
{
|
return db.insert(composite);
|
||||||
return db.insert(composite);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
auto _run(Db& db) const -> decltype(db.insert(this->_get_statement()))
|
auto _run(Db& db) const -> decltype(db.insert(this->_get_statement()))
|
||||||
{
|
{
|
||||||
return db.insert(_get_statement());
|
return db.insert(_get_statement());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
template<typename Db, typename Composite>
|
template <typename Db, typename Composite>
|
||||||
auto _prepare(Db& db, const Composite& composite) const
|
auto _prepare(Db& db, const Composite& composite) const -> prepared_insert_t<Db, Composite>
|
||||||
-> prepared_insert_t<Db, Composite>
|
{
|
||||||
{
|
return {{}, db.prepare_insert(composite)};
|
||||||
return {{}, db.prepare_insert(composite)};
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
auto _prepare(Db& db) const
|
auto _prepare(Db& db) const -> prepared_insert_t<Db, _statement_t>
|
||||||
-> prepared_insert_t<Db, _statement_t>
|
{
|
||||||
{
|
return {{}, db.prepare_insert(_get_statement())};
|
||||||
return {{}, db.prepare_insert(_get_statement())};
|
}
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Context>
|
template <typename Context>
|
||||||
struct serializer_t<Context, insert_name_t>
|
struct serializer_t<Context, insert_name_t>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = insert_name_t;
|
using T = insert_name_t;
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
static Context& _(const T&, Context& context)
|
||||||
{
|
{
|
||||||
context << "INSERT ";
|
context << "INSERT ";
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Database>
|
template <typename Database>
|
||||||
using blank_insert_t = statement_t<Database,
|
using blank_insert_t = statement_t<Database, insert_t, no_into_t, no_insert_value_list_t>;
|
||||||
insert_t,
|
|
||||||
no_into_t,
|
|
||||||
no_insert_value_list_t>;
|
|
||||||
|
|
||||||
inline auto insert()
|
inline auto insert() -> blank_insert_t<void>
|
||||||
-> blank_insert_t<void>
|
{
|
||||||
{
|
return {blank_insert_t<void>()};
|
||||||
return { blank_insert_t<void>() };
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Table>
|
template <typename Table>
|
||||||
constexpr auto insert_into(Table table)
|
constexpr auto insert_into(Table table) -> decltype(blank_insert_t<void>().into(table))
|
||||||
-> decltype(blank_insert_t<void>().into(table))
|
{
|
||||||
{
|
return {blank_insert_t<void>().into(table)};
|
||||||
return { blank_insert_t<void>().into(table) };
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Database>
|
template <typename Database>
|
||||||
constexpr auto dynamic_insert(const Database&)
|
constexpr auto dynamic_insert(const Database&) -> decltype(blank_insert_t<Database>())
|
||||||
-> decltype(blank_insert_t<Database>())
|
{
|
||||||
{
|
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
||||||
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
return {blank_insert_t<Database>()};
|
||||||
return { blank_insert_t<Database>() };
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Database, typename Table>
|
template <typename Database, typename Table>
|
||||||
constexpr auto dynamic_insert_into(const Database&, Table table)
|
constexpr auto dynamic_insert_into(const Database&, Table table) -> decltype(blank_insert_t<Database>().into(table))
|
||||||
-> decltype(blank_insert_t<Database>().into(table))
|
{
|
||||||
{
|
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
||||||
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
return {blank_insert_t<Database>().into(table)};
|
||||||
return { blank_insert_t<Database>().into(table) };
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -36,91 +36,84 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Type, bool>
|
template <typename Type, bool>
|
||||||
struct type_if
|
struct type_if
|
||||||
{
|
{
|
||||||
using type = Type;
|
using type = Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Type>
|
template <typename Type>
|
||||||
struct type_if<Type, false>
|
struct type_if<Type, false>
|
||||||
{
|
{
|
||||||
struct type
|
struct type
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Column>
|
template <typename Column>
|
||||||
struct insert_value_t
|
struct insert_value_t
|
||||||
{
|
{
|
||||||
using _is_insert_value = std::true_type;
|
using _is_insert_value = std::true_type;
|
||||||
using _column_t = Column;
|
using _column_t = Column;
|
||||||
static constexpr bool _trivial_value_is_null = trivial_value_is_null_t<Column>::value;
|
static constexpr bool _trivial_value_is_null = trivial_value_is_null_t<Column>::value;
|
||||||
using _pure_value_t = typename value_type_of<Column>::_cpp_value_type;
|
using _pure_value_t = typename value_type_of<Column>::_cpp_value_type;
|
||||||
using _wrapped_value_t = wrap_operand_t<_pure_value_t>;
|
using _wrapped_value_t = wrap_operand_t<_pure_value_t>;
|
||||||
using _tvin_t = tvin_t<_wrapped_value_t>;
|
using _tvin_t = tvin_t<_wrapped_value_t>;
|
||||||
|
|
||||||
insert_value_t(rhs_wrap_t<_wrapped_value_t, _trivial_value_is_null> rhs):
|
insert_value_t(rhs_wrap_t<_wrapped_value_t, _trivial_value_is_null> rhs)
|
||||||
_is_null(rhs._is_null()),
|
: _is_null(rhs._is_null()), _is_default(rhs._is_default()), _value(rhs._expr._t)
|
||||||
_is_default(rhs._is_default()),
|
{
|
||||||
_value(rhs._expr._t)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
insert_value_t(rhs_wrap_t<_tvin_t, _trivial_value_is_null> rhs):
|
insert_value_t(rhs_wrap_t<_tvin_t, _trivial_value_is_null> rhs)
|
||||||
_is_null(rhs._is_null()),
|
: _is_null(rhs._is_null()), _is_default(rhs._is_default()), _value(rhs._expr._value)
|
||||||
_is_default(rhs._is_default()),
|
{
|
||||||
_value(rhs._expr._value)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
insert_value_t(const rhs_wrap_t<null_t, _trivial_value_is_null>&):
|
insert_value_t(const rhs_wrap_t<null_t, _trivial_value_is_null>&) : _is_null(true), _is_default(false), _value{}
|
||||||
_is_null(true),
|
{
|
||||||
_is_default(false),
|
}
|
||||||
_value{}
|
|
||||||
{}
|
|
||||||
|
|
||||||
insert_value_t(const rhs_wrap_t<default_value_t, _trivial_value_is_null>&):
|
insert_value_t(const rhs_wrap_t<default_value_t, _trivial_value_is_null>&)
|
||||||
_is_null(false),
|
: _is_null(false), _is_default(true), _value{}
|
||||||
_is_default(true),
|
{
|
||||||
_value{}
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
insert_value_t(const insert_value_t&) = default;
|
insert_value_t(const insert_value_t&) = default;
|
||||||
insert_value_t(insert_value_t&&) = default;
|
insert_value_t(insert_value_t&&) = default;
|
||||||
insert_value_t& operator=(const insert_value_t&) = default;
|
insert_value_t& operator=(const insert_value_t&) = default;
|
||||||
insert_value_t& operator=(insert_value_t&&) = default;
|
insert_value_t& operator=(insert_value_t&&) = default;
|
||||||
~insert_value_t() = default;
|
~insert_value_t() = default;
|
||||||
|
|
||||||
bool _is_null;
|
bool _is_null;
|
||||||
bool _is_default;
|
bool _is_default;
|
||||||
_wrapped_value_t _value;
|
_wrapped_value_t _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename ValueType>
|
template <typename Context, typename ValueType>
|
||||||
struct serializer_t<Context, insert_value_t<ValueType>>
|
struct serializer_t<Context, insert_value_t<ValueType>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, ValueType>;
|
using _serialize_check = serialize_check_of<Context, ValueType>;
|
||||||
using T = insert_value_t<ValueType>;
|
using T = insert_value_t<ValueType>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
if ((trivial_value_is_null_t<typename T::_column_t>::value and t._value._is_trivial())
|
|
||||||
or t._is_null)
|
|
||||||
{
|
|
||||||
context << "NULL";
|
|
||||||
}
|
|
||||||
else if (t._is_default)
|
|
||||||
context << "DEFAULT";
|
|
||||||
else
|
|
||||||
serialize_operand(t._value, context);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
if ((trivial_value_is_null_t<typename T::_column_t>::value and t._value._is_trivial()) or t._is_null)
|
||||||
|
{
|
||||||
|
context << "NULL";
|
||||||
|
}
|
||||||
|
else if (t._is_default)
|
||||||
|
context << "DEFAULT";
|
||||||
|
else
|
||||||
|
serialize_operand(t._value, context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,477 +39,509 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename... Columns>
|
template <typename... Columns>
|
||||||
struct have_all_required_columns
|
struct have_all_required_columns
|
||||||
{
|
{
|
||||||
static constexpr bool value = false;
|
static constexpr bool value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename First, typename... Columns>
|
template <typename First, typename... Columns>
|
||||||
struct have_all_required_columns<First, Columns...>
|
struct have_all_required_columns<First, Columns...>
|
||||||
{
|
{
|
||||||
using _table = typename First::_table;
|
using _table = typename First::_table;
|
||||||
using required_columns = typename _table::_required_insert_columns;
|
using required_columns = typename _table::_required_insert_columns;
|
||||||
using set_columns = detail::make_type_set_t<First, Columns...>;
|
using set_columns = detail::make_type_set_t<First, Columns...>;
|
||||||
static constexpr bool value = detail::is_subset_of<required_columns, set_columns>::value;
|
static constexpr bool value = detail::is_subset_of<required_columns, set_columns>::value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct insert_default_values_data_t
|
struct insert_default_values_data_t
|
||||||
{};
|
{
|
||||||
|
};
|
||||||
// COLUMN AND VALUE LIST
|
|
||||||
struct insert_default_values_t
|
// COLUMN AND VALUE LIST
|
||||||
{
|
struct insert_default_values_t
|
||||||
using _traits = make_traits<no_value_t>;
|
{
|
||||||
using _nodes = detail::type_vector<>;
|
using _traits = make_traits<no_value_t>;
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
// Data
|
|
||||||
using _data_t = insert_default_values_data_t;
|
// Data
|
||||||
|
using _data_t = insert_default_values_data_t;
|
||||||
// Member implementation with data and methods
|
|
||||||
template<typename Policies>
|
// Member implementation with data and methods
|
||||||
struct _impl_t
|
template <typename Policies>
|
||||||
{
|
struct _impl_t
|
||||||
_data_t _data;
|
{
|
||||||
};
|
_data_t _data;
|
||||||
|
};
|
||||||
// Base template to be inherited by the statement
|
|
||||||
template<typename Policies>
|
// Base template to be inherited by the statement
|
||||||
struct _base_t
|
template <typename Policies>
|
||||||
{
|
struct _base_t
|
||||||
using _data_t = insert_default_values_data_t;
|
{
|
||||||
|
using _data_t = insert_default_values_data_t;
|
||||||
_impl_t<Policies> default_values;
|
|
||||||
_impl_t<Policies>& operator()() { return default_values; }
|
_impl_t<Policies> default_values;
|
||||||
const _impl_t<Policies>& operator()() const { return default_values; }
|
_impl_t<Policies>& operator()()
|
||||||
|
{
|
||||||
template<typename T>
|
return default_values;
|
||||||
static auto _get_member(T t) -> decltype(t.default_values)
|
}
|
||||||
{
|
const _impl_t<Policies>& operator()() const
|
||||||
return t.default_values;
|
{
|
||||||
}
|
return default_values;
|
||||||
|
}
|
||||||
using _consistency_check = consistent_t;
|
|
||||||
};
|
template <typename T>
|
||||||
};
|
static auto _get_member(T t) -> decltype(t.default_values)
|
||||||
|
{
|
||||||
template<typename Database, typename... Assignments>
|
return t.default_values;
|
||||||
struct insert_list_data_t
|
}
|
||||||
{
|
|
||||||
insert_list_data_t(Assignments... assignments):
|
using _consistency_check = consistent_t;
|
||||||
_assignments(assignments...),
|
};
|
||||||
_columns({assignments._lhs}...),
|
};
|
||||||
_values(assignments._rhs...)
|
|
||||||
{}
|
template <typename Database, typename... Assignments>
|
||||||
|
struct insert_list_data_t
|
||||||
insert_list_data_t(const insert_list_data_t&) = default;
|
{
|
||||||
insert_list_data_t(insert_list_data_t&&) = default;
|
insert_list_data_t(Assignments... assignments)
|
||||||
insert_list_data_t& operator=(const insert_list_data_t&) = default;
|
: _assignments(assignments...), _columns({assignments._lhs}...), _values(assignments._rhs...)
|
||||||
insert_list_data_t& operator=(insert_list_data_t&&) = default;
|
{
|
||||||
~insert_list_data_t() = default;
|
}
|
||||||
|
|
||||||
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
|
insert_list_data_t(const insert_list_data_t&) = default;
|
||||||
std::tuple<simple_column_t<lhs_t<Assignments>>...> _columns;
|
insert_list_data_t(insert_list_data_t&&) = default;
|
||||||
std::tuple<rhs_t<Assignments>...> _values;
|
insert_list_data_t& operator=(const insert_list_data_t&) = default;
|
||||||
interpretable_list_t<Database> _dynamic_columns;
|
insert_list_data_t& operator=(insert_list_data_t&&) = default;
|
||||||
interpretable_list_t<Database> _dynamic_values;
|
~insert_list_data_t() = default;
|
||||||
};
|
|
||||||
|
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments
|
||||||
struct assert_no_unknown_tables_in_insert_assignments_t
|
// (connector-container requires assignments)
|
||||||
{
|
std::tuple<simple_column_t<lhs_t<Assignments>>...> _columns;
|
||||||
using type = std::false_type;
|
std::tuple<rhs_t<Assignments>...> _values;
|
||||||
|
interpretable_list_t<Database> _dynamic_columns;
|
||||||
template<typename T = void>
|
interpretable_list_t<Database> _dynamic_values;
|
||||||
static void _()
|
};
|
||||||
{
|
|
||||||
static_assert(wrong_t<T>::value, "at least one insert assignment requires a table which is otherwise not known in the statement");
|
struct assert_no_unknown_tables_in_insert_assignments_t
|
||||||
}
|
{
|
||||||
};
|
using type = std::false_type;
|
||||||
|
|
||||||
template<typename Database, typename... Assignments>
|
template <typename T = void>
|
||||||
struct insert_list_t
|
static void _()
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_insert_list>;
|
static_assert(wrong_t<T>::value,
|
||||||
using _nodes = detail::type_vector<lhs_t<Assignments>..., rhs_t<Assignments>...>;
|
"at least one insert assignment requires a table which is otherwise not known in the statement");
|
||||||
|
}
|
||||||
using _is_dynamic = is_database<Database>;
|
};
|
||||||
|
|
||||||
template<template<typename...> class Target>
|
template <typename Database, typename... Assignments>
|
||||||
using copy_assignments_t = Target<Assignments...>; // FIXME: Nice idea to copy variadic template arguments?
|
struct insert_list_t
|
||||||
template<template<typename...> class Target, template<typename> class Wrap>
|
{
|
||||||
using copy_wrapped_assignments_t = Target<Wrap<Assignments>...>;
|
using _traits = make_traits<no_value_t, tag::is_insert_list>;
|
||||||
|
using _nodes = detail::type_vector<lhs_t<Assignments>..., rhs_t<Assignments>...>;
|
||||||
// Data
|
|
||||||
using _data_t = insert_list_data_t<Database, Assignments...>;
|
using _is_dynamic = is_database<Database>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
template <template <typename...> class Target>
|
||||||
template <typename Policies>
|
using copy_assignments_t = Target<Assignments...>; // FIXME: Nice idea to copy variadic template arguments?
|
||||||
struct _impl_t
|
template <template <typename...> class Target, template <typename> class Wrap>
|
||||||
{
|
using copy_wrapped_assignments_t = Target<Wrap<Assignments>...>;
|
||||||
template<typename Assignment>
|
|
||||||
void add_ntc(Assignment assignment)
|
// Data
|
||||||
{
|
using _data_t = insert_list_data_t<Database, Assignments...>;
|
||||||
add<Assignment, std::false_type>(assignment);
|
|
||||||
}
|
// Member implementation with data and methods
|
||||||
|
template <typename Policies>
|
||||||
template<typename Assignment, typename TableCheckRequired = std::true_type>
|
struct _impl_t
|
||||||
void add(Assignment assignment)
|
{
|
||||||
{
|
template <typename Assignment>
|
||||||
static_assert(_is_dynamic::value, "add must not be called for static from()");
|
void add_ntc(Assignment assignment)
|
||||||
static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments");
|
{
|
||||||
using _assigned_columns = detail::make_type_set_t<lhs_t<Assignments>...>;
|
add<Assignment, std::false_type>(assignment);
|
||||||
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value, "Must not assign value to column twice");
|
}
|
||||||
static_assert(not must_not_insert_t<lhs_t<Assignment>>::value, "add() argument must not be used in insert");
|
|
||||||
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table");
|
template <typename Assignment, typename TableCheckRequired = std::true_type>
|
||||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Assignment>;
|
void add(Assignment assignment)
|
||||||
_serialize_check::_();
|
{
|
||||||
|
static_assert(_is_dynamic::value, "add must not be called for static from()");
|
||||||
using ok = logic::all_t<
|
static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments");
|
||||||
_is_dynamic::value,
|
using _assigned_columns = detail::make_type_set_t<lhs_t<Assignments>...>;
|
||||||
is_assignment_t<Assignment>::value,
|
static_assert(not detail::is_element_of<lhs_t<Assignment>, _assigned_columns>::value,
|
||||||
_serialize_check::type::value>;
|
"Must not assign value to column twice");
|
||||||
|
static_assert(not must_not_insert_t<lhs_t<Assignment>>::value, "add() argument must not be used in insert");
|
||||||
_add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
|
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value,
|
||||||
}
|
"add() contains a column from a foreign table");
|
||||||
|
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Assignment>;
|
||||||
private:
|
_serialize_check::_();
|
||||||
template<typename Assignment>
|
|
||||||
void _add_impl(Assignment assignment, const std::true_type&)
|
using ok = logic::all_t<_is_dynamic::value, is_assignment_t<Assignment>::value, _serialize_check::type::value>;
|
||||||
{
|
|
||||||
_data._dynamic_columns.emplace_back(simple_column_t<lhs_t<Assignment>>{assignment._lhs});
|
_add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
|
||||||
_data._dynamic_values.emplace_back(assignment._rhs);
|
}
|
||||||
}
|
|
||||||
|
private:
|
||||||
template<typename Assignment>
|
template <typename Assignment>
|
||||||
void _add_impl(Assignment assignment, const std::false_type&);
|
void _add_impl(Assignment assignment, const std::true_type&)
|
||||||
public:
|
{
|
||||||
_data_t _data;
|
_data._dynamic_columns.emplace_back(simple_column_t<lhs_t<Assignment>>{assignment._lhs});
|
||||||
};
|
_data._dynamic_values.emplace_back(assignment._rhs);
|
||||||
|
}
|
||||||
// Base template to be inherited by the statement
|
|
||||||
template<typename Policies>
|
template <typename Assignment>
|
||||||
struct _base_t
|
void _add_impl(Assignment assignment, const std::false_type&);
|
||||||
{
|
|
||||||
using _data_t = insert_list_data_t<Database, Assignments...>;
|
public:
|
||||||
|
_data_t _data;
|
||||||
_impl_t<Policies> insert_list;
|
};
|
||||||
_impl_t<Policies>& operator()() { return insert_list; }
|
|
||||||
const _impl_t<Policies>& operator()() const { return insert_list; }
|
// Base template to be inherited by the statement
|
||||||
|
template <typename Policies>
|
||||||
template<typename T>
|
struct _base_t
|
||||||
static auto _get_member(T t) -> decltype(t.insert_list)
|
{
|
||||||
{
|
using _data_t = insert_list_data_t<Database, Assignments...>;
|
||||||
return t.insert_list;
|
|
||||||
}
|
_impl_t<Policies> insert_list;
|
||||||
|
_impl_t<Policies>& operator()()
|
||||||
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<insert_list_t>::value,
|
{
|
||||||
consistent_t,
|
return insert_list;
|
||||||
assert_no_unknown_tables_in_insert_assignments_t>::type;
|
}
|
||||||
};
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
};
|
return insert_list;
|
||||||
|
}
|
||||||
template<typename... Columns>
|
|
||||||
struct column_list_data_t
|
template <typename T>
|
||||||
{
|
static auto _get_member(T t) -> decltype(t.insert_list)
|
||||||
column_list_data_t(Columns... cols):
|
{
|
||||||
_columns(simple_column_t<Columns>{cols}...)
|
return t.insert_list;
|
||||||
{}
|
}
|
||||||
|
|
||||||
column_list_data_t(const column_list_data_t&) = default;
|
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<insert_list_t>::value,
|
||||||
column_list_data_t(column_list_data_t&&) = default;
|
consistent_t,
|
||||||
column_list_data_t& operator=(const column_list_data_t&) = default;
|
assert_no_unknown_tables_in_insert_assignments_t>::type;
|
||||||
column_list_data_t& operator=(column_list_data_t&&) = default;
|
};
|
||||||
~column_list_data_t() = default;
|
};
|
||||||
|
|
||||||
using _value_tuple_t = std::tuple<insert_value_t<Columns>...>;
|
template <typename... Columns>
|
||||||
std::tuple<simple_column_t<Columns>...> _columns;
|
struct column_list_data_t
|
||||||
std::vector<_value_tuple_t> _insert_values;
|
{
|
||||||
};
|
column_list_data_t(Columns... cols) : _columns(simple_column_t<Columns>{cols}...)
|
||||||
|
{
|
||||||
struct assert_no_unknown_tables_in_column_list_t
|
}
|
||||||
{
|
|
||||||
using type = std::false_type;
|
column_list_data_t(const column_list_data_t&) = default;
|
||||||
|
column_list_data_t(column_list_data_t&&) = default;
|
||||||
template<typename T = void>
|
column_list_data_t& operator=(const column_list_data_t&) = default;
|
||||||
static void _()
|
column_list_data_t& operator=(column_list_data_t&&) = default;
|
||||||
{
|
~column_list_data_t() = default;
|
||||||
static_assert(wrong_t<T>::value, "at least one column requires a table which is otherwise not known in the statement");
|
|
||||||
}
|
using _value_tuple_t = std::tuple<insert_value_t<Columns>...>;
|
||||||
};
|
std::tuple<simple_column_t<Columns>...> _columns;
|
||||||
|
std::vector<_value_tuple_t> _insert_values;
|
||||||
template<typename... Columns>
|
};
|
||||||
struct column_list_t
|
|
||||||
{
|
struct assert_no_unknown_tables_in_column_list_t
|
||||||
using _traits = make_traits<no_value_t, tag::is_column_list>;
|
{
|
||||||
using _nodes = detail::type_vector<Columns...>;
|
using type = std::false_type;
|
||||||
|
|
||||||
using _value_tuple_t = typename column_list_data_t<Columns...>::_value_tuple_t;
|
template <typename T = void>
|
||||||
|
static void _()
|
||||||
|
{
|
||||||
// Data
|
static_assert(wrong_t<T>::value,
|
||||||
using _data_t = column_list_data_t<Columns...>;
|
"at least one column requires a table which is otherwise not known in the statement");
|
||||||
|
}
|
||||||
// Member implementation with data and methods
|
};
|
||||||
template <typename Policies>
|
|
||||||
struct _impl_t
|
template <typename... Columns>
|
||||||
{
|
struct column_list_t
|
||||||
template<typename... Assignments>
|
{
|
||||||
void add(Assignments... assignments)
|
using _traits = make_traits<no_value_t, tag::is_column_list>;
|
||||||
{
|
using _nodes = detail::type_vector<Columns...>;
|
||||||
static_assert(logic::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments");
|
|
||||||
using _arg_value_tuple = std::tuple<insert_value_t<lhs_t<Assignments>>...>;
|
using _value_tuple_t = typename column_list_data_t<Columns...>::_value_tuple_t;
|
||||||
using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>;
|
|
||||||
static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments");
|
// Data
|
||||||
|
using _data_t = column_list_data_t<Columns...>;
|
||||||
using ok = logic::all_t<
|
|
||||||
logic::all_t<is_assignment_t<Assignments>::value...>::value,
|
// Member implementation with data and methods
|
||||||
_args_correct::value>;
|
template <typename Policies>
|
||||||
|
struct _impl_t
|
||||||
_add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
|
{
|
||||||
}
|
template <typename... Assignments>
|
||||||
|
void add(Assignments... assignments)
|
||||||
private:
|
{
|
||||||
template<typename... Assignments>
|
static_assert(logic::all_t<is_assignment_t<Assignments>::value...>::value,
|
||||||
void _add_impl(const std::true_type&, Assignments... assignments)
|
"add_values() arguments have to be assignments");
|
||||||
{
|
using _arg_value_tuple = std::tuple<insert_value_t<lhs_t<Assignments>>...>;
|
||||||
return _data._insert_values.emplace_back(insert_value_t<lhs_t<Assignments>>{assignments._rhs}...);
|
using _args_correct = std::is_same<_arg_value_tuple, _value_tuple_t>;
|
||||||
}
|
static_assert(_args_correct::value, "add_values() arguments do not match columns() arguments");
|
||||||
|
|
||||||
template<typename... Assignments>
|
using ok = logic::all_t<logic::all_t<is_assignment_t<Assignments>::value...>::value, _args_correct::value>;
|
||||||
void _add_impl(const std::false_type&, Assignments... assignments);
|
|
||||||
public:
|
_add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
|
||||||
_data_t _data;
|
}
|
||||||
};
|
|
||||||
|
private:
|
||||||
// Base template to be inherited by the statement
|
template <typename... Assignments>
|
||||||
template<typename Policies>
|
void _add_impl(const std::true_type&, Assignments... assignments)
|
||||||
struct _base_t
|
{
|
||||||
{
|
return _data._insert_values.emplace_back(insert_value_t<lhs_t<Assignments>>{assignments._rhs}...);
|
||||||
using _data_t = column_list_data_t<Columns...>;
|
}
|
||||||
|
|
||||||
_impl_t<Policies> values;
|
template <typename... Assignments>
|
||||||
_impl_t<Policies>& operator()() { return values; }
|
void _add_impl(const std::false_type&, Assignments... assignments);
|
||||||
const _impl_t<Policies>& operator()() const { return values; }
|
|
||||||
|
public:
|
||||||
template<typename T>
|
_data_t _data;
|
||||||
static auto _get_member(T t) -> decltype(t.values)
|
};
|
||||||
{
|
|
||||||
return t.values;
|
// Base template to be inherited by the statement
|
||||||
}
|
template <typename Policies>
|
||||||
|
struct _base_t
|
||||||
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<column_list_t>::value,
|
{
|
||||||
consistent_t,
|
using _data_t = column_list_data_t<Columns...>;
|
||||||
assert_no_unknown_tables_in_column_list_t>::type;
|
|
||||||
};
|
_impl_t<Policies> values;
|
||||||
};
|
_impl_t<Policies>& operator()()
|
||||||
|
{
|
||||||
struct assert_insert_values_t
|
return values;
|
||||||
{
|
}
|
||||||
using type = std::false_type;
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
template<typename T = void>
|
return values;
|
||||||
static void _()
|
}
|
||||||
{
|
|
||||||
static_assert(wrong_t<T>::value, "insert values required, e.g. set(...) or default_values()");
|
template <typename T>
|
||||||
}
|
static auto _get_member(T t) -> decltype(t.values)
|
||||||
};
|
{
|
||||||
|
return t.values;
|
||||||
// NO INSERT COLUMNS/VALUES YET
|
}
|
||||||
struct no_insert_value_list_t
|
|
||||||
{
|
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<column_list_t>::value,
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
consistent_t,
|
||||||
using _nodes = detail::type_vector<>;
|
assert_no_unknown_tables_in_column_list_t>::type;
|
||||||
|
};
|
||||||
// Data
|
};
|
||||||
using _data_t = no_data_t;
|
|
||||||
|
struct assert_insert_values_t
|
||||||
// Member implementation with data and methods
|
{
|
||||||
template<typename Policies>
|
using type = std::false_type;
|
||||||
struct _impl_t
|
|
||||||
{
|
template <typename T = void>
|
||||||
_data_t _data;
|
static void _()
|
||||||
};
|
{
|
||||||
|
static_assert(wrong_t<T>::value, "insert values required, e.g. set(...) or default_values()");
|
||||||
// Base template to be inherited by the statement
|
}
|
||||||
template<typename Policies>
|
};
|
||||||
struct _base_t
|
|
||||||
{
|
// NO INSERT COLUMNS/VALUES YET
|
||||||
using _data_t = no_data_t;
|
struct no_insert_value_list_t
|
||||||
|
{
|
||||||
_impl_t<Policies> no_insert_values;
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
_impl_t<Policies>& operator()() { return no_insert_values; }
|
using _nodes = detail::type_vector<>;
|
||||||
const _impl_t<Policies>& operator()() const { return no_insert_values; }
|
|
||||||
|
// Data
|
||||||
template<typename T>
|
using _data_t = no_data_t;
|
||||||
static auto _get_member(T t) -> decltype(t.no_insert_values)
|
|
||||||
{
|
// Member implementation with data and methods
|
||||||
return t.no_insert_values;
|
template <typename Policies>
|
||||||
}
|
struct _impl_t
|
||||||
|
{
|
||||||
using _database_t = typename Policies::_database_t;
|
_data_t _data;
|
||||||
|
};
|
||||||
template<typename... T>
|
|
||||||
using _column_check = logic::all_t<is_column_t<T>::value...>;
|
// Base template to be inherited by the statement
|
||||||
|
template <typename Policies>
|
||||||
template<typename... T>
|
struct _base_t
|
||||||
using _assignment_check = logic::all_t<is_assignment_t<T>::value...>;
|
{
|
||||||
|
using _data_t = no_data_t;
|
||||||
template<typename Check, typename T>
|
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_insert_value_list_t, T>;
|
_impl_t<Policies> no_insert_values;
|
||||||
|
_impl_t<Policies>& operator()()
|
||||||
using _consistency_check = assert_insert_values_t;
|
{
|
||||||
|
return no_insert_values;
|
||||||
auto default_values() const
|
}
|
||||||
-> _new_statement_t<std::true_type, insert_default_values_t>
|
const _impl_t<Policies>& operator()() const
|
||||||
{
|
{
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), insert_default_values_data_t{} };
|
return no_insert_values;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Columns>
|
template <typename T>
|
||||||
auto columns(Columns... cols) const
|
static auto _get_member(T t) -> decltype(t.no_insert_values)
|
||||||
-> _new_statement_t<_column_check<Columns...>, column_list_t<Columns...>>
|
{
|
||||||
{
|
return t.no_insert_values;
|
||||||
static_assert(logic::all_t<is_column_t<Columns>::value...>::value, "at least one argument is not a column in columns()");
|
}
|
||||||
static_assert(sizeof...(Columns), "at least one column required in columns()");
|
|
||||||
|
using _database_t = typename Policies::_database_t;
|
||||||
return _columns_impl(_column_check<Columns...>{}, cols...);
|
|
||||||
}
|
template <typename... T>
|
||||||
|
using _column_check = logic::all_t<is_column_t<T>::value...>;
|
||||||
template<typename... Assignments>
|
|
||||||
auto set(Assignments... assignments) const
|
template <typename... T>
|
||||||
-> _new_statement_t<_assignment_check<Assignments...>, insert_list_t<void, Assignments...>>
|
using _assignment_check = logic::all_t<is_assignment_t<T>::value...>;
|
||||||
{
|
|
||||||
static_assert(_assignment_check<Assignments...>::value, "at least one argument is not an assignment in set()");
|
template <typename Check, typename T>
|
||||||
static_assert(sizeof...(Assignments), "at least one assignment expression required in set()");
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_insert_value_list_t, T>;
|
||||||
|
|
||||||
return _set_impl<void>(_assignment_check<Assignments...>{}, assignments...);
|
using _consistency_check = assert_insert_values_t;
|
||||||
}
|
|
||||||
|
auto default_values() const -> _new_statement_t<std::true_type, insert_default_values_t>
|
||||||
template<typename... Assignments>
|
{
|
||||||
auto dynamic_set(Assignments... assignments) const
|
return {static_cast<const derived_statement_t<Policies>&>(*this), insert_default_values_data_t{}};
|
||||||
-> _new_statement_t<_assignment_check<Assignments...>, insert_list_t<_database_t, Assignments...>>
|
}
|
||||||
{
|
|
||||||
static_assert(_assignment_check<Assignments...>::value, "at least one argument is not an assignment in set()");
|
template <typename... Columns>
|
||||||
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement");
|
auto columns(Columns... cols) const -> _new_statement_t<_column_check<Columns...>, column_list_t<Columns...>>
|
||||||
|
{
|
||||||
return _set_impl<_database_t>(_assignment_check<Assignments...>{}, assignments...);
|
static_assert(logic::all_t<is_column_t<Columns>::value...>::value,
|
||||||
}
|
"at least one argument is not a column in columns()");
|
||||||
private:
|
static_assert(sizeof...(Columns), "at least one column required in columns()");
|
||||||
template<typename... Columns>
|
|
||||||
auto _columns_impl(const std::false_type&, Columns... cols) const
|
return _columns_impl(_column_check<Columns...>{}, cols...);
|
||||||
-> bad_statement;
|
}
|
||||||
|
|
||||||
template<typename... Columns>
|
template <typename... Assignments>
|
||||||
auto _columns_impl(const std::true_type&, Columns... cols) const
|
auto set(Assignments... assignments) const
|
||||||
-> _new_statement_t<std::true_type, column_list_t<Columns...>>
|
-> _new_statement_t<_assignment_check<Assignments...>, insert_list_t<void, Assignments...>>
|
||||||
{
|
{
|
||||||
static_assert(not detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected in columns()");
|
static_assert(_assignment_check<Assignments...>::value, "at least one argument is not an assignment in set()");
|
||||||
static_assert(logic::none_t<must_not_insert_t<Columns>::value...>::value, "at least one column argument has a must_not_insert tag in its definition");
|
static_assert(sizeof...(Assignments), "at least one assignment expression required in set()");
|
||||||
using _column_required_tables = detail::make_joined_set_t<required_tables_of<Columns>...>;
|
|
||||||
static_assert(_column_required_tables::size::value == 1, "columns() contains columns from several tables");
|
return _set_impl<void>(_assignment_check<Assignments...>{}, assignments...);
|
||||||
|
}
|
||||||
static_assert(detail::have_all_required_columns<Columns...>::value, "At least one required column is missing in columns()");
|
|
||||||
|
template <typename... Assignments>
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), column_list_data_t<Columns...>{cols...} };
|
auto dynamic_set(Assignments... assignments) const
|
||||||
}
|
-> _new_statement_t<_assignment_check<Assignments...>, insert_list_t<_database_t, Assignments...>>
|
||||||
|
{
|
||||||
template<typename Database, typename... Assignments>
|
static_assert(_assignment_check<Assignments...>::value, "at least one argument is not an assignment in set()");
|
||||||
auto _set_impl(const std::false_type&, Assignments... assignments) const
|
static_assert(not std::is_same<_database_t, void>::value,
|
||||||
-> bad_statement;
|
"dynamic_set must not be called in a static statement");
|
||||||
|
|
||||||
template<typename Database, typename... Assignments>
|
return _set_impl<_database_t>(_assignment_check<Assignments...>{}, assignments...);
|
||||||
auto _set_impl(const std::true_type&, Assignments... assignments) const
|
}
|
||||||
-> _new_statement_t<std::true_type, insert_list_t<Database, Assignments...>>
|
|
||||||
{
|
private:
|
||||||
static_assert(not detail::has_duplicates<lhs_t<Assignments>...>::value, "at least one duplicate column detected in set()");
|
template <typename... Columns>
|
||||||
static_assert(logic::none_t<must_not_insert_t<lhs_t<Assignments>>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
|
auto _columns_impl(const std::false_type&, Columns... cols) const -> bad_statement;
|
||||||
|
|
||||||
using _column_required_tables = detail::make_joined_set_t<required_tables_of<lhs_t<Assignments>>...>;
|
template <typename... Columns>
|
||||||
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from several tables");
|
auto _columns_impl(const std::true_type&, Columns... cols) const
|
||||||
|
-> _new_statement_t<std::true_type, column_list_t<Columns...>>
|
||||||
static_assert(not std::is_same<_database_t, void>::value or detail::have_all_required_columns<lhs_t<Assignments>...>::value, "At least one required column is missing in set()");
|
{
|
||||||
|
static_assert(not detail::has_duplicates<Columns...>::value,
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), insert_list_data_t<Database, Assignments...>{assignments...} };
|
"at least one duplicate argument detected in columns()");
|
||||||
}
|
static_assert(logic::none_t<must_not_insert_t<Columns>::value...>::value,
|
||||||
};
|
"at least one column argument has a must_not_insert tag in its definition");
|
||||||
};
|
using _column_required_tables = detail::make_joined_set_t<required_tables_of<Columns>...>;
|
||||||
|
static_assert(_column_required_tables::size::value == 1, "columns() contains columns from several tables");
|
||||||
// Interpreters
|
|
||||||
template<typename Context>
|
static_assert(detail::have_all_required_columns<Columns...>::value,
|
||||||
struct serializer_t<Context, insert_default_values_data_t>
|
"At least one required column is missing in columns()");
|
||||||
{
|
|
||||||
using _serialize_check = consistent_t;
|
return {static_cast<const derived_statement_t<Policies>&>(*this), column_list_data_t<Columns...>{cols...}};
|
||||||
using T = insert_default_values_data_t;
|
}
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
template <typename Database, typename... Assignments>
|
||||||
{
|
auto _set_impl(const std::false_type&, Assignments... assignments) const -> bad_statement;
|
||||||
context << " DEFAULT VALUES";
|
|
||||||
return context;
|
template <typename Database, typename... Assignments>
|
||||||
}
|
auto _set_impl(const std::true_type&, Assignments... assignments) const
|
||||||
};
|
-> _new_statement_t<std::true_type, insert_list_t<Database, Assignments...>>
|
||||||
|
{
|
||||||
template<typename Context, typename... Columns>
|
static_assert(not detail::has_duplicates<lhs_t<Assignments>...>::value,
|
||||||
struct serializer_t<Context, column_list_data_t<Columns...>>
|
"at least one duplicate column detected in set()");
|
||||||
{
|
static_assert(logic::none_t<must_not_insert_t<lhs_t<Assignments>>::value...>::value,
|
||||||
using _serialize_check = serialize_check_of<Context, Columns...>;
|
"at least one assignment is prohibited by its column definition in set()");
|
||||||
using T = column_list_data_t<Columns...>;
|
|
||||||
|
using _column_required_tables = detail::make_joined_set_t<required_tables_of<lhs_t<Assignments>>...>;
|
||||||
static Context& _(const T& t, Context& context)
|
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true,
|
||||||
{
|
"set() contains assignments for columns from several tables");
|
||||||
context << " (";
|
|
||||||
interpret_tuple(t._columns, ",", context);
|
static_assert(not std::is_same<_database_t, void>::value or
|
||||||
context << ")";
|
detail::have_all_required_columns<lhs_t<Assignments>...>::value,
|
||||||
context << " VALUES ";
|
"At least one required column is missing in set()");
|
||||||
bool first = true;
|
|
||||||
for (const auto& row : t._insert_values)
|
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
||||||
{
|
insert_list_data_t<Database, Assignments...>{assignments...}};
|
||||||
if (not first)
|
}
|
||||||
context << ',';
|
};
|
||||||
else
|
};
|
||||||
first = false;
|
|
||||||
context << '(';
|
// Interpreters
|
||||||
interpret_tuple(row, ",", context);
|
template <typename Context>
|
||||||
context << ')';
|
struct serializer_t<Context, insert_default_values_data_t>
|
||||||
}
|
{
|
||||||
|
using _serialize_check = consistent_t;
|
||||||
return context;
|
using T = insert_default_values_data_t;
|
||||||
}
|
|
||||||
};
|
static Context& _(const T&, Context& context)
|
||||||
|
{
|
||||||
template<typename Context, typename Database, typename... Assignments>
|
context << " DEFAULT VALUES";
|
||||||
struct serializer_t<Context, insert_list_data_t<Database, Assignments...>>
|
return context;
|
||||||
{
|
}
|
||||||
using _serialize_check = serialize_check_of<Context, Assignments...>;
|
};
|
||||||
using T = insert_list_data_t<Database, Assignments...>;
|
|
||||||
|
template <typename Context, typename... Columns>
|
||||||
static Context& _(const T& t, Context& context)
|
struct serializer_t<Context, column_list_data_t<Columns...>>
|
||||||
{
|
{
|
||||||
if (sizeof...(Assignments) + t._dynamic_columns.size() == 0)
|
using _serialize_check = serialize_check_of<Context, Columns...>;
|
||||||
{
|
using T = column_list_data_t<Columns...>;
|
||||||
serialize(insert_default_values_data_t(), context);
|
|
||||||
}
|
static Context& _(const T& t, Context& context)
|
||||||
else
|
{
|
||||||
{
|
context << " (";
|
||||||
context << " (";
|
interpret_tuple(t._columns, ",", context);
|
||||||
interpret_tuple(t._columns, ",", context);
|
context << ")";
|
||||||
if (sizeof...(Assignments) and not t._dynamic_columns.empty())
|
context << " VALUES ";
|
||||||
context << ',';
|
bool first = true;
|
||||||
interpret_list(t._dynamic_columns, ',', context);
|
for (const auto& row : t._insert_values)
|
||||||
context << ") VALUES(";
|
{
|
||||||
interpret_tuple(t._values, ",", context);
|
if (not first)
|
||||||
if (sizeof...(Assignments) and not t._dynamic_values.empty())
|
context << ',';
|
||||||
context << ',';
|
else
|
||||||
interpret_list(t._dynamic_values, ',', context);
|
first = false;
|
||||||
context << ")";
|
context << '(';
|
||||||
}
|
interpret_tuple(row, ",", context);
|
||||||
return context;
|
context << ')';
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Context, typename Database, typename... Assignments>
|
||||||
|
struct serializer_t<Context, insert_list_data_t<Database, Assignments...>>
|
||||||
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, Assignments...>;
|
||||||
|
using T = insert_list_data_t<Database, Assignments...>;
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
if (sizeof...(Assignments) + t._dynamic_columns.size() == 0)
|
||||||
|
{
|
||||||
|
serialize(insert_default_values_data_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
|
#endif
|
||||||
|
@ -37,293 +37,291 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// integral value type
|
// integral value type
|
||||||
struct integral
|
struct integral
|
||||||
{
|
{
|
||||||
using _traits = make_traits<integral, tag::is_value_type>;
|
using _traits = make_traits<integral, tag::is_value_type>;
|
||||||
using _tag = tag::is_integral;
|
using _tag = tag::is_integral;
|
||||||
using _cpp_value_type = int64_t;
|
using _cpp_value_type = int64_t;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_numeric_t<T>;
|
using _is_valid_operand = is_numeric_t<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// integral parameter value
|
// integral parameter value
|
||||||
template<>
|
template <>
|
||||||
struct parameter_value_t<integral>
|
struct parameter_value_t<integral>
|
||||||
{
|
{
|
||||||
using _value_type = integral;
|
using _value_type = integral;
|
||||||
using _cpp_value_type = typename _value_type::_cpp_value_type;
|
using _cpp_value_type = typename _value_type::_cpp_value_type;
|
||||||
|
|
||||||
parameter_value_t():
|
parameter_value_t() : _value(0), _is_null(true)
|
||||||
_value(0),
|
{
|
||||||
_is_null(true)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
explicit parameter_value_t(const _cpp_value_type& val):
|
explicit parameter_value_t(const _cpp_value_type& val) : _value(val), _is_null(false)
|
||||||
_value(val),
|
{
|
||||||
_is_null(false)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
parameter_value_t& operator=(const _cpp_value_type& val)
|
parameter_value_t& operator=(const _cpp_value_type& val)
|
||||||
{
|
{
|
||||||
_value = val;
|
_value = val;
|
||||||
_is_null = false;
|
_is_null = false;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
|
parameter_value_t& operator=(const tvin_t<wrap_operand_t<_cpp_value_type>>& t)
|
||||||
{
|
{
|
||||||
if (t._is_trivial())
|
if (t._is_trivial())
|
||||||
{
|
{
|
||||||
_value = 0;
|
_value = 0;
|
||||||
_is_null = true;
|
_is_null = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_value = t._value._t;
|
_value = t._value._t;
|
||||||
_is_null = false;
|
_is_null = false;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_null()
|
void set_null()
|
||||||
{
|
{
|
||||||
_value = 0;
|
_value = 0;
|
||||||
_is_null = true;
|
_is_null = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_null() const
|
bool is_null() const
|
||||||
{
|
{
|
||||||
return _is_null;
|
return _is_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const _cpp_value_type& value() const
|
const _cpp_value_type& value() const
|
||||||
{
|
{
|
||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
operator _cpp_value_type() const { return _value; }
|
operator _cpp_value_type() const
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Target>
|
template <typename Target>
|
||||||
void _bind(Target& target, size_t index) const
|
void _bind(Target& target, size_t index) const
|
||||||
{
|
{
|
||||||
target._bind_integral_parameter(index, &_value, _is_null);
|
target._bind_integral_parameter(index, &_value, _is_null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
_cpp_value_type _value;
|
_cpp_value_type _value;
|
||||||
bool _is_null;
|
bool _is_null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// integral expression operators
|
// integral expression operators
|
||||||
template<typename Base>
|
template <typename Base>
|
||||||
struct expression_operators<Base, integral>: public basic_expression_operators<Base, integral>
|
struct expression_operators<Base, integral> : public basic_expression_operators<Base, integral>
|
||||||
{
|
{
|
||||||
template<typename T>
|
template <typename T>
|
||||||
using _is_valid_operand = is_valid_operand<integral, T>;
|
using _is_valid_operand = is_valid_operand<integral, T>;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
plus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator +(T t) const
|
plus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator+(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {t} };
|
return {*static_cast<const Base*>(this), {t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
minus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator -(T t) const
|
minus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator-(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {t} };
|
return {*static_cast<const Base*>(this), {t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>> operator *(T t) const
|
multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>> operator*(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {t} };
|
return {*static_cast<const Base*>(this), {t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
divides_t<Base, wrap_operand_t<T>> operator /(T t) const
|
divides_t<Base, wrap_operand_t<T>> operator/(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {t} };
|
return {*static_cast<const Base*>(this), {t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
modulus_t<Base, wrap_operand_t<T>> operator %(T t) const
|
modulus_t<Base, wrap_operand_t<T>> operator%(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {t} };
|
return {*static_cast<const Base*>(this), {t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
unary_plus_t<integral, Base> operator +() const
|
unary_plus_t<integral, Base> operator+() const
|
||||||
{
|
{
|
||||||
return { *static_cast<const Base*>(this) };
|
return {*static_cast<const Base*>(this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
unary_minus_t<integral, Base> operator -() const
|
unary_minus_t<integral, Base> operator-() const
|
||||||
{
|
{
|
||||||
return { *static_cast<const Base*>(this) };
|
return {*static_cast<const Base*>(this)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
bitwise_and_t<Base, value_type_t<T>, wrap_operand_t<T>> operator &(T t) const
|
bitwise_and_t<Base, value_type_t<T>, wrap_operand_t<T>> operator&(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {t} };
|
return {*static_cast<const Base*>(this), {t}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
bitwise_or_t<Base, value_type_t<T>, wrap_operand_t<T>> operator |(T t) const
|
bitwise_or_t<Base, value_type_t<T>, wrap_operand_t<T>> operator|(T t) const
|
||||||
{
|
{
|
||||||
using rhs = wrap_operand_t<T>;
|
using rhs = wrap_operand_t<T>;
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {t} };
|
return {*static_cast<const Base*>(this), {t}};
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
};
|
// integral column operators
|
||||||
|
template <typename Base>
|
||||||
|
struct column_operators<Base, integral>
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
using _is_valid_operand = is_valid_operand<integral, T>;
|
||||||
|
|
||||||
// integral column operators
|
template <typename T>
|
||||||
template<typename Base>
|
auto operator+=(T t) const -> assignment_t<Base, plus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
||||||
struct column_operators<Base, integral>
|
{
|
||||||
{
|
using rhs = wrap_operand_t<T>;
|
||||||
template<typename T>
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||||
using _is_valid_operand = is_valid_operand<integral, T>;
|
|
||||||
|
|
||||||
template<typename T>
|
return {*static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
|
||||||
auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
}
|
||||||
{
|
|
||||||
using rhs = wrap_operand_t<T>;
|
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
|
template <typename T>
|
||||||
}
|
auto operator-=(T t) const -> assignment_t<Base, minus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
||||||
|
{
|
||||||
|
using rhs = wrap_operand_t<T>;
|
||||||
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||||
|
|
||||||
template<typename T>
|
return {*static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
|
||||||
auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
}
|
||||||
{
|
|
||||||
using rhs = wrap_operand_t<T>;
|
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
|
template <typename T>
|
||||||
}
|
auto operator/=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
|
||||||
|
{
|
||||||
|
using rhs = wrap_operand_t<T>;
|
||||||
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||||
|
|
||||||
template<typename T>
|
return {*static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
|
||||||
auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
|
}
|
||||||
{
|
|
||||||
using rhs = wrap_operand_t<T>;
|
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
|
template <typename T>
|
||||||
}
|
auto operator*=(T t) const -> assignment_t<Base, multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
||||||
|
{
|
||||||
|
using rhs = wrap_operand_t<T>;
|
||||||
|
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||||
|
|
||||||
template<typename T>
|
return {*static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
|
||||||
auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
}
|
||||||
{
|
};
|
||||||
using rhs = wrap_operand_t<T>;
|
|
||||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
|
||||||
|
|
||||||
return { *static_cast<const Base*>(this), {{*static_cast<const Base*>(this), rhs{t}}}};
|
// integral result field
|
||||||
}
|
template <typename Db, typename FieldSpec>
|
||||||
};
|
struct result_field_t<integral, Db, FieldSpec>
|
||||||
|
: public result_field_methods_t<result_field_t<integral, Db, FieldSpec>>
|
||||||
|
{
|
||||||
|
static_assert(std::is_same<value_type_of<FieldSpec>, integral>::value, "field type mismatch");
|
||||||
|
using _cpp_value_type = typename integral::_cpp_value_type;
|
||||||
|
|
||||||
// integral result field
|
result_field_t() : _is_valid(false), _is_null(true), _value(0)
|
||||||
template<typename Db, typename FieldSpec>
|
{
|
||||||
struct result_field_t<integral, Db, FieldSpec>: public result_field_methods_t<result_field_t<integral, Db, FieldSpec>>
|
}
|
||||||
{
|
|
||||||
static_assert(std::is_same<value_type_of<FieldSpec>, integral>::value, "field type mismatch");
|
|
||||||
using _cpp_value_type = typename integral::_cpp_value_type;
|
|
||||||
|
|
||||||
result_field_t():
|
void _invalidate()
|
||||||
_is_valid(false),
|
{
|
||||||
_is_null(true),
|
_is_valid = false;
|
||||||
_value(0)
|
_is_null = true;
|
||||||
{}
|
_value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void _invalidate()
|
void _validate()
|
||||||
{
|
{
|
||||||
_is_valid = false;
|
_is_valid = true;
|
||||||
_is_null = true;
|
}
|
||||||
_value = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _validate()
|
bool is_null() const
|
||||||
{
|
{
|
||||||
_is_valid = true;
|
if (not _is_valid)
|
||||||
}
|
throw exception("accessing is_null in non-existing row");
|
||||||
|
return _is_null;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_null() const
|
bool _is_trivial() const
|
||||||
{
|
{
|
||||||
if (not _is_valid)
|
if (not _is_valid)
|
||||||
throw exception("accessing is_null in non-existing row");
|
throw exception("accessing is_null in non-existing row");
|
||||||
return _is_null;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _is_trivial() const
|
return value() == 0;
|
||||||
{
|
}
|
||||||
if (not _is_valid)
|
|
||||||
throw exception("accessing is_null in non-existing row");
|
|
||||||
|
|
||||||
return value() == 0;
|
_cpp_value_type value() const
|
||||||
}
|
{
|
||||||
|
if (not _is_valid)
|
||||||
|
throw exception("accessing value in non-existing row");
|
||||||
|
|
||||||
_cpp_value_type value() const
|
if (_is_null)
|
||||||
{
|
{
|
||||||
if (not _is_valid)
|
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||||
throw exception("accessing value in non-existing row");
|
{
|
||||||
|
throw exception("accessing value of NULL field");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
if (_is_null)
|
template <typename Target>
|
||||||
{
|
void _bind(Target& target, size_t i)
|
||||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
{
|
||||||
{
|
target._bind_integral_result(i, &_value, &_is_null);
|
||||||
throw exception("accessing value of NULL field");
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Target>
|
private:
|
||||||
void _bind(Target& target, size_t i)
|
bool _is_valid;
|
||||||
{
|
bool _is_null;
|
||||||
target._bind_integral_result(i, &_value, &_is_null);
|
_cpp_value_type _value;
|
||||||
}
|
};
|
||||||
|
|
||||||
private:
|
// ostream operator for integral result field
|
||||||
bool _is_valid;
|
template <typename Db, typename FieldSpec>
|
||||||
bool _is_null;
|
inline std::ostream& operator<<(std::ostream& os, const result_field_t<integral, Db, FieldSpec>& e)
|
||||||
_cpp_value_type _value;
|
{
|
||||||
};
|
return serialize(e, os);
|
||||||
|
}
|
||||||
// ostream operator for integral result field
|
|
||||||
template<typename Db, typename FieldSpec>
|
|
||||||
inline std::ostream& operator<<(std::ostream& os, const result_field_t<integral, Db, FieldSpec>& e)
|
|
||||||
{
|
|
||||||
return serialize(e, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
using tinyint = integral;
|
|
||||||
using smallint = integral;
|
|
||||||
using integer = integral;
|
|
||||||
using bigint = integral;
|
|
||||||
|
|
||||||
|
using tinyint = integral;
|
||||||
|
using smallint = integral;
|
||||||
|
using integer = integral;
|
||||||
|
using bigint = integral;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,13 +31,11 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename T, typename Context>
|
template <typename T, typename Context>
|
||||||
auto interpret(const T& t, Context& context)
|
auto interpret(const T& t, Context& context) -> decltype(interpreter_t<Context, T>::_(t, context))
|
||||||
-> decltype(interpreter_t<Context, T>::_(t, context))
|
{
|
||||||
{
|
return interpreter_t<Context, T>::_(t, context);
|
||||||
return interpreter_t<Context, T>::_(t, context);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,45 +34,50 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Element, typename Separator, typename Context, typename UseBraces>
|
template <typename Element, typename Separator, typename Context, typename UseBraces>
|
||||||
static void interpret_tuple_element(const Element& element, const Separator& separator, Context& context, const UseBraces&, size_t index)
|
static void interpret_tuple_element(
|
||||||
{
|
const Element& element, const Separator& separator, Context& context, const UseBraces&, size_t index)
|
||||||
if (index)
|
{
|
||||||
context << separator;
|
if (index)
|
||||||
if (UseBraces::value)
|
context << separator;
|
||||||
serialize_operand(element, context);
|
if (UseBraces::value)
|
||||||
else
|
serialize_operand(element, context);
|
||||||
serialize(element, context);
|
else
|
||||||
}
|
serialize(element, context);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Tuple, typename Separator, typename Context, typename UseBraces, size_t... Is>
|
template <typename Tuple, typename Separator, typename Context, typename UseBraces, size_t... Is>
|
||||||
auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const UseBraces& useBraces, const detail::index_sequence<Is...>&)
|
auto interpret_tuple_impl(const Tuple& t,
|
||||||
-> Context&
|
const Separator& separator,
|
||||||
{
|
Context& context,
|
||||||
// Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4.
|
const UseBraces& useBraces,
|
||||||
// See for example: "http://en.cppreference.com/w/cpp/utility/integer_sequence"
|
const detail::index_sequence<Is...>&) -> Context &
|
||||||
// See also: "http://stackoverflow.com/questions/6245735/pretty-print-stdtuple/6245777#6245777"
|
{
|
||||||
// Beware of gcc-bug: "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253", otherwise an empty swallow struct could be used
|
// Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init]
|
||||||
using swallow = int[];
|
// paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4.
|
||||||
(void) swallow{
|
// See for example: "http://en.cppreference.com/w/cpp/utility/integer_sequence"
|
||||||
0, //workaround against -Wpedantic GCC warning "zero-size array 'int [0]'"
|
// See also: "http://stackoverflow.com/questions/6245735/pretty-print-stdtuple/6245777#6245777"
|
||||||
(interpret_tuple_element(std::get<Is>(t), separator, context, useBraces, Is), 0)...};
|
// Beware of gcc-bug: "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253", otherwise an empty swallow struct could
|
||||||
return context;
|
// be used
|
||||||
}
|
using swallow = int[];
|
||||||
|
(void)swallow{0, // workaround against -Wpedantic GCC warning "zero-size array 'int [0]'"
|
||||||
|
(interpret_tuple_element(std::get<Is>(t), separator, context, useBraces, Is), 0)...};
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Tuple, typename Separator, typename Context>
|
template <typename Tuple, typename Separator, typename Context>
|
||||||
auto interpret_tuple(const Tuple& t, const Separator& separator, Context& context)
|
auto interpret_tuple(const Tuple& t, const Separator& separator, Context& context) -> Context &
|
||||||
-> Context&
|
{
|
||||||
{
|
return interpret_tuple_impl(t, separator, context, std::true_type{},
|
||||||
return interpret_tuple_impl(t, separator, context, std::true_type{}, detail::make_index_sequence<std::tuple_size<Tuple>::value>{});
|
detail::make_index_sequence<std::tuple_size<Tuple>::value>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Tuple, typename Separator, typename Context>
|
template <typename Tuple, typename Separator, typename Context>
|
||||||
auto interpret_tuple_without_braces(const Tuple& t, const Separator& separator, Context& context)
|
auto interpret_tuple_without_braces(const Tuple& t, const Separator& separator, Context& context) -> Context &
|
||||||
-> Context&
|
{
|
||||||
{
|
return interpret_tuple_impl(t, separator, context, std::false_type{},
|
||||||
return interpret_tuple_impl(t, separator, context, std::false_type{}, detail::make_index_sequence<std::tuple_size<Tuple>::value>{});
|
detail::make_index_sequence<std::tuple_size<Tuple>::value>{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,106 +35,106 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
struct interpretable_t
|
struct interpretable_t
|
||||||
{
|
{
|
||||||
using _serializer_context_t = typename Db::_serializer_context_t;
|
using _serializer_context_t = typename Db::_serializer_context_t;
|
||||||
using _interpreter_context_t = typename Db::_interpreter_context_t;
|
using _interpreter_context_t = typename Db::_interpreter_context_t;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
interpretable_t(T t):
|
interpretable_t(T t)
|
||||||
_requires_braces(requires_braces_t<T>::value),
|
: _requires_braces(requires_braces_t<T>::value), _impl(std::make_shared<_impl_t<T>>(t))
|
||||||
_impl(std::make_shared<_impl_t<T>>(t))
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
interpretable_t(const interpretable_t&) = default;
|
interpretable_t(const interpretable_t&) = default;
|
||||||
interpretable_t(interpretable_t&&) = default;
|
interpretable_t(interpretable_t&&) = default;
|
||||||
interpretable_t& operator=(const interpretable_t&) = default;
|
interpretable_t& operator=(const interpretable_t&) = default;
|
||||||
interpretable_t& operator=(interpretable_t&&) = default;
|
interpretable_t& operator=(interpretable_t&&) = default;
|
||||||
~interpretable_t() = default;
|
~interpretable_t() = default;
|
||||||
|
|
||||||
serializer_context_t& serialize(serializer_context_t& context) const
|
serializer_context_t& serialize(serializer_context_t& context) const
|
||||||
{
|
{
|
||||||
return _impl->serialize(context);
|
return _impl->serialize(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method only exists if Db::_serializer_context_t and serializer_context_t are not the same
|
// This method only exists if Db::_serializer_context_t and serializer_context_t are not the same
|
||||||
template<typename Context>
|
template <typename Context>
|
||||||
auto serialize(Context& context) const
|
auto serialize(Context& context) const ->
|
||||||
-> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value
|
typename std::enable_if<std::is_same<Context, _serializer_context_t>::value and
|
||||||
and not std::is_same<Context, serializer_context_t>::value, Context&>::type
|
not std::is_same<Context, serializer_context_t>::value,
|
||||||
{
|
Context&>::type
|
||||||
return _impl->db_serialize(context);
|
{
|
||||||
}
|
return _impl->db_serialize(context);
|
||||||
|
}
|
||||||
|
|
||||||
_interpreter_context_t& interpret(_interpreter_context_t& context) const
|
_interpreter_context_t& interpret(_interpreter_context_t& context) const
|
||||||
{
|
{
|
||||||
return _impl->interpret(context);
|
return _impl->interpret(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _requires_braces;
|
bool _requires_braces;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct _impl_base
|
struct _impl_base
|
||||||
{
|
{
|
||||||
virtual serializer_context_t& serialize(serializer_context_t& context) const = 0;
|
virtual serializer_context_t& serialize(serializer_context_t& context) const = 0;
|
||||||
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
|
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
|
||||||
virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
|
virtual _interpreter_context_t& interpret(_interpreter_context_t& context) 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>::size::value, "parameters not supported in dynamic statement parts");
|
static_assert(not make_parameter_list_t<T>::size::value, "parameters not supported in dynamic statement parts");
|
||||||
_impl_t(T t):
|
_impl_t(T t) : _t(t)
|
||||||
_t(t)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
serializer_context_t& serialize(serializer_context_t& context) const
|
serializer_context_t& serialize(serializer_context_t& context) const
|
||||||
{
|
{
|
||||||
::sqlpp::serialize(_t, context);
|
::sqlpp::serialize(_t, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
_serializer_context_t& db_serialize(_serializer_context_t& context) const
|
_serializer_context_t& db_serialize(_serializer_context_t& context) const
|
||||||
{
|
{
|
||||||
Db::_serialize_interpretable(_t, context);
|
Db::_serialize_interpretable(_t, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
_interpreter_context_t& interpret(_interpreter_context_t& context) const
|
_interpreter_context_t& interpret(_interpreter_context_t& context) const
|
||||||
{
|
{
|
||||||
Db::_interpret_interpretable(_t, context);
|
Db::_interpret_interpretable(_t, context);
|
||||||
return 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>
|
template <typename Context, typename Database>
|
||||||
struct serializer_t<Context, interpretable_t<Database>>
|
struct serializer_t<Context, interpretable_t<Database>>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = interpretable_t<Database>;
|
using T = interpretable_t<Database>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if (t._requires_braces)
|
if (t._requires_braces)
|
||||||
{
|
{
|
||||||
context << '(';
|
context << '(';
|
||||||
t.serialize(context);
|
t.serialize(context);
|
||||||
context << ')';
|
context << ')';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
t.serialize(context);
|
t.serialize(context);
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,85 +32,82 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
struct interpretable_list_t
|
struct interpretable_list_t
|
||||||
{
|
{
|
||||||
std::vector<interpretable_t<Db>> _serializables;
|
std::vector<interpretable_t<Db>> _serializables;
|
||||||
|
|
||||||
std::size_t size() const
|
std::size_t size() const
|
||||||
{
|
{
|
||||||
return _serializables.size();
|
return _serializables.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const
|
bool empty() const
|
||||||
{
|
{
|
||||||
return _serializables.empty();
|
return _serializables.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expr>
|
template <typename Expr>
|
||||||
void emplace_back(Expr expr)
|
void emplace_back(Expr expr)
|
||||||
{
|
{
|
||||||
_serializables.emplace_back(expr);
|
_serializables.emplace_back(expr);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
};
|
template <>
|
||||||
|
struct interpretable_list_t<void>
|
||||||
|
{
|
||||||
|
static constexpr std::size_t size()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
static constexpr bool empty()
|
||||||
struct interpretable_list_t<void>
|
{
|
||||||
{
|
return true;
|
||||||
static constexpr std::size_t size()
|
}
|
||||||
{
|
};
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static constexpr bool empty()
|
template <typename Context, typename List>
|
||||||
{
|
struct serializable_list_interpreter_t
|
||||||
return true;
|
{
|
||||||
}
|
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;
|
||||||
|
serialize(entry, context);
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Context, typename List>
|
template <typename Context>
|
||||||
struct serializable_list_interpreter_t
|
struct serializable_list_interpreter_t<Context, interpretable_list_t<void>>
|
||||||
{
|
{
|
||||||
using T = List;
|
using T = interpretable_list_t<void>;
|
||||||
|
|
||||||
template<typename Separator>
|
template <typename Separator>
|
||||||
static Context& _(const T& t, const Separator& separator, Context& context)
|
static Context& _(const T&, const Separator& /* separator */, Context& context)
|
||||||
{
|
{
|
||||||
bool first = true;
|
return context;
|
||||||
for (const auto entry : t._serializables)
|
}
|
||||||
{
|
};
|
||||||
if (not first)
|
|
||||||
{
|
|
||||||
context << separator;
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
serialize(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&, 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<Context, T>::_(t, separator, context))
|
|
||||||
{
|
|
||||||
return serializable_list_interpreter_t<Context, T>::_(t, separator, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T, typename Separator, typename Context>
|
||||||
|
auto interpret_list(const T& t, const Separator& separator, Context& context)
|
||||||
|
-> decltype(serializable_list_interpreter_t<Context, T>::_(t, separator, context))
|
||||||
|
{
|
||||||
|
return serializable_list_interpreter_t<Context, T>::_(t, separator, context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,15 +31,14 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Context, typename T, typename Enable = void>
|
template <typename Context, typename T, typename Enable = void>
|
||||||
struct interpreter_t
|
struct interpreter_t
|
||||||
{
|
{
|
||||||
static void _(const T&, Context&)
|
static void _(const T&, Context&)
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<interpreter_t>::value, "missing interpreter specialization");
|
static_assert(wrong_t<interpreter_t>::value, "missing interpreter specialization");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,159 +37,171 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// A SINGLE TABLE DATA
|
// A SINGLE TABLE DATA
|
||||||
template<typename Database, typename Table>
|
template <typename Database, typename Table>
|
||||||
struct into_data_t
|
struct into_data_t
|
||||||
{
|
{
|
||||||
into_data_t(Table table):
|
into_data_t(Table table) : _table(table)
|
||||||
_table(table)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
into_data_t(const into_data_t&) = default;
|
into_data_t(const into_data_t&) = default;
|
||||||
into_data_t(into_data_t&&) = default;
|
into_data_t(into_data_t&&) = default;
|
||||||
into_data_t& operator=(const into_data_t&) = default;
|
into_data_t& operator=(const into_data_t&) = default;
|
||||||
into_data_t& operator=(into_data_t&&) = default;
|
into_data_t& operator=(into_data_t&&) = default;
|
||||||
~into_data_t() = default;
|
~into_data_t() = default;
|
||||||
|
|
||||||
Table _table;
|
Table _table;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A SINGLE TABLE
|
// A SINGLE TABLE
|
||||||
template<typename Database, typename Table>
|
template <typename Database, typename Table>
|
||||||
struct into_t
|
struct into_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_into>;
|
using _traits = make_traits<no_value_t, tag::is_into>;
|
||||||
using _nodes = detail::type_vector<Table>;
|
using _nodes = detail::type_vector<Table>;
|
||||||
|
|
||||||
using _data_t = into_data_t<Database, Table>;
|
using _data_t = into_data_t<Database, Table>;
|
||||||
|
|
||||||
struct _alias_t {};
|
struct _alias_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Base template to be inherited by the statement
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
using _data_t = into_data_t<Database, Table>;
|
using _data_t = into_data_t<Database, Table>;
|
||||||
|
|
||||||
_impl_t<Policies> into;
|
_impl_t<Policies> into;
|
||||||
_impl_t<Policies>& operator()() { return into; }
|
_impl_t<Policies>& operator()()
|
||||||
const _impl_t<Policies>& operator()() const { return into; }
|
{
|
||||||
|
return into;
|
||||||
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return into;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.into)
|
static auto _get_member(T t) -> decltype(t.into)
|
||||||
{
|
{
|
||||||
return t.into;
|
return t.into;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = consistent_t;
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
};
|
struct assert_into_t
|
||||||
|
{
|
||||||
|
using type = std::false_type;
|
||||||
|
|
||||||
struct assert_into_t
|
template <typename T = void>
|
||||||
{
|
static void _()
|
||||||
using type = std::false_type;
|
{
|
||||||
|
static_assert(wrong_t<T>::value, "into() required");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T = void>
|
// NO INTO YET
|
||||||
static void _()
|
struct no_into_t
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "into() required");
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
}
|
using _nodes = detail::type_vector<>;
|
||||||
};
|
|
||||||
|
|
||||||
// NO INTO YET
|
// Data
|
||||||
struct no_into_t
|
using _data_t = no_data_t;
|
||||||
{
|
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
|
|
||||||
// Data
|
// Member implementation with data and methods
|
||||||
using _data_t = no_data_t;
|
template <typename Policies>
|
||||||
|
struct _impl_t
|
||||||
|
{
|
||||||
|
_data_t _data;
|
||||||
|
};
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Base template to be inherited by the statement
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
_data_t _data;
|
using _data_t = no_data_t;
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
_impl_t<Policies> no_into;
|
||||||
template<typename Policies>
|
_impl_t<Policies>& operator()()
|
||||||
struct _base_t
|
{
|
||||||
{
|
return no_into;
|
||||||
using _data_t = no_data_t;
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return no_into;
|
||||||
|
}
|
||||||
|
|
||||||
_impl_t<Policies> no_into;
|
template <typename T>
|
||||||
_impl_t<Policies>& operator()() { return no_into; }
|
static auto _get_member(T t) -> decltype(t.no_into)
|
||||||
const _impl_t<Policies>& operator()() const { return no_into; }
|
{
|
||||||
|
return t.no_into;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
using _database_t = typename Policies::_database_t;
|
||||||
static auto _get_member(T t) -> decltype(t.no_into)
|
|
||||||
{
|
|
||||||
return t.no_into;
|
|
||||||
}
|
|
||||||
|
|
||||||
using _database_t = typename Policies::_database_t;
|
template <typename T>
|
||||||
|
using _check = logic::all_t<is_raw_table_t<T>::value>;
|
||||||
|
|
||||||
template<typename T>
|
template <typename Check, typename T>
|
||||||
using _check = logic::all_t<is_raw_table_t<T>::value>;
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_into_t, T>;
|
||||||
|
|
||||||
template<typename Check, typename T>
|
using _consistency_check = assert_into_t;
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_into_t, T>;
|
|
||||||
|
|
||||||
using _consistency_check = assert_into_t;
|
template <typename Table>
|
||||||
|
auto into(Table table) const -> _new_statement_t<_check<Table>, into_t<void, Table>>
|
||||||
|
{
|
||||||
|
static_assert(_check<Table>::value, "argument is not a raw table in into()");
|
||||||
|
return _into_impl<void>(_check<Table>{}, table);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Table>
|
private:
|
||||||
auto into(Table table) const
|
template <typename Database, typename Table>
|
||||||
-> _new_statement_t<_check<Table>, into_t<void, Table>>
|
auto _into_impl(const std::false_type&, Table table) const -> bad_statement;
|
||||||
{
|
|
||||||
static_assert(_check<Table>::value, "argument is not a raw table in into()");
|
|
||||||
return _into_impl<void>(_check<Table>{}, table);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
template <typename Database, typename Table>
|
||||||
template<typename Database, typename Table>
|
auto _into_impl(const std::true_type&, Table table) const
|
||||||
auto _into_impl(const std::false_type&, Table table) const
|
-> _new_statement_t<std::true_type, into_t<Database, Table>>
|
||||||
-> bad_statement;
|
{
|
||||||
|
static_assert(required_tables_of<into_t<Database, Table>>::size::value == 0,
|
||||||
|
"argument depends on another table in into()");
|
||||||
|
|
||||||
template<typename Database, typename Table>
|
return {static_cast<const derived_statement_t<Policies>&>(*this), into_data_t<Database, Table>{table}};
|
||||||
auto _into_impl(const std::true_type&, Table table) const
|
}
|
||||||
-> _new_statement_t<std::true_type, into_t<Database, Table>>
|
};
|
||||||
{
|
};
|
||||||
static_assert(required_tables_of<into_t<Database, Table>>::size::value == 0, "argument depends on another table in into()");
|
|
||||||
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), into_data_t<Database, Table>{table} };
|
// Interpreters
|
||||||
}
|
template <typename Context, typename Database, typename Table>
|
||||||
};
|
struct serializer_t<Context, into_data_t<Database, Table>>
|
||||||
};
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, Table>;
|
||||||
|
using T = into_data_t<Database, Table>;
|
||||||
|
|
||||||
// Interpreters
|
static Context& _(const T& t, Context& context)
|
||||||
template<typename Context, typename Database, typename Table>
|
{
|
||||||
struct serializer_t<Context, into_data_t<Database, Table>>
|
context << " INTO ";
|
||||||
{
|
serialize(t._table, context);
|
||||||
using _serialize_check = serialize_check_of<Context, Table>;
|
return context;
|
||||||
using T = into_data_t<Database, Table>;
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
template <typename T>
|
||||||
{
|
auto into(T&& t) -> decltype(statement_t<void, no_into_t>().into(std::forward<T>(t)))
|
||||||
context << " INTO ";
|
{
|
||||||
serialize(t._table, context);
|
return statement_t<void, no_into_t>().into(std::forward<T>(t));
|
||||||
return context;
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto into(T&& t) -> decltype(statement_t<void, no_into_t>().into(std::forward<T>(t)))
|
|
||||||
{
|
|
||||||
return statement_t<void, no_into_t>().into(std::forward<T>(t));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,57 +34,55 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct is_not_null_alias_t
|
struct is_not_null_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "is_not_null_";
|
static constexpr const char _literal[] = "is_not_null_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T is_not_null;
|
T is_not_null;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Operand>
|
template <typename Operand>
|
||||||
struct is_not_null_t:
|
struct is_not_null_t : public expression_operators<is_not_null_t<Operand>, boolean>,
|
||||||
public expression_operators<is_not_null_t<Operand>, boolean>,
|
public alias_operators<is_not_null_t<Operand>>
|
||||||
public alias_operators<is_not_null_t<Operand>>
|
{
|
||||||
{
|
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
||||||
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
using _nodes = detail::type_vector<Operand>;
|
||||||
using _nodes = detail::type_vector<Operand>;
|
|
||||||
|
|
||||||
using _auto_alias_t = is_not_null_alias_t;
|
using _auto_alias_t = is_not_null_alias_t;
|
||||||
|
|
||||||
is_not_null_t(Operand operand):
|
is_not_null_t(Operand operand) : _operand(operand)
|
||||||
_operand(operand)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
is_not_null_t(const is_not_null_t&) = default;
|
is_not_null_t(const is_not_null_t&) = default;
|
||||||
is_not_null_t(is_not_null_t&&) = default;
|
is_not_null_t(is_not_null_t&&) = default;
|
||||||
is_not_null_t& operator=(const is_not_null_t&) = default;
|
is_not_null_t& operator=(const is_not_null_t&) = default;
|
||||||
is_not_null_t& operator=(is_not_null_t&&) = default;
|
is_not_null_t& operator=(is_not_null_t&&) = default;
|
||||||
~is_not_null_t() = default;
|
~is_not_null_t() = default;
|
||||||
|
|
||||||
Operand _operand;
|
Operand _operand;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Operand>
|
template <typename Context, typename Operand>
|
||||||
struct serializer_t<Context, is_not_null_t<Operand>>
|
struct serializer_t<Context, is_not_null_t<Operand>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Operand>;
|
using _serialize_check = serialize_check_of<Context, Operand>;
|
||||||
using T = is_not_null_t<Operand>;
|
using T = is_not_null_t<Operand>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
serialize_operand(t._operand, context);
|
|
||||||
context << " IS NOT NULL";
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
serialize_operand(t._operand, context);
|
||||||
|
context << " IS NOT NULL";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,57 +34,55 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct is_null_alias_t
|
struct is_null_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "is_null_";
|
static constexpr const char _literal[] = "is_null_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T is_null;
|
T is_null;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Operand>
|
template <typename Operand>
|
||||||
struct is_null_t:
|
struct is_null_t : public expression_operators<is_null_t<Operand>, boolean>,
|
||||||
public expression_operators<is_null_t<Operand>, boolean>,
|
public alias_operators<is_null_t<Operand>>
|
||||||
public alias_operators<is_null_t<Operand>>
|
{
|
||||||
{
|
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
||||||
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
using _nodes = detail::type_vector<Operand>;
|
||||||
using _nodes = detail::type_vector<Operand>;
|
|
||||||
|
|
||||||
using _auto_alias_t = is_null_alias_t;
|
using _auto_alias_t = is_null_alias_t;
|
||||||
|
|
||||||
is_null_t(Operand operand):
|
is_null_t(Operand operand) : _operand(operand)
|
||||||
_operand(operand)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
is_null_t(const is_null_t&) = default;
|
is_null_t(const is_null_t&) = default;
|
||||||
is_null_t(is_null_t&&) = default;
|
is_null_t(is_null_t&&) = default;
|
||||||
is_null_t& operator=(const is_null_t&) = default;
|
is_null_t& operator=(const is_null_t&) = default;
|
||||||
is_null_t& operator=(is_null_t&&) = default;
|
is_null_t& operator=(is_null_t&&) = default;
|
||||||
~is_null_t() = default;
|
~is_null_t() = default;
|
||||||
|
|
||||||
Operand _operand;
|
Operand _operand;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Operand>
|
template <typename Context, typename Operand>
|
||||||
struct serializer_t<Context, is_null_t<Operand>>
|
struct serializer_t<Context, is_null_t<Operand>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Operand>;
|
using _serialize_check = serialize_check_of<Context, Operand>;
|
||||||
using T = is_null_t<Operand>;
|
using T = is_null_t<Operand>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
serialize_operand(t._operand, context);
|
|
||||||
context << " IS NULL";
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
serialize_operand(t._operand, context);
|
||||||
|
context << " IS NULL";
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,10 +29,10 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Operand>
|
template <typename Operand>
|
||||||
struct is_null_t;
|
struct is_null_t;
|
||||||
template<typename Operand>
|
template <typename Operand>
|
||||||
struct is_not_null_t;
|
struct is_not_null_t;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,125 +33,123 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct inner_join_t
|
struct inner_join_t
|
||||||
{
|
{
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
|
using _provided_outer_tables =
|
||||||
|
detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
|
||||||
|
|
||||||
static constexpr const char* _name = " INNER ";
|
static constexpr const char* _name = " INNER ";
|
||||||
};
|
};
|
||||||
struct outer_join_t
|
struct outer_join_t
|
||||||
{
|
{
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
||||||
|
|
||||||
static constexpr const char* _name = " OUTER ";
|
static constexpr const char* _name = " OUTER ";
|
||||||
};
|
};
|
||||||
struct left_outer_join_t
|
struct left_outer_join_t
|
||||||
{
|
{
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
|
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
|
||||||
|
|
||||||
static constexpr const char* _name = " LEFT OUTER ";
|
static constexpr const char* _name = " LEFT OUTER ";
|
||||||
};
|
};
|
||||||
struct right_outer_join_t
|
struct right_outer_join_t
|
||||||
{
|
{
|
||||||
template<typename Lhs, typename Rhs>
|
template <typename Lhs, typename Rhs>
|
||||||
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
||||||
|
|
||||||
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 = noop>
|
||||||
struct join_t
|
struct join_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
|
using _traits = make_traits<no_value_t, tag::is_table, tag::is_join>;
|
||||||
using _nodes = detail::type_vector<Lhs, Rhs>;
|
using _nodes = detail::type_vector<Lhs, Rhs>;
|
||||||
using _can_be_null = std::false_type;
|
using _can_be_null = std::false_type;
|
||||||
|
|
||||||
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
|
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
|
||||||
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
|
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
|
||||||
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
|
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
|
||||||
static_assert(is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
|
static_assert(is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
|
||||||
|
|
||||||
static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value, "joined tables must not be identical");
|
static_assert(detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value,
|
||||||
|
"joined tables must not be identical");
|
||||||
|
|
||||||
static_assert(required_tables_of<join_t>::size::value == 0, "joined tables must not depend on other tables");
|
static_assert(required_tables_of<join_t>::size::value == 0, "joined tables must not depend on other tables");
|
||||||
|
|
||||||
template<typename OnT>
|
template <typename OnT>
|
||||||
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
|
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
|
||||||
|
|
||||||
template<typename... Expr>
|
template <typename... Expr>
|
||||||
auto on(Expr... expr)
|
auto on(Expr... expr) -> set_on_t<on_t<void, Expr...>>
|
||||||
-> set_on_t<on_t<void, Expr...>>
|
{
|
||||||
{
|
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
|
||||||
static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
|
static_assert(logic::all_t<is_expression_t<Expr>::value...>::value,
|
||||||
static_assert(logic::all_t<is_expression_t<Expr>::value...>::value, "at least one argument is not an expression in on()");
|
"at least one argument is not an expression in on()");
|
||||||
|
|
||||||
return { _lhs,
|
return {_lhs, _rhs, {std::tuple<Expr...>{expr...}, {}}};
|
||||||
_rhs,
|
}
|
||||||
{std::tuple<Expr...>{expr...}, {}}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
join_t<inner_join_t, join_t, T> join(T t)
|
join_t<inner_join_t, join_t, T> join(T t)
|
||||||
{
|
{
|
||||||
static_assert(not is_noop<On>::value, "join type requires on()");
|
static_assert(not is_noop<On>::value, "join type requires on()");
|
||||||
return { *this, t, {} };
|
return {*this, t, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
join_t<inner_join_t, join_t, T> inner_join(T t)
|
join_t<inner_join_t, join_t, T> inner_join(T t)
|
||||||
{
|
{
|
||||||
static_assert(not is_noop<On>::value, "join type requires on()");
|
static_assert(not is_noop<On>::value, "join type requires on()");
|
||||||
return { *this, t, {} };
|
return {*this, t, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
join_t<outer_join_t, join_t, T> outer_join(T t)
|
join_t<outer_join_t, join_t, T> outer_join(T t)
|
||||||
{
|
{
|
||||||
static_assert(not is_noop<On>::value, "join type requires on()");
|
static_assert(not is_noop<On>::value, "join type requires on()");
|
||||||
return { *this, t, {} };
|
return {*this, t, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
join_t<left_outer_join_t, join_t, T> left_outer_join(T t)
|
join_t<left_outer_join_t, join_t, T> left_outer_join(T t)
|
||||||
{
|
{
|
||||||
static_assert(not is_noop<On>::value, "join type requires on()");
|
static_assert(not is_noop<On>::value, "join type requires on()");
|
||||||
return { *this, t, {} };
|
return {*this, t, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
join_t<right_outer_join_t, join_t, T> right_outer_join(T t)
|
join_t<right_outer_join_t, join_t, T> right_outer_join(T t)
|
||||||
{
|
{
|
||||||
static_assert(not is_noop<On>::value, "join type requires on()");
|
static_assert(not is_noop<On>::value, "join type requires on()");
|
||||||
return { *this, t, {} };
|
return {*this, t, {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
Lhs _lhs;
|
Lhs _lhs;
|
||||||
Rhs _rhs;
|
Rhs _rhs;
|
||||||
On _on;
|
On _on;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename JoinType, typename Lhs, typename Rhs, typename On>
|
template <typename Context, typename JoinType, typename Lhs, typename Rhs, typename On>
|
||||||
struct serializer_t<Context, join_t<JoinType, Lhs, Rhs, On>>
|
struct serializer_t<Context, join_t<JoinType, Lhs, Rhs, On>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Lhs, Rhs, On>;
|
using _serialize_check = serialize_check_of<Context, Lhs, Rhs, On>;
|
||||||
using T = join_t<JoinType, Lhs, Rhs, On>;
|
using T = join_t<JoinType, Lhs, Rhs, On>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
static_assert(not is_noop<On>::value, "joined tables require on()");
|
|
||||||
serialize(t._lhs, context);
|
|
||||||
context << JoinType::_name;
|
|
||||||
context << " JOIN ";
|
|
||||||
serialize(t._rhs, context);
|
|
||||||
serialize(t._on, context);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
static_assert(not is_noop<On>::value, "joined tables require on()");
|
||||||
|
serialize(t._lhs, context);
|
||||||
|
context << JoinType::_name;
|
||||||
|
context << " JOIN ";
|
||||||
|
serialize(t._rhs, context);
|
||||||
|
serialize(t._on, context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,57 +34,61 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Operand, typename Pattern>
|
template <typename Operand, typename Pattern>
|
||||||
struct like_t:
|
struct like_t : public expression_operators<like_t<Operand, Pattern>, boolean>,
|
||||||
public expression_operators<like_t<Operand, Pattern>, boolean>,
|
public alias_operators<like_t<Operand, Pattern>>
|
||||||
public alias_operators<like_t<Operand, Pattern>>
|
{
|
||||||
{
|
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
||||||
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
using _nodes = detail::type_vector<Operand, Pattern>;
|
||||||
using _nodes = detail::type_vector<Operand, Pattern>;
|
|
||||||
|
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "like_";
|
static constexpr const char _literal[] = "like_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T like;
|
T like;
|
||||||
T& operator()() { return like; }
|
T& operator()()
|
||||||
const T& operator()() const { return like; }
|
{
|
||||||
};
|
return like;
|
||||||
};
|
}
|
||||||
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return like;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
like_t(Operand operand, Pattern pattern):
|
like_t(Operand operand, Pattern pattern) : _operand(operand), _pattern(pattern)
|
||||||
_operand(operand),
|
{
|
||||||
_pattern(pattern)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
like_t(const like_t&) = default;
|
like_t(const like_t&) = default;
|
||||||
like_t(like_t&&) = default;
|
like_t(like_t&&) = default;
|
||||||
like_t& operator=(const like_t&) = default;
|
like_t& operator=(const like_t&) = default;
|
||||||
like_t& operator=(like_t&&) = default;
|
like_t& operator=(like_t&&) = default;
|
||||||
~like_t() = default;
|
~like_t() = default;
|
||||||
|
|
||||||
Operand _operand;
|
Operand _operand;
|
||||||
Pattern _pattern;
|
Pattern _pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Operand, typename Pattern>
|
template <typename Context, typename Operand, typename Pattern>
|
||||||
struct serializer_t<Context, like_t<Operand, Pattern>>
|
struct serializer_t<Context, like_t<Operand, Pattern>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Operand, Pattern>;
|
using _serialize_check = serialize_check_of<Context, Operand, Pattern>;
|
||||||
using T = like_t<Operand, Pattern>;
|
using T = like_t<Operand, Pattern>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
serialize_operand(t._operand, context);
|
serialize_operand(t._operand, context);
|
||||||
context << " LIKE(";
|
context << " LIKE(";
|
||||||
serialize(t._pattern, context);
|
serialize(t._pattern, context);
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,234 +33,246 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// LIMIT DATA
|
// LIMIT DATA
|
||||||
template<typename Limit>
|
template <typename Limit>
|
||||||
struct limit_data_t
|
struct limit_data_t
|
||||||
{
|
{
|
||||||
limit_data_t(Limit value):
|
limit_data_t(Limit value) : _value(value)
|
||||||
_value(value)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
limit_data_t(const limit_data_t&) = default;
|
limit_data_t(const limit_data_t&) = default;
|
||||||
limit_data_t(limit_data_t&&) = default;
|
limit_data_t(limit_data_t&&) = default;
|
||||||
limit_data_t& operator=(const limit_data_t&) = default;
|
limit_data_t& operator=(const limit_data_t&) = default;
|
||||||
limit_data_t& operator=(limit_data_t&&) = default;
|
limit_data_t& operator=(limit_data_t&&) = default;
|
||||||
~limit_data_t() = default;
|
~limit_data_t() = default;
|
||||||
|
|
||||||
Limit _value;
|
Limit _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// LIMIT
|
// LIMIT
|
||||||
template<typename Limit>
|
template <typename Limit>
|
||||||
struct limit_t
|
struct limit_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_limit>;
|
using _traits = make_traits<no_value_t, tag::is_limit>;
|
||||||
using _nodes = detail::type_vector<Limit>;
|
using _nodes = detail::type_vector<Limit>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = limit_data_t<Limit>;
|
using _data_t = limit_data_t<Limit>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Base template to be inherited by the statement
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
using _data_t = limit_data_t<Limit>;
|
using _data_t = limit_data_t<Limit>;
|
||||||
|
|
||||||
_impl_t<Policies> limit;
|
_impl_t<Policies> limit;
|
||||||
_impl_t<Policies>& operator()() { return limit; }
|
_impl_t<Policies>& operator()()
|
||||||
const _impl_t<Policies>& operator()() const { return limit; }
|
{
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.limit)
|
static auto _get_member(T t) -> decltype(t.limit)
|
||||||
{
|
{
|
||||||
return t.limit;
|
return t.limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = consistent_t;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// DYNAMIC LIMIT DATA
|
// DYNAMIC LIMIT DATA
|
||||||
template<typename Database>
|
template <typename Database>
|
||||||
struct dynamic_limit_data_t
|
struct dynamic_limit_data_t
|
||||||
{
|
{
|
||||||
dynamic_limit_data_t():
|
dynamic_limit_data_t() : _value(noop())
|
||||||
_value(noop())
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Limit>
|
template <typename Limit>
|
||||||
dynamic_limit_data_t(Limit value):
|
dynamic_limit_data_t(Limit value)
|
||||||
_initialized(true),
|
: _initialized(true), _value(wrap_operand_t<Limit>(value))
|
||||||
_value(wrap_operand_t<Limit>(value))
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
|
||||||
dynamic_limit_data_t(const dynamic_limit_data_t&) = default;
|
dynamic_limit_data_t(const dynamic_limit_data_t&) = default;
|
||||||
dynamic_limit_data_t(dynamic_limit_data_t&&) = default;
|
dynamic_limit_data_t(dynamic_limit_data_t&&) = default;
|
||||||
dynamic_limit_data_t& operator=(const dynamic_limit_data_t&) = default;
|
dynamic_limit_data_t& operator=(const dynamic_limit_data_t&) = default;
|
||||||
dynamic_limit_data_t& operator=(dynamic_limit_data_t&&) = default;
|
dynamic_limit_data_t& operator=(dynamic_limit_data_t&&) = default;
|
||||||
~dynamic_limit_data_t() = default;
|
~dynamic_limit_data_t() = default;
|
||||||
|
|
||||||
bool _initialized = false;
|
bool _initialized = false;
|
||||||
interpretable_t<Database> _value;
|
interpretable_t<Database> _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// DYNAMIC LIMIT
|
// DYNAMIC LIMIT
|
||||||
template<typename Database>
|
template <typename Database>
|
||||||
struct dynamic_limit_t
|
struct dynamic_limit_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_limit>;
|
using _traits = make_traits<no_value_t, tag::is_limit>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = dynamic_limit_data_t<Database>;
|
using _data_t = dynamic_limit_data_t<Database>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
template<typename Limit>
|
template <typename Limit>
|
||||||
void set(Limit value)
|
void set(Limit value)
|
||||||
{
|
{
|
||||||
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
|
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
|
||||||
using arg_t = wrap_operand_t<Limit>;
|
using arg_t = wrap_operand_t<Limit>;
|
||||||
static_assert(is_integral_t<arg_t>::value, "limit requires an integral value or integral parameter");
|
static_assert(is_integral_t<arg_t>::value, "limit requires an integral value or integral parameter");
|
||||||
_data._value = arg_t{value};
|
_data._value = arg_t{value};
|
||||||
_data._initialized = true;
|
_data._initialized = true;
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
_data_t _data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
public:
|
||||||
template<typename Policies>
|
_data_t _data;
|
||||||
struct _base_t
|
};
|
||||||
{
|
|
||||||
using _data_t = dynamic_limit_data_t<Database>;
|
|
||||||
|
|
||||||
_impl_t<Policies> limit;
|
// Base template to be inherited by the statement
|
||||||
_impl_t<Policies>& operator()() { return limit; }
|
template <typename Policies>
|
||||||
const _impl_t<Policies>& operator()() const { return limit; }
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = dynamic_limit_data_t<Database>;
|
||||||
|
|
||||||
template<typename T>
|
_impl_t<Policies> limit;
|
||||||
static auto _get_member(T t) -> decltype(t.limit)
|
_impl_t<Policies>& operator()()
|
||||||
{
|
{
|
||||||
return t.limit;
|
return limit;
|
||||||
}
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return limit;
|
||||||
|
}
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
template <typename T>
|
||||||
};
|
static auto _get_member(T t) -> decltype(t.limit)
|
||||||
};
|
{
|
||||||
|
return t.limit;
|
||||||
|
}
|
||||||
|
|
||||||
struct no_limit_t
|
using _consistency_check = consistent_t;
|
||||||
{
|
};
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
};
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
|
|
||||||
// Data
|
struct no_limit_t
|
||||||
using _data_t = no_data_t;
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Data
|
||||||
template<typename Policies>
|
using _data_t = no_data_t;
|
||||||
struct _impl_t
|
|
||||||
{
|
|
||||||
_data_t _data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Member implementation with data and methods
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
using _data_t = no_data_t;
|
_data_t _data;
|
||||||
|
};
|
||||||
|
|
||||||
_impl_t<Policies> no_limit;
|
// Base template to be inherited by the statement
|
||||||
_impl_t<Policies>& operator()() { return no_limit; }
|
template <typename Policies>
|
||||||
const _impl_t<Policies>& operator()() const { return no_limit; }
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
template<typename T>
|
_impl_t<Policies> no_limit;
|
||||||
static auto _get_member(T t) -> decltype(t.no_limit)
|
_impl_t<Policies>& operator()()
|
||||||
{
|
{
|
||||||
return t.no_limit;
|
return no_limit;
|
||||||
}
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return no_limit;
|
||||||
|
}
|
||||||
|
|
||||||
using _database_t = typename Policies::_database_t;
|
template <typename T>
|
||||||
|
static auto _get_member(T t) -> decltype(t.no_limit)
|
||||||
|
{
|
||||||
|
return t.no_limit;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
using _database_t = typename Policies::_database_t;
|
||||||
using _check = is_integral_t<wrap_operand_t<T>>;
|
|
||||||
|
|
||||||
template<typename Check, typename T>
|
template <typename T>
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_limit_t, T>;
|
using _check = is_integral_t<wrap_operand_t<T>>;
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
template <typename Check, typename T>
|
||||||
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_limit_t, T>;
|
||||||
|
|
||||||
template<typename Arg>
|
using _consistency_check = consistent_t;
|
||||||
auto limit(Arg arg) const
|
|
||||||
-> _new_statement_t<_check<Arg>, limit_t<wrap_operand_t<Arg>>>
|
|
||||||
{
|
|
||||||
static_assert(_check<Arg>::value, "limit requires an integral value or integral parameter");
|
|
||||||
return _limit_impl(_check<Arg>{}, wrap_operand_t<Arg>{arg});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dynamic_limit() const
|
template <typename Arg>
|
||||||
-> _new_statement_t<std::true_type, dynamic_limit_t<_database_t>>
|
auto limit(Arg arg) const -> _new_statement_t<_check<Arg>, limit_t<wrap_operand_t<Arg>>>
|
||||||
{
|
{
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), dynamic_limit_data_t<_database_t>{} };
|
static_assert(_check<Arg>::value, "limit requires an integral value or integral parameter");
|
||||||
}
|
return _limit_impl(_check<Arg>{}, wrap_operand_t<Arg>{arg});
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
auto dynamic_limit() const -> _new_statement_t<std::true_type, dynamic_limit_t<_database_t>>
|
||||||
template<typename Arg>
|
{
|
||||||
auto _limit_impl(const std::false_type&, Arg arg) const
|
return {static_cast<const derived_statement_t<Policies>&>(*this), dynamic_limit_data_t<_database_t>{}};
|
||||||
-> bad_statement;
|
}
|
||||||
|
|
||||||
template<typename Arg>
|
private:
|
||||||
auto _limit_impl(const std::true_type&, Arg arg) const
|
template <typename Arg>
|
||||||
-> _new_statement_t<std::true_type, limit_t<Arg>>
|
auto _limit_impl(const std::false_type&, Arg arg) const -> bad_statement;
|
||||||
{
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), limit_data_t<Arg>{arg} };
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
template <typename Arg>
|
||||||
};
|
auto _limit_impl(const std::true_type&, Arg arg) const -> _new_statement_t<std::true_type, limit_t<Arg>>
|
||||||
|
{
|
||||||
|
return {static_cast<const derived_statement_t<Policies>&>(*this), limit_data_t<Arg>{arg}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// Interpreters
|
// Interpreters
|
||||||
template<typename Context, typename Database>
|
template <typename Context, typename Database>
|
||||||
struct serializer_t<Context, dynamic_limit_data_t<Database>>
|
struct serializer_t<Context, dynamic_limit_data_t<Database>>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = dynamic_limit_data_t<Database>;
|
using T = dynamic_limit_data_t<Database>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if (t._initialized)
|
if (t._initialized)
|
||||||
{
|
{
|
||||||
context << " LIMIT ";
|
context << " LIMIT ";
|
||||||
serialize(t._value, context);
|
serialize(t._value, context);
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Limit>
|
template <typename Context, typename Limit>
|
||||||
struct serializer_t<Context, limit_data_t<Limit>>
|
struct serializer_t<Context, limit_data_t<Limit>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Limit>;
|
using _serialize_check = serialize_check_of<Context, Limit>;
|
||||||
using T = limit_data_t<Limit>;
|
using T = limit_data_t<Limit>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << " LIMIT ";
|
context << " LIMIT ";
|
||||||
serialize_operand(t._value, context);
|
serialize_operand(t._value, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -27,56 +27,49 @@
|
|||||||
#ifndef SQLPP_DETAIL_LOGIC_H
|
#ifndef SQLPP_DETAIL_LOGIC_H
|
||||||
#define SQLPP_DETAIL_LOGIC_H
|
#define SQLPP_DETAIL_LOGIC_H
|
||||||
|
|
||||||
#include <ciso646> // Required for some compilers to use aliases for boolean operators
|
#include <ciso646> // Required for some compilers to use aliases for boolean operators
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace logic
|
namespace logic
|
||||||
{
|
{
|
||||||
template<bool... B>
|
template <bool... B>
|
||||||
struct logic_helper;
|
struct logic_helper;
|
||||||
|
|
||||||
// see http://lists.boost.org/Archives/boost/2014/05/212946.php :-)
|
// see http://lists.boost.org/Archives/boost/2014/05/212946.php :-)
|
||||||
template<bool... B>
|
template <bool... B>
|
||||||
using all_t = std::integral_constant<
|
using all_t = std::integral_constant<bool, std::is_same<logic_helper<B...>, logic_helper<(true or B)...>>::value>;
|
||||||
bool,
|
|
||||||
std::is_same<logic_helper<B...>, logic_helper<(true or B)...>>::value>;
|
|
||||||
|
|
||||||
template<bool... B>
|
template <bool... B>
|
||||||
using any_t = std::integral_constant<
|
using any_t =
|
||||||
bool,
|
std::integral_constant<bool, not std::is_same<logic_helper<B...>, logic_helper<(false and B)...>>::value>;
|
||||||
not std::is_same<logic_helper<B...>, logic_helper<(false and B)...>>::value>;
|
|
||||||
|
|
||||||
template<bool... B>
|
template <bool... B>
|
||||||
using none_t = std::integral_constant<
|
using none_t =
|
||||||
bool,
|
std::integral_constant<bool, std::is_same<logic_helper<B...>, logic_helper<(false and B)...>>::value>;
|
||||||
std::is_same<logic_helper<B...>, logic_helper<(false and B)...>>::value>;
|
|
||||||
|
|
||||||
template<bool>
|
template <bool>
|
||||||
struct not_impl;
|
struct not_impl;
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
struct not_impl<true>
|
struct not_impl<true>
|
||||||
{
|
{
|
||||||
using type = std::false_type;
|
using type = std::false_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template <>
|
||||||
struct not_impl<false>
|
struct not_impl<false>
|
||||||
{
|
{
|
||||||
using type = std::true_type;
|
using type = std::true_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <template <typename> class Predicate, typename... T>
|
||||||
|
using not_t = typename not_impl<Predicate<T>::value...>::type;
|
||||||
|
|
||||||
template<template<typename> class Predicate, typename... T>
|
template <typename T>
|
||||||
using not_t = typename not_impl<Predicate<T>::value...>::type;
|
using identity_t = T;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
using identity_t = T;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,68 +32,72 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct max_alias_t
|
struct max_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "max_";
|
static constexpr const char _literal[] = "max_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T max;
|
T max;
|
||||||
T& operator()() { return max; }
|
T& operator()()
|
||||||
const T& operator()() const { return max; }
|
{
|
||||||
};
|
return max;
|
||||||
};
|
}
|
||||||
};
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Expr>
|
template <typename Expr>
|
||||||
struct max_t:
|
struct max_t : public expression_operators<max_t<Expr>, value_type_of<Expr>>, public alias_operators<max_t<Expr>>
|
||||||
public expression_operators<max_t<Expr>, value_type_of<Expr>>,
|
{
|
||||||
public alias_operators<max_t<Expr>>
|
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
|
||||||
{
|
using _nodes = detail::type_vector<Expr, aggregate_function>;
|
||||||
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
|
|
||||||
using _nodes = detail::type_vector<Expr, aggregate_function>;
|
|
||||||
|
|
||||||
using _auto_alias_t = max_alias_t;
|
using _auto_alias_t = max_alias_t;
|
||||||
|
|
||||||
max_t(Expr expr):
|
max_t(Expr expr) : _expr(expr)
|
||||||
_expr(expr)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
max_t(const max_t&) = default;
|
max_t(const max_t&) = default;
|
||||||
max_t(max_t&&) = default;
|
max_t(max_t&&) = default;
|
||||||
max_t& operator=(const max_t&) = default;
|
max_t& operator=(const max_t&) = default;
|
||||||
max_t& operator=(max_t&&) = default;
|
max_t& operator=(max_t&&) = default;
|
||||||
~max_t() = default;
|
~max_t() = default;
|
||||||
|
|
||||||
Expr _expr;
|
Expr _expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Expr>
|
template <typename Context, typename Expr>
|
||||||
struct serializer_t<Context, max_t<Expr>>
|
struct serializer_t<Context, max_t<Expr>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Expr>;
|
using _serialize_check = serialize_check_of<Context, Expr>;
|
||||||
using T = max_t<Expr>;
|
using T = max_t<Expr>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "MAX(";
|
context << "MAX(";
|
||||||
serialize(t._expr, context);
|
serialize(t._expr, context);
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto max(T t) -> max_t<wrap_operand_t<T>>
|
|
||||||
{
|
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "max() cannot be used on an aggregate function");
|
|
||||||
static_assert(is_expression_t<wrap_operand_t<T>>::value, "max() requires an expression as argument");
|
|
||||||
return { t };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto max(T t) -> max_t<wrap_operand_t<T>>
|
||||||
|
{
|
||||||
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
|
"max() cannot be used on an aggregate function");
|
||||||
|
static_assert(is_expression_t<wrap_operand_t<T>>::value, "max() requires an expression as argument");
|
||||||
|
return {t};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,68 +32,72 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct min_alias_t
|
struct min_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "min_";
|
static constexpr const char _literal[] = "min_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T min;
|
T min;
|
||||||
T& operator()() { return min; }
|
T& operator()()
|
||||||
const T& operator()() const { return min; }
|
{
|
||||||
};
|
return min;
|
||||||
};
|
}
|
||||||
};
|
const T& operator()() const
|
||||||
|
{
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Expr>
|
template <typename Expr>
|
||||||
struct min_t:
|
struct min_t : public expression_operators<min_t<Expr>, value_type_of<Expr>>, public alias_operators<min_t<Expr>>
|
||||||
public expression_operators<min_t<Expr>, value_type_of<Expr>>,
|
{
|
||||||
public alias_operators<min_t<Expr>>
|
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
|
||||||
{
|
using _nodes = detail::type_vector<Expr, aggregate_function>;
|
||||||
using _traits = make_traits<value_type_of<Expr>, tag::is_expression, tag::is_selectable>;
|
|
||||||
using _nodes = detail::type_vector<Expr, aggregate_function>;
|
|
||||||
|
|
||||||
using _auto_alias_t = min_alias_t;
|
using _auto_alias_t = min_alias_t;
|
||||||
|
|
||||||
min_t(Expr expr):
|
min_t(Expr expr) : _expr(expr)
|
||||||
_expr(expr)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
min_t(const min_t&) = default;
|
min_t(const min_t&) = default;
|
||||||
min_t(min_t&&) = default;
|
min_t(min_t&&) = default;
|
||||||
min_t& operator=(const min_t&) = default;
|
min_t& operator=(const min_t&) = default;
|
||||||
min_t& operator=(min_t&&) = default;
|
min_t& operator=(min_t&&) = default;
|
||||||
~min_t() = default;
|
~min_t() = default;
|
||||||
|
|
||||||
Expr _expr;
|
Expr _expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Expr>
|
template <typename Context, typename Expr>
|
||||||
struct serializer_t<Context, min_t<Expr>>
|
struct serializer_t<Context, min_t<Expr>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Expr>;
|
using _serialize_check = serialize_check_of<Context, Expr>;
|
||||||
using T = min_t<Expr>;
|
using T = min_t<Expr>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << "MIN(";
|
context << "MIN(";
|
||||||
serialize(t._expr, context);
|
serialize(t._expr, context);
|
||||||
context << ")";
|
context << ")";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
auto min(T t) -> min_t<wrap_operand_t<T>>
|
|
||||||
{
|
|
||||||
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value, "min() cannot be used on an aggregate function");
|
|
||||||
static_assert(is_expression_t<wrap_operand_t<T>>::value, "min() requires an expression as argument");
|
|
||||||
return { t };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
auto min(T t) -> min_t<wrap_operand_t<T>>
|
||||||
|
{
|
||||||
|
static_assert(not contains_aggregate_function_t<wrap_operand_t<T>>::value,
|
||||||
|
"min() cannot be used on an aggregate function");
|
||||||
|
static_assert(is_expression_t<wrap_operand_t<T>>::value, "min() requires an expression as argument");
|
||||||
|
return {t};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,112 +35,110 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename AliasProvider, typename... Columns>
|
template <typename AliasProvider, typename... Columns>
|
||||||
struct multi_column_alias_t;
|
struct multi_column_alias_t;
|
||||||
|
|
||||||
template<typename Unused, typename... Columns>
|
template <typename Unused, typename... Columns>
|
||||||
struct multi_column_t
|
struct multi_column_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t>;
|
using _traits = make_traits<no_value_t>;
|
||||||
using _nodes = detail::type_vector<Columns...>;
|
using _nodes = detail::type_vector<Columns...>;
|
||||||
|
|
||||||
static_assert(logic::all_t<is_selectable_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
|
static_assert(logic::all_t<is_selectable_t<Columns>::value...>::value,
|
||||||
|
"multi_column parameters need to be named expressions");
|
||||||
|
|
||||||
multi_column_t(std::tuple<Columns...> columns):
|
multi_column_t(std::tuple<Columns...> columns) : _columns(columns)
|
||||||
_columns(columns)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
multi_column_t(Columns... columns):
|
multi_column_t(Columns... columns) : _columns(columns...)
|
||||||
_columns(columns...)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
multi_column_t(const multi_column_t&) = default;
|
multi_column_t(const multi_column_t&) = default;
|
||||||
multi_column_t(multi_column_t&&) = default;
|
multi_column_t(multi_column_t&&) = default;
|
||||||
multi_column_t& operator=(const multi_column_t&) = default;
|
multi_column_t& operator=(const multi_column_t&) = default;
|
||||||
multi_column_t& operator=(multi_column_t&&) = default;
|
multi_column_t& operator=(multi_column_t&&) = default;
|
||||||
~multi_column_t() = default;
|
~multi_column_t() = default;
|
||||||
|
|
||||||
template<typename AliasProvider>
|
template <typename AliasProvider>
|
||||||
multi_column_alias_t<AliasProvider, Columns...> as(const AliasProvider&)
|
multi_column_alias_t<AliasProvider, Columns...> as(const AliasProvider&)
|
||||||
{
|
{
|
||||||
return { *this };
|
return {*this};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<Columns...> _columns;
|
std::tuple<Columns...> _columns;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename AliasProvider, typename... Columns>
|
template <typename AliasProvider, typename... Columns>
|
||||||
struct multi_column_alias_t
|
struct multi_column_alias_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_multi_column, tag::is_selectable>;
|
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_multi_column, tag::is_selectable>;
|
||||||
using _nodes = detail::type_vector<Columns...>;
|
using _nodes = detail::type_vector<Columns...>;
|
||||||
|
|
||||||
static_assert(logic::all_t<is_selectable_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
|
static_assert(logic::all_t<is_selectable_t<Columns>::value...>::value,
|
||||||
|
"multi_column parameters need to be named expressions");
|
||||||
|
|
||||||
using _alias_t = typename AliasProvider::_alias_t;
|
using _alias_t = typename AliasProvider::_alias_t;
|
||||||
|
|
||||||
multi_column_alias_t(multi_column_t<void, Columns...> multi_column):
|
multi_column_alias_t(multi_column_t<void, Columns...> multi_column) : _columns(multi_column._columns)
|
||||||
_columns(multi_column._columns)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
multi_column_alias_t(std::tuple<Columns...> columns):
|
multi_column_alias_t(std::tuple<Columns...> columns) : _columns(columns)
|
||||||
_columns(columns)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
multi_column_alias_t(Columns... columns):
|
multi_column_alias_t(Columns... columns) : _columns(columns...)
|
||||||
_columns(columns...)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
multi_column_alias_t(const multi_column_alias_t&) = default;
|
multi_column_alias_t(const multi_column_alias_t&) = default;
|
||||||
multi_column_alias_t(multi_column_alias_t&&) = default;
|
multi_column_alias_t(multi_column_alias_t&&) = default;
|
||||||
multi_column_alias_t& operator=(const multi_column_alias_t&) = default;
|
multi_column_alias_t& operator=(const multi_column_alias_t&) = default;
|
||||||
multi_column_alias_t& operator=(multi_column_alias_t&&) = default;
|
multi_column_alias_t& operator=(multi_column_alias_t&&) = default;
|
||||||
~multi_column_alias_t() = default;
|
~multi_column_alias_t() = default;
|
||||||
|
|
||||||
std::tuple<Columns...> _columns;
|
std::tuple<Columns...> _columns;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename... Columns>
|
template <typename Context, typename... Columns>
|
||||||
struct serializer_t<Context, multi_column_t<void, Columns...>>
|
struct serializer_t<Context, multi_column_t<void, Columns...>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Columns...>;
|
using _serialize_check = serialize_check_of<Context, Columns...>;
|
||||||
using T = multi_column_t<void, Columns...>;
|
using T = multi_column_t<void, Columns...>;
|
||||||
|
|
||||||
static void _(const T&, Context&)
|
static void _(const T&, Context&)
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<serializer_t>::value, "multi_column must be used with an alias");
|
static_assert(wrong_t<serializer_t>::value, "multi_column must be used with an alias");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename AliasProvider, typename... Columns>
|
template <typename Context, typename AliasProvider, typename... Columns>
|
||||||
struct serializer_t<Context, multi_column_alias_t<AliasProvider, Columns...>>
|
struct serializer_t<Context, multi_column_alias_t<AliasProvider, Columns...>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Columns...>;
|
using _serialize_check = serialize_check_of<Context, Columns...>;
|
||||||
using T = multi_column_alias_t<AliasProvider, Columns...>;
|
using T = multi_column_alias_t<AliasProvider, Columns...>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
interpret_tuple(t._columns, ',', context);
|
interpret_tuple(t._columns, ',', context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template<typename... Columns>
|
|
||||||
using make_multi_column_t =
|
|
||||||
copy_tuple_args_t<multi_column_t, void,
|
|
||||||
decltype(column_tuple_merge(std::declval<Columns>()...))>;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Columns>
|
|
||||||
auto multi_column(Columns... columns)
|
|
||||||
-> detail::make_multi_column_t<Columns...>
|
|
||||||
{
|
|
||||||
return detail::make_multi_column_t<Columns...>(std::tuple_cat(detail::as_column_tuple<Columns>::_(columns)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <typename... Columns>
|
||||||
|
using make_multi_column_t =
|
||||||
|
copy_tuple_args_t<multi_column_t, void, decltype(column_tuple_merge(std::declval<Columns>()...))>;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Columns>
|
||||||
|
auto multi_column(Columns... columns) -> detail::make_multi_column_t<Columns...>
|
||||||
|
{
|
||||||
|
return detail::make_multi_column_t<Columns...>(std::tuple_cat(detail::as_column_tuple<Columns>::_(columns)...));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,117 +34,117 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
struct named_interpretable_t
|
struct named_interpretable_t
|
||||||
{
|
{
|
||||||
using _serializer_context_t = typename Db::_serializer_context_t;
|
using _serializer_context_t = typename Db::_serializer_context_t;
|
||||||
using _interpreter_context_t = typename Db::_interpreter_context_t;
|
using _interpreter_context_t = typename Db::_interpreter_context_t;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
named_interpretable_t(T t):
|
named_interpretable_t(T t)
|
||||||
_requires_braces(requires_braces_t<T>::value),
|
: _requires_braces(requires_braces_t<T>::value), _impl(std::make_shared<_impl_t<T>>(t))
|
||||||
_impl(std::make_shared<_impl_t<T>>(t))
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
named_interpretable_t(const named_interpretable_t&) = default;
|
named_interpretable_t(const named_interpretable_t&) = default;
|
||||||
named_interpretable_t(named_interpretable_t&&) = default;
|
named_interpretable_t(named_interpretable_t&&) = default;
|
||||||
named_interpretable_t& operator=(const named_interpretable_t&) = default;
|
named_interpretable_t& operator=(const named_interpretable_t&) = default;
|
||||||
named_interpretable_t& operator=(named_interpretable_t&&) = default;
|
named_interpretable_t& operator=(named_interpretable_t&&) = default;
|
||||||
~named_interpretable_t() = default;
|
~named_interpretable_t() = default;
|
||||||
|
|
||||||
serializer_context_t& serialize(serializer_context_t& context) const
|
serializer_context_t& serialize(serializer_context_t& context) const
|
||||||
{
|
{
|
||||||
return _impl->serialize(context);
|
return _impl->serialize(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method only exists if Db::_serializer_context_t and serializer_context_t are not the same
|
// This method only exists if Db::_serializer_context_t and serializer_context_t are not the same
|
||||||
template<typename Context>
|
template <typename Context>
|
||||||
auto serialize(Context& context) const
|
auto serialize(Context& context) const ->
|
||||||
-> typename std::enable_if<std::is_same<Context, _serializer_context_t>::value
|
typename std::enable_if<std::is_same<Context, _serializer_context_t>::value and
|
||||||
and not std::is_same<Context, serializer_context_t>::value, Context&>::type
|
not std::is_same<Context, serializer_context_t>::value,
|
||||||
{
|
Context&>::type
|
||||||
return _impl->db_serialize(context);
|
{
|
||||||
}
|
return _impl->db_serialize(context);
|
||||||
|
}
|
||||||
|
|
||||||
_interpreter_context_t& interpret(_interpreter_context_t& context) const
|
_interpreter_context_t& interpret(_interpreter_context_t& context) const
|
||||||
{
|
{
|
||||||
return _impl->interpret(context);
|
return _impl->interpret(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string _get_name() const
|
std::string _get_name() const
|
||||||
{
|
{
|
||||||
return _impl->_get_name();
|
return _impl->_get_name();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _requires_braces;
|
bool _requires_braces;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct _impl_base
|
struct _impl_base
|
||||||
{
|
{
|
||||||
virtual serializer_context_t& serialize(serializer_context_t& context) const = 0;
|
virtual serializer_context_t& serialize(serializer_context_t& context) const = 0;
|
||||||
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
|
virtual _serializer_context_t& db_serialize(_serializer_context_t& context) const = 0;
|
||||||
virtual _interpreter_context_t& interpret(_interpreter_context_t& context) const = 0;
|
virtual _interpreter_context_t& interpret(_interpreter_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>::size::value, "parameters not supported in dynamic statement parts");
|
static_assert(not make_parameter_list_t<T>::size::value, "parameters not supported in dynamic statement parts");
|
||||||
_impl_t(T t):
|
_impl_t(T t) : _t(t)
|
||||||
_t(t)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
serializer_context_t& serialize(serializer_context_t& context) const
|
serializer_context_t& serialize(serializer_context_t& context) const
|
||||||
{
|
{
|
||||||
::sqlpp::serialize(_t, context);
|
::sqlpp::serialize(_t, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
_serializer_context_t& db_serialize(_serializer_context_t& context) const
|
_serializer_context_t& db_serialize(_serializer_context_t& context) const
|
||||||
{
|
{
|
||||||
Db::_serialize_interpretable(_t, context);
|
Db::_serialize_interpretable(_t, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
_interpreter_context_t& interpret(_interpreter_context_t& context) const
|
_interpreter_context_t& interpret(_interpreter_context_t& context) const
|
||||||
{
|
{
|
||||||
Db::_interpret_interpretable(_t, context);
|
Db::_interpret_interpretable(_t, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string _get_name() const
|
std::string _get_name() const
|
||||||
{
|
{
|
||||||
return name_of<T>::char_ptr();
|
return name_of<T>::char_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
T _t;
|
T _t;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<const _impl_base> _impl;
|
std::shared_ptr<const _impl_base> _impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Database>
|
template <typename Context, typename Database>
|
||||||
struct serializer_t<Context, named_interpretable_t<Database>>
|
struct serializer_t<Context, named_interpretable_t<Database>>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = named_interpretable_t<Database>;
|
using T = named_interpretable_t<Database>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if (t._requires_braces)
|
if (t._requires_braces)
|
||||||
{
|
{
|
||||||
context << '(';
|
context << '(';
|
||||||
t.serialize(context);
|
t.serialize(context);
|
||||||
context << ')';
|
context << ')';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
t.serialize(context);
|
t.serialize(context);
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,18 +32,20 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct no_data_t {};
|
struct no_data_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Context>
|
template <typename Context>
|
||||||
struct serializer_t<Context, no_data_t>
|
struct serializer_t<Context, no_data_t>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = no_data_t;
|
using T = no_data_t;
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
static Context& _(const T&, Context& context)
|
||||||
{
|
{
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,20 +32,19 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct no_value_t
|
struct no_value_t
|
||||||
{
|
{
|
||||||
using _tag = void;
|
using _tag = void;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Base>
|
template <typename Base>
|
||||||
struct expression_operators<Base, no_value_t>
|
struct expression_operators<Base, no_value_t>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Base>
|
|
||||||
struct column_operators<Base, no_value_t>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template <typename Base>
|
||||||
|
struct column_operators<Base, no_value_t>
|
||||||
|
{
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,67 +34,68 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct noop
|
struct noop
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
struct _alias_t {};
|
struct _alias_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Statement>
|
template <typename Statement>
|
||||||
struct _result_methods_t
|
struct _result_methods_t
|
||||||
{
|
{
|
||||||
using _statement_t = Statement;
|
using _statement_t = Statement;
|
||||||
|
|
||||||
const _statement_t& _get_statement() const
|
const _statement_t& _get_statement() const
|
||||||
{
|
{
|
||||||
return static_cast<const _statement_t&>(*this);
|
return static_cast<const _statement_t&>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
template<typename Db, typename Composite>
|
template <typename Db, typename Composite>
|
||||||
auto _run(Db& db, const Composite& composite) const -> size_t
|
auto _run(Db& db, const Composite& composite) const -> size_t
|
||||||
{
|
{
|
||||||
return db.execute(composite);
|
return db.execute(composite);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
auto _run(Db& db) const -> size_t
|
auto _run(Db& db) const -> size_t
|
||||||
{
|
{
|
||||||
return db.execute(_get_statement());
|
return db.execute(_get_statement());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
template<typename Db, typename Composite>
|
template <typename Db, typename Composite>
|
||||||
auto _prepare(Db& db, const Composite& composite) const
|
auto _prepare(Db& db, const Composite& composite) const -> prepared_execute_t<Db, Composite>
|
||||||
-> prepared_execute_t<Db, Composite>
|
{
|
||||||
{
|
return {{}, db.prepare_execute(composite)};
|
||||||
return {{}, db.prepare_execute(composite)};
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
auto _prepare(Db& db) const
|
auto _prepare(Db& db) const -> prepared_execute_t<Db, _statement_t>
|
||||||
-> prepared_execute_t<Db, _statement_t>
|
{
|
||||||
{
|
return {{}, db.prepare_execute(_get_statement())};
|
||||||
return {{}, db.prepare_execute(_get_statement())};
|
}
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Context>
|
template <typename Context>
|
||||||
struct serializer_t<Context, noop>
|
struct serializer_t<Context, noop>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = noop;
|
using T = noop;
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
static Context& _(const T&, Context& context)
|
||||||
{
|
{
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
struct is_noop: std::is_same<T, noop> {};
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct is_noop : std::is_same<T, noop>
|
||||||
|
{
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -29,9 +29,9 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct noop;
|
struct noop;
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct is_noop;
|
struct is_noop;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,94 +35,90 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct not_in_alias_t
|
struct not_in_alias_t
|
||||||
{
|
{
|
||||||
struct _alias_t
|
struct _alias_t
|
||||||
{
|
{
|
||||||
static constexpr const char _literal[] = "not_in_";
|
static constexpr const char _literal[] = "not_in_";
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>;
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct _member_t
|
struct _member_t
|
||||||
{
|
{
|
||||||
T in;
|
T in;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Operand, typename... Args>
|
template <typename Operand, typename... Args>
|
||||||
struct not_in_t:
|
struct not_in_t : public expression_operators<not_in_t<Operand, Args...>, boolean>,
|
||||||
public expression_operators<not_in_t<Operand, Args...>, boolean>,
|
public alias_operators<not_in_t<Operand, Args...>>
|
||||||
public alias_operators<not_in_t<Operand, Args...>>
|
{
|
||||||
{
|
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
||||||
using _traits = make_traits<boolean, tag::is_expression, tag::is_selectable>;
|
using _nodes = detail::type_vector<Operand, Args...>;
|
||||||
using _nodes = detail::type_vector<Operand, Args...>;
|
|
||||||
|
|
||||||
static_assert(sizeof...(Args) > 0, "not_in() requires at least one argument");
|
static_assert(sizeof...(Args) > 0, "not_in() requires at least one argument");
|
||||||
|
|
||||||
using _auto_alias_t = not_in_alias_t;
|
using _auto_alias_t = not_in_alias_t;
|
||||||
|
|
||||||
not_in_t(Operand operand, Args... args):
|
not_in_t(Operand operand, Args... args) : _operand(operand), _args(args...)
|
||||||
_operand(operand),
|
{
|
||||||
_args(args...)
|
}
|
||||||
{}
|
|
||||||
|
|
||||||
not_in_t(const not_in_t&) = default;
|
not_in_t(const not_in_t&) = default;
|
||||||
not_in_t(not_in_t&&) = default;
|
not_in_t(not_in_t&&) = default;
|
||||||
not_in_t& operator=(const not_in_t&) = default;
|
not_in_t& operator=(const not_in_t&) = default;
|
||||||
not_in_t& operator=(not_in_t&&) = default;
|
not_in_t& operator=(not_in_t&&) = default;
|
||||||
~not_in_t() = default;
|
~not_in_t() = default;
|
||||||
|
|
||||||
Operand _operand;
|
Operand _operand;
|
||||||
std::tuple<Args...> _args;
|
std::tuple<Args...> _args;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Operand, typename... Args>
|
template <typename Context, typename Operand, typename... Args>
|
||||||
struct serializer_t<Context, not_in_t<Operand, Args...>>
|
struct serializer_t<Context, not_in_t<Operand, Args...>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Args...>;
|
using _serialize_check = serialize_check_of<Context, Args...>;
|
||||||
using T = not_in_t<Operand, Args...>;
|
using T = not_in_t<Operand, Args...>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
serialize_operand(t._operand, context);
|
serialize_operand(t._operand, context);
|
||||||
context << " NOT IN(";
|
context << " NOT IN(";
|
||||||
if (sizeof...(Args) == 1)
|
if (sizeof...(Args) == 1)
|
||||||
serialize(std::get<0>(t._args), context);
|
serialize(std::get<0>(t._args), context);
|
||||||
else
|
else
|
||||||
interpret_tuple(t._args, ',', context);
|
interpret_tuple(t._args, ',', context);
|
||||||
context << ')';
|
context << ')';
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Container>
|
template <typename Container>
|
||||||
struct value_list_t;
|
struct value_list_t;
|
||||||
|
|
||||||
template<typename Context, typename Operand, typename Container>
|
|
||||||
struct serializer_t<Context, not_in_t<Operand, value_list_t<Container>>>
|
|
||||||
{
|
|
||||||
using _serialize_check = serialize_check_of<Context, value_list_t<Container>>;
|
|
||||||
using T = not_in_t<Operand, value_list_t<Container>>;
|
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
const auto& value_list = std::get<0>(t._args);
|
|
||||||
if (value_list._container.empty())
|
|
||||||
{
|
|
||||||
context << " 'operand not in empty list' != 'false' ";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
serialize(t._operand, context);
|
|
||||||
context << " NOT IN(";
|
|
||||||
serialize(value_list, context);
|
|
||||||
context << ')';
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template <typename Context, typename Operand, typename Container>
|
||||||
|
struct serializer_t<Context, not_in_t<Operand, value_list_t<Container>>>
|
||||||
|
{
|
||||||
|
using _serialize_check = serialize_check_of<Context, value_list_t<Container>>;
|
||||||
|
using T = not_in_t<Operand, value_list_t<Container>>;
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
const auto& value_list = std::get<0>(t._args);
|
||||||
|
if (value_list._container.empty())
|
||||||
|
{
|
||||||
|
context << " 'operand not in empty list' != 'false' ";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
serialize(t._operand, context);
|
||||||
|
context << " NOT IN(";
|
||||||
|
serialize(value_list, context);
|
||||||
|
context << ')';
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,27 +31,26 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct null_t
|
struct null_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_expression, tag::is_sql_null>;
|
using _traits = make_traits<no_value_t, tag::is_expression, tag::is_sql_null>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context>
|
template <typename Context>
|
||||||
struct serializer_t<Context, null_t>
|
struct serializer_t<Context, null_t>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using Operand = null_t;
|
using Operand = null_t;
|
||||||
|
|
||||||
static Context& _(const Operand&, Context& context)
|
static Context& _(const Operand&, Context& context)
|
||||||
{
|
{
|
||||||
context << "NULL";
|
context << "NULL";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr null_t null = {};
|
|
||||||
|
|
||||||
|
constexpr null_t null = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,249 +33,262 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// OFFSET DATA
|
// OFFSET DATA
|
||||||
template<typename Offset>
|
template <typename Offset>
|
||||||
struct offset_data_t
|
struct offset_data_t
|
||||||
{
|
{
|
||||||
offset_data_t(Offset value):
|
offset_data_t(Offset value) : _value(value)
|
||||||
_value(value)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
offset_data_t(const offset_data_t&) = default;
|
offset_data_t(const offset_data_t&) = default;
|
||||||
offset_data_t(offset_data_t&&) = default;
|
offset_data_t(offset_data_t&&) = default;
|
||||||
offset_data_t& operator=(const offset_data_t&) = default;
|
offset_data_t& operator=(const offset_data_t&) = default;
|
||||||
offset_data_t& operator=(offset_data_t&&) = default;
|
offset_data_t& operator=(offset_data_t&&) = default;
|
||||||
~offset_data_t() = default;
|
~offset_data_t() = default;
|
||||||
|
|
||||||
Offset _value;
|
Offset _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// OFFSET
|
// OFFSET
|
||||||
template<typename Offset>
|
template <typename Offset>
|
||||||
struct offset_t
|
struct offset_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_offset>;
|
using _traits = make_traits<no_value_t, tag::is_offset>;
|
||||||
using _nodes = detail::type_vector<Offset>;
|
using _nodes = detail::type_vector<Offset>;
|
||||||
|
|
||||||
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
|
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = offset_data_t<Offset>;
|
using _data_t = offset_data_t<Offset>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
_data_t _data;
|
_data_t _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Base template to be inherited by the statement
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _base_t
|
||||||
{
|
{
|
||||||
using _data_t = offset_data_t<Offset>;
|
using _data_t = offset_data_t<Offset>;
|
||||||
|
|
||||||
_impl_t<Policies> offset;
|
_impl_t<Policies> offset;
|
||||||
_impl_t<Policies>& operator()() { return offset; }
|
_impl_t<Policies>& operator()()
|
||||||
const _impl_t<Policies>& operator()() const { return offset; }
|
{
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template <typename T>
|
||||||
static auto _get_member(T t) -> decltype(t.offset)
|
static auto _get_member(T t) -> decltype(t.offset)
|
||||||
{
|
{
|
||||||
return t.offset;
|
return t.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
using _consistency_check = consistent_t;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// DYNAMIC OFFSET DATA
|
// DYNAMIC OFFSET DATA
|
||||||
template<typename Database>
|
template <typename Database>
|
||||||
struct dynamic_offset_data_t
|
struct dynamic_offset_data_t
|
||||||
{
|
{
|
||||||
dynamic_offset_data_t():
|
dynamic_offset_data_t() : _value(noop())
|
||||||
_value(noop())
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Offset>
|
template <typename Offset>
|
||||||
dynamic_offset_data_t(Offset value):
|
dynamic_offset_data_t(Offset value)
|
||||||
_initialized(true),
|
: _initialized(true), _value(wrap_operand_t<Offset>(value))
|
||||||
_value(wrap_operand_t<Offset>(value))
|
{
|
||||||
{
|
}
|
||||||
}
|
|
||||||
|
|
||||||
dynamic_offset_data_t(const dynamic_offset_data_t&) = default;
|
dynamic_offset_data_t(const dynamic_offset_data_t&) = default;
|
||||||
dynamic_offset_data_t(dynamic_offset_data_t&&) = default;
|
dynamic_offset_data_t(dynamic_offset_data_t&&) = default;
|
||||||
dynamic_offset_data_t& operator=(const dynamic_offset_data_t&) = default;
|
dynamic_offset_data_t& operator=(const dynamic_offset_data_t&) = default;
|
||||||
dynamic_offset_data_t& operator=(dynamic_offset_data_t&&) = default;
|
dynamic_offset_data_t& operator=(dynamic_offset_data_t&&) = default;
|
||||||
~dynamic_offset_data_t() = default;
|
~dynamic_offset_data_t() = default;
|
||||||
|
|
||||||
bool _initialized = false;
|
bool _initialized = false;
|
||||||
interpretable_t<Database> _value;
|
interpretable_t<Database> _value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// DYNAMIC OFFSET
|
// DYNAMIC OFFSET
|
||||||
template<typename Database>
|
template <typename Database>
|
||||||
struct dynamic_offset_t
|
struct dynamic_offset_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_offset>;
|
using _traits = make_traits<no_value_t, tag::is_offset>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = dynamic_offset_data_t<Database>;
|
using _data_t = dynamic_offset_data_t<Database>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template <typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
template<typename Offset>
|
template <typename Offset>
|
||||||
void set(Offset value)
|
void set(Offset value)
|
||||||
{
|
{
|
||||||
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
|
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
|
||||||
using arg_t = wrap_operand_t<Offset>;
|
using arg_t = wrap_operand_t<Offset>;
|
||||||
static_assert(is_integral_t<arg_t>::value, "offset requires an integral value or integral parameter");
|
static_assert(is_integral_t<arg_t>::value, "offset requires an integral value or integral parameter");
|
||||||
_data._value = arg_t{value};
|
_data._value = arg_t{value};
|
||||||
_data._initialized = true;
|
_data._initialized = true;
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
_data_t _data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
public:
|
||||||
template<typename Policies>
|
_data_t _data;
|
||||||
struct _base_t
|
};
|
||||||
{
|
|
||||||
using _data_t = dynamic_offset_data_t<Database>;
|
|
||||||
|
|
||||||
_impl_t<Policies> offset;
|
// Base template to be inherited by the statement
|
||||||
_impl_t<Policies>& operator()() { return offset; }
|
template <typename Policies>
|
||||||
const _impl_t<Policies>& operator()() const { return offset; }
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = dynamic_offset_data_t<Database>;
|
||||||
|
|
||||||
template<typename T>
|
_impl_t<Policies> offset;
|
||||||
static auto _get_member(T t) -> decltype(t.offset)
|
_impl_t<Policies>& operator()()
|
||||||
{
|
{
|
||||||
return t.offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
template <typename T>
|
||||||
|
static auto _get_member(T t) -> decltype(t.offset)
|
||||||
|
{
|
||||||
|
return t.offset;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Offset>
|
using _consistency_check = consistent_t;
|
||||||
void set_offset(Offset value)
|
|
||||||
{
|
|
||||||
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
|
|
||||||
using arg_t = wrap_operand_t<Offset>;
|
|
||||||
static_cast<derived_statement_t<Policies>*>(this)->_offset()._value = arg_t{value};
|
|
||||||
static_cast<derived_statement_t<Policies>*>(this)->_offset()._initialized = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
bool _initialized = false;
|
template <typename Offset>
|
||||||
interpretable_t<Database> _value;
|
void set_offset(Offset value)
|
||||||
};
|
{
|
||||||
|
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
|
||||||
|
using arg_t = wrap_operand_t<Offset>;
|
||||||
|
static_cast<derived_statement_t<Policies>*>(this)->_offset()._value = arg_t{value};
|
||||||
|
static_cast<derived_statement_t<Policies>*>(this)->_offset()._initialized = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct no_offset_t
|
bool _initialized = false;
|
||||||
{
|
interpretable_t<Database> _value;
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
};
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
|
|
||||||
// Data
|
struct no_offset_t
|
||||||
using _data_t = no_data_t;
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Data
|
||||||
template<typename Policies>
|
using _data_t = no_data_t;
|
||||||
struct _impl_t
|
|
||||||
{
|
|
||||||
_data_t _data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Member implementation with data and methods
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
using _data_t = no_data_t;
|
_data_t _data;
|
||||||
|
};
|
||||||
|
|
||||||
_impl_t<Policies> no_offset;
|
// Base template to be inherited by the statement
|
||||||
_impl_t<Policies>& operator()() { return no_offset; }
|
template <typename Policies>
|
||||||
const _impl_t<Policies>& operator()() const { return no_offset; }
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
template<typename T>
|
_impl_t<Policies> no_offset;
|
||||||
static auto _get_member(T t) -> decltype(t.no_offset)
|
_impl_t<Policies>& operator()()
|
||||||
{
|
{
|
||||||
return t.no_offset;
|
return no_offset;
|
||||||
}
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return no_offset;
|
||||||
|
}
|
||||||
|
|
||||||
using _database_t = typename Policies::_database_t;
|
template <typename T>
|
||||||
|
static auto _get_member(T t) -> decltype(t.no_offset)
|
||||||
|
{
|
||||||
|
return t.no_offset;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
using _database_t = typename Policies::_database_t;
|
||||||
using _check = is_integral_t<wrap_operand_t<T>>;
|
|
||||||
|
|
||||||
template<typename Check, typename T>
|
template <typename T>
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_offset_t, T>;
|
using _check = is_integral_t<wrap_operand_t<T>>;
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
template <typename Check, typename T>
|
||||||
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_offset_t, T>;
|
||||||
|
|
||||||
template<typename Arg>
|
using _consistency_check = consistent_t;
|
||||||
auto offset(Arg arg) const
|
|
||||||
-> _new_statement_t<_check<Arg>, offset_t<wrap_operand_t<Arg>>>
|
|
||||||
{
|
|
||||||
static_assert(_check<Arg>::value, "offset requires an integral value or integral parameter");
|
|
||||||
return _offset_impl(_check<Arg>{}, wrap_operand_t<Arg>{arg});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto dynamic_offset() const
|
template <typename Arg>
|
||||||
-> _new_statement_t<std::true_type, dynamic_offset_t<_database_t>>
|
auto offset(Arg arg) const -> _new_statement_t<_check<Arg>, offset_t<wrap_operand_t<Arg>>>
|
||||||
{
|
{
|
||||||
static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement");
|
static_assert(_check<Arg>::value, "offset requires an integral value or integral parameter");
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), dynamic_offset_data_t<_database_t>{} };
|
return _offset_impl(_check<Arg>{}, wrap_operand_t<Arg>{arg});
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
auto dynamic_offset() const -> _new_statement_t<std::true_type, dynamic_offset_t<_database_t>>
|
||||||
template<typename Arg>
|
{
|
||||||
auto _offset_impl(const std::false_type&, Arg arg) const
|
static_assert(not std::is_same<_database_t, void>::value,
|
||||||
-> bad_statement;
|
"dynamic_offset must not be called in a static statement");
|
||||||
|
return {static_cast<const derived_statement_t<Policies>&>(*this), dynamic_offset_data_t<_database_t>{}};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Arg>
|
private:
|
||||||
auto _offset_impl(const std::true_type&, Arg arg) const
|
template <typename Arg>
|
||||||
-> _new_statement_t<std::true_type, offset_t<Arg>>
|
auto _offset_impl(const std::false_type&, Arg arg) const -> bad_statement;
|
||||||
{
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), offset_data_t<Arg>{arg} };
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
template <typename Arg>
|
||||||
};
|
auto _offset_impl(const std::true_type&, Arg arg) const -> _new_statement_t<std::true_type, offset_t<Arg>>
|
||||||
|
{
|
||||||
|
return {static_cast<const derived_statement_t<Policies>&>(*this), offset_data_t<Arg>{arg}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// Interpreters
|
// Interpreters
|
||||||
template<typename Context, typename Offset>
|
template <typename Context, typename Offset>
|
||||||
struct serializer_t<Context, offset_data_t<Offset>>
|
struct serializer_t<Context, offset_data_t<Offset>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Offset>;
|
using _serialize_check = serialize_check_of<Context, Offset>;
|
||||||
using T = offset_data_t<Offset>;
|
using T = offset_data_t<Offset>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
context << " OFFSET ";
|
context << " OFFSET ";
|
||||||
serialize_operand(t._value, context);
|
serialize_operand(t._value, context);
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Database>
|
template <typename Context, typename Database>
|
||||||
struct serializer_t<Context, dynamic_offset_data_t<Database>>
|
struct serializer_t<Context, dynamic_offset_data_t<Database>>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = dynamic_offset_data_t<Database>;
|
using T = dynamic_offset_data_t<Database>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
static Context& _(const T& t, Context& context)
|
||||||
{
|
{
|
||||||
if (t._initialized)
|
if (t._initialized)
|
||||||
{
|
{
|
||||||
context << " OFFSET ";
|
context << " OFFSET ";
|
||||||
serialize(t._value, context);
|
serialize(t._value, context);
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,63 +34,62 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Database, typename... Expressions>
|
template <typename Database, typename... Expressions>
|
||||||
struct on_t
|
struct on_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_on>;
|
using _traits = make_traits<no_value_t, tag::is_on>;
|
||||||
using _nodes = detail::type_vector<Expressions...>;
|
using _nodes = detail::type_vector<Expressions...>;
|
||||||
|
|
||||||
using _is_dynamic = is_database<Database>;
|
using _is_dynamic = is_database<Database>;
|
||||||
|
|
||||||
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in on()");
|
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in on()");
|
||||||
|
|
||||||
template<typename Expr>
|
template <typename Expr>
|
||||||
void add(Expr expr)
|
void add(Expr expr)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "on::add() must not be called for static on()");
|
static_assert(_is_dynamic::value, "on::add() must not be called for static on()");
|
||||||
static_assert(is_expression_t<Expr>::value, "invalid expression argument in on::add()");
|
static_assert(is_expression_t<Expr>::value, "invalid expression argument in on::add()");
|
||||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expr>;
|
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expr>;
|
||||||
_serialize_check::_();
|
_serialize_check::_();
|
||||||
|
|
||||||
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expr>::value, _serialize_check::type::value>;
|
using ok = logic::all_t<_is_dynamic::value, is_expression_t<Expr>::value, _serialize_check::type::value>;
|
||||||
|
|
||||||
_add_impl(expr, ok()); // dispatch to prevent compile messages after the static_assert
|
_add_impl(expr, ok()); // dispatch to prevent compile messages after the static_assert
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Expr>
|
template <typename Expr>
|
||||||
void _add_impl(Expr expr, const std::true_type&)
|
void _add_impl(Expr expr, const std::true_type&)
|
||||||
{
|
{
|
||||||
return _dynamic_expressions.emplace_back(expr);
|
return _dynamic_expressions.emplace_back(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expr>
|
template <typename Expr>
|
||||||
void _add_impl(Expr expr, const std::false_type&);
|
void _add_impl(Expr expr, const std::false_type&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::tuple<Expressions...> _expressions;
|
std::tuple<Expressions...> _expressions;
|
||||||
interpretable_list_t<Database> _dynamic_expressions;
|
interpretable_list_t<Database> _dynamic_expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename Database, typename... Expressions>
|
template <typename Context, typename Database, typename... Expressions>
|
||||||
struct serializer_t<Context, on_t<Database, Expressions...>>
|
struct serializer_t<Context, on_t<Database, Expressions...>>
|
||||||
{
|
{
|
||||||
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
||||||
using T = on_t<Database, Expressions...>;
|
using T = on_t<Database, Expressions...>;
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
|
||||||
return context;
|
|
||||||
context << " ON ";
|
|
||||||
interpret_tuple(t._expressions, " AND ", context);
|
|
||||||
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
|
||||||
context << " AND ";
|
|
||||||
interpret_list(t._dynamic_expressions, " AND ", context);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
||||||
|
return context;
|
||||||
|
context << " ON ";
|
||||||
|
interpret_tuple(t._expressions, " AND ", context);
|
||||||
|
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
||||||
|
context << " AND ";
|
||||||
|
interpret_list(t._dynamic_expressions, " AND ", context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -37,203 +37,220 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
// ORDER BY DATA
|
// ORDER BY DATA
|
||||||
template<typename Database, typename... Expressions>
|
template <typename Database, typename... Expressions>
|
||||||
struct order_by_data_t
|
struct order_by_data_t
|
||||||
{
|
{
|
||||||
order_by_data_t(Expressions... expressions):
|
order_by_data_t(Expressions... expressions) : _expressions(expressions...)
|
||||||
_expressions(expressions...)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
order_by_data_t(const order_by_data_t&) = default;
|
order_by_data_t(const order_by_data_t&) = default;
|
||||||
order_by_data_t(order_by_data_t&&) = default;
|
order_by_data_t(order_by_data_t&&) = default;
|
||||||
order_by_data_t& operator=(const order_by_data_t&) = default;
|
order_by_data_t& operator=(const order_by_data_t&) = default;
|
||||||
order_by_data_t& operator=(order_by_data_t&&) = default;
|
order_by_data_t& operator=(order_by_data_t&&) = default;
|
||||||
~order_by_data_t() = default;
|
~order_by_data_t() = default;
|
||||||
|
|
||||||
std::tuple<Expressions...> _expressions;
|
std::tuple<Expressions...> _expressions;
|
||||||
interpretable_list_t<Database> _dynamic_expressions;
|
interpretable_list_t<Database> _dynamic_expressions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct assert_no_unknown_tables_in_order_by_t
|
struct assert_no_unknown_tables_in_order_by_t
|
||||||
{
|
{
|
||||||
using type = std::false_type;
|
using type = std::false_type;
|
||||||
|
|
||||||
template<typename T = void>
|
template <typename T = void>
|
||||||
static void _()
|
static void _()
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<T>::value, "at least one order-by expression requires a table which is otherwise not known in the statement");
|
static_assert(wrong_t<T>::value,
|
||||||
}
|
"at least one order-by expression requires a table which is otherwise not known in the statement");
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// ORDER BY
|
// ORDER BY
|
||||||
template<typename Database, typename... Expressions>
|
template <typename Database, typename... Expressions>
|
||||||
struct order_by_t
|
struct order_by_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_order_by>;
|
using _traits = make_traits<no_value_t, tag::is_order_by>;
|
||||||
using _nodes = detail::type_vector<Expressions...>;
|
using _nodes = detail::type_vector<Expressions...>;
|
||||||
|
|
||||||
using _is_dynamic = is_database<Database>;
|
using _is_dynamic = is_database<Database>;
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
using _data_t = order_by_data_t<Database, Expressions...>;
|
using _data_t = order_by_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Member implementation with data and methods
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _impl_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
void add_ntc(Expression expression)
|
void add_ntc(Expression expression)
|
||||||
{
|
{
|
||||||
add<Expression, std::false_type>(expression);
|
add<Expression, std::false_type>(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression, typename TableCheckRequired = std::true_type>
|
template <typename Expression, typename TableCheckRequired = std::true_type>
|
||||||
void add(Expression expression)
|
void add(Expression expression)
|
||||||
{
|
{
|
||||||
static_assert(_is_dynamic::value, "add() must not be called for static order_by");
|
static_assert(_is_dynamic::value, "add() must not be called for static order_by");
|
||||||
static_assert(is_sort_order_t<Expression>::value, "invalid expression argument in order_by::add()");
|
static_assert(is_sort_order_t<Expression>::value, "invalid expression argument in order_by::add()");
|
||||||
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in order_by::add()");
|
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value,
|
||||||
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
|
"expression uses tables unknown to this statement in order_by::add()");
|
||||||
_serialize_check::_();
|
using _serialize_check = sqlpp::serialize_check_t<typename Database::_serializer_context_t, Expression>;
|
||||||
|
_serialize_check::_();
|
||||||
|
|
||||||
using ok = logic::all_t<_is_dynamic::value, is_sort_order_t<Expression>::value, _serialize_check::type::value>;
|
using ok = logic::all_t<_is_dynamic::value, is_sort_order_t<Expression>::value, _serialize_check::type::value>;
|
||||||
|
|
||||||
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
|
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
void _add_impl(Expression expression, const std::true_type&)
|
void _add_impl(Expression expression, const std::true_type&)
|
||||||
{
|
{
|
||||||
return _data._dynamic_expressions.emplace_back(expression);
|
return _data._dynamic_expressions.emplace_back(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Expression>
|
template <typename Expression>
|
||||||
void _add_impl(Expression expression, const std::false_type&);
|
void _add_impl(Expression expression, const std::false_type&);
|
||||||
public:
|
|
||||||
_data_t _data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
public:
|
||||||
template<typename Policies>
|
_data_t _data;
|
||||||
struct _base_t
|
};
|
||||||
{
|
|
||||||
using _data_t = order_by_data_t<Database, Expressions...>;
|
|
||||||
|
|
||||||
_impl_t<Policies> order_by;
|
// Base template to be inherited by the statement
|
||||||
_impl_t<Policies>& operator()() { return order_by; }
|
template <typename Policies>
|
||||||
const _impl_t<Policies>& operator()() const { return order_by; }
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = order_by_data_t<Database, Expressions...>;
|
||||||
|
|
||||||
template<typename T>
|
_impl_t<Policies> order_by;
|
||||||
static auto _get_member(T t) -> decltype(t.order_by)
|
_impl_t<Policies>& operator()()
|
||||||
{
|
{
|
||||||
return t.order_by;
|
return order_by;
|
||||||
}
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return order_by;
|
||||||
|
}
|
||||||
|
|
||||||
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<order_by_t>::value,
|
template <typename T>
|
||||||
consistent_t,
|
static auto _get_member(T t) -> decltype(t.order_by)
|
||||||
assert_no_unknown_tables_in_order_by_t>::type;
|
{
|
||||||
};
|
return t.order_by;
|
||||||
};
|
}
|
||||||
|
|
||||||
// NO ORDER BY YET
|
using _consistency_check = typename std::conditional<Policies::template _no_unknown_tables<order_by_t>::value,
|
||||||
struct no_order_by_t
|
consistent_t,
|
||||||
{
|
assert_no_unknown_tables_in_order_by_t>::type;
|
||||||
using _traits = make_traits<no_value_t, tag::is_noop>;
|
};
|
||||||
using _nodes = detail::type_vector<>;
|
};
|
||||||
|
|
||||||
// Data
|
// NO ORDER BY YET
|
||||||
using _data_t = no_data_t;
|
struct no_order_by_t
|
||||||
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_noop>;
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
// Member implementation with data and methods
|
// Data
|
||||||
template<typename Policies>
|
using _data_t = no_data_t;
|
||||||
struct _impl_t
|
|
||||||
{
|
|
||||||
_data_t _data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Base template to be inherited by the statement
|
// Member implementation with data and methods
|
||||||
template<typename Policies>
|
template <typename Policies>
|
||||||
struct _base_t
|
struct _impl_t
|
||||||
{
|
{
|
||||||
using _data_t = no_data_t;
|
_data_t _data;
|
||||||
|
};
|
||||||
|
|
||||||
_impl_t<Policies> no_order_by;
|
// Base template to be inherited by the statement
|
||||||
_impl_t<Policies>& operator()() { return no_order_by; }
|
template <typename Policies>
|
||||||
const _impl_t<Policies>& operator()() const { return no_order_by; }
|
struct _base_t
|
||||||
|
{
|
||||||
|
using _data_t = no_data_t;
|
||||||
|
|
||||||
template<typename T>
|
_impl_t<Policies> no_order_by;
|
||||||
static auto _get_member(T t) -> decltype(t.no_order_by)
|
_impl_t<Policies>& operator()()
|
||||||
{
|
{
|
||||||
return t.no_order_by;
|
return no_order_by;
|
||||||
}
|
}
|
||||||
|
const _impl_t<Policies>& operator()() const
|
||||||
|
{
|
||||||
|
return no_order_by;
|
||||||
|
}
|
||||||
|
|
||||||
using _database_t = typename Policies::_database_t;
|
template <typename T>
|
||||||
|
static auto _get_member(T t) -> decltype(t.no_order_by)
|
||||||
|
{
|
||||||
|
return t.no_order_by;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... T>
|
using _database_t = typename Policies::_database_t;
|
||||||
using _check = logic::all_t<is_sort_order_t<T>::value...>;
|
|
||||||
|
|
||||||
template<typename Check, typename T>
|
template <typename... T>
|
||||||
using _new_statement_t = new_statement_t<Check::value, Policies, no_order_by_t, T>;
|
using _check = logic::all_t<is_sort_order_t<T>::value...>;
|
||||||
|
|
||||||
using _consistency_check = consistent_t;
|
template <typename Check, typename T>
|
||||||
|
using _new_statement_t = new_statement_t<Check::value, Policies, no_order_by_t, T>;
|
||||||
|
|
||||||
template<typename... Expressions>
|
using _consistency_check = consistent_t;
|
||||||
auto order_by(Expressions... expressions) const
|
|
||||||
-> _new_statement_t<_check<Expressions...>, order_by_t<void, Expressions...>>
|
|
||||||
{
|
|
||||||
static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()");
|
|
||||||
static_assert(_check<Expressions...>::value, "at least one argument is not a sort order in order_by()");
|
|
||||||
|
|
||||||
return _order_by_impl<void>(_check<Expressions...>{}, expressions...);
|
template <typename... Expressions>
|
||||||
}
|
auto order_by(Expressions... expressions) const
|
||||||
|
-> _new_statement_t<_check<Expressions...>, order_by_t<void, Expressions...>>
|
||||||
|
{
|
||||||
|
static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()");
|
||||||
|
static_assert(_check<Expressions...>::value, "at least one argument is not a sort order in order_by()");
|
||||||
|
|
||||||
template<typename... Expressions>
|
return _order_by_impl<void>(_check<Expressions...>{}, expressions...);
|
||||||
auto dynamic_order_by(Expressions... expressions) const
|
}
|
||||||
-> _new_statement_t<_check<Expressions...>, order_by_t<_database_t, Expressions...>>
|
|
||||||
{
|
|
||||||
static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement");
|
|
||||||
static_assert(_check<Expressions...>::value, "at least one argument is not a sort order in order_by()");
|
|
||||||
|
|
||||||
return _order_by_impl<_database_t>(_check<Expressions...>{}, expressions...);
|
template <typename... Expressions>
|
||||||
}
|
auto dynamic_order_by(Expressions... expressions) const
|
||||||
|
-> _new_statement_t<_check<Expressions...>, order_by_t<_database_t, Expressions...>>
|
||||||
|
{
|
||||||
|
static_assert(not std::is_same<_database_t, void>::value,
|
||||||
|
"dynamic_order_by must not be called in a static statement");
|
||||||
|
static_assert(_check<Expressions...>::value, "at least one argument is not a sort order in order_by()");
|
||||||
|
|
||||||
private:
|
return _order_by_impl<_database_t>(_check<Expressions...>{}, expressions...);
|
||||||
template<typename Database, typename... Expressions>
|
}
|
||||||
auto _order_by_impl(const std::false_type&, Expressions... expressions) const
|
|
||||||
-> bad_statement;
|
|
||||||
|
|
||||||
template<typename Database, typename... Expressions>
|
private:
|
||||||
auto _order_by_impl(const std::true_type&, Expressions... expressions) const
|
template <typename Database, typename... Expressions>
|
||||||
-> _new_statement_t<std::true_type, order_by_t<_database_t, Expressions...>>
|
auto _order_by_impl(const std::false_type&, Expressions... expressions) const -> bad_statement;
|
||||||
{
|
|
||||||
static_assert(not detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
|
|
||||||
|
|
||||||
return { static_cast<const derived_statement_t<Policies>&>(*this), order_by_data_t<Database, Expressions...>{expressions...} };
|
template <typename Database, typename... Expressions>
|
||||||
}
|
auto _order_by_impl(const std::true_type&, Expressions... expressions) const
|
||||||
};
|
-> _new_statement_t<std::true_type, order_by_t<_database_t, Expressions...>>
|
||||||
};
|
{
|
||||||
|
static_assert(not detail::has_duplicates<Expressions...>::value,
|
||||||
|
"at least one duplicate argument detected in order_by()");
|
||||||
|
|
||||||
// Interpreters
|
return {static_cast<const derived_statement_t<Policies>&>(*this),
|
||||||
template<typename Context, typename Database, typename... Expressions>
|
order_by_data_t<Database, Expressions...>{expressions...}};
|
||||||
struct serializer_t<Context, order_by_data_t<Database, Expressions...>>
|
}
|
||||||
{
|
};
|
||||||
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
};
|
||||||
using T = order_by_data_t<Database, Expressions...>;
|
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
// Interpreters
|
||||||
{
|
template <typename Context, typename Database, typename... Expressions>
|
||||||
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
struct serializer_t<Context, order_by_data_t<Database, Expressions...>>
|
||||||
return context;
|
{
|
||||||
context << " ORDER BY ";
|
using _serialize_check = serialize_check_of<Context, Expressions...>;
|
||||||
interpret_tuple(t._expressions, ',', context);
|
using T = order_by_data_t<Database, Expressions...>;
|
||||||
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
|
||||||
context << ',';
|
static Context& _(const T& t, Context& context)
|
||||||
interpret_list(t._dynamic_expressions, ',', context);
|
{
|
||||||
return context;
|
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
|
||||||
}
|
return context;
|
||||||
};
|
context << " ORDER BY ";
|
||||||
|
interpret_tuple(t._expressions, ',', context);
|
||||||
|
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
|
||||||
|
context << ',';
|
||||||
|
interpret_list(t._dynamic_expressions, ',', context);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,58 +33,55 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename ValueType, typename NameType>
|
template <typename ValueType, typename NameType>
|
||||||
struct parameter_t:
|
struct parameter_t : public expression_operators<parameter_t<ValueType, NameType>, ValueType>
|
||||||
public expression_operators<parameter_t<ValueType, NameType>, ValueType>
|
{
|
||||||
{
|
using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>;
|
||||||
using _traits = make_traits<ValueType, tag::is_parameter, tag::is_expression>;
|
|
||||||
|
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
using _parameters = detail::type_vector<parameter_t>;
|
using _parameters = detail::type_vector<parameter_t>;
|
||||||
using _can_be_null = std::true_type;
|
using _can_be_null = std::true_type;
|
||||||
|
|
||||||
using _instance_t = member_t<NameType, parameter_value_t<ValueType>>;
|
using _instance_t = member_t<NameType, parameter_value_t<ValueType>>;
|
||||||
|
|
||||||
parameter_t()
|
parameter_t()
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
parameter_t(const parameter_t&) = default;
|
parameter_t(const parameter_t&) = default;
|
||||||
parameter_t(parameter_t&&) = default;
|
parameter_t(parameter_t&&) = default;
|
||||||
parameter_t& operator=(const parameter_t&) = default;
|
parameter_t& operator=(const parameter_t&) = default;
|
||||||
parameter_t& operator=(parameter_t&&) = default;
|
parameter_t& operator=(parameter_t&&) = default;
|
||||||
~parameter_t() = default;
|
~parameter_t() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename ValueType, typename NameType>
|
template <typename Context, typename ValueType, typename NameType>
|
||||||
struct serializer_t<Context, parameter_t<ValueType, NameType>>
|
struct serializer_t<Context, parameter_t<ValueType, NameType>>
|
||||||
{
|
{
|
||||||
using _serialize_check = consistent_t;
|
using _serialize_check = consistent_t;
|
||||||
using T = parameter_t<ValueType, NameType>;
|
using T = parameter_t<ValueType, NameType>;
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
static Context& _(const T&, Context& context)
|
||||||
{
|
{
|
||||||
context << "?";
|
context << "?";
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename NamedExpr>
|
template <typename NamedExpr>
|
||||||
auto parameter(const NamedExpr&)
|
auto parameter(const NamedExpr&) -> parameter_t<value_type_of<NamedExpr>, NamedExpr>
|
||||||
-> parameter_t<value_type_of<NamedExpr>, NamedExpr>
|
{
|
||||||
{
|
static_assert(is_selectable_t<NamedExpr>::value, "not a named expression");
|
||||||
static_assert(is_selectable_t<NamedExpr>::value, "not a named expression");
|
return {};
|
||||||
return {};
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ValueType, typename AliasProvider>
|
|
||||||
auto parameter(const ValueType&, const AliasProvider&)
|
|
||||||
-> parameter_t<wrap_operand_t<ValueType>, AliasProvider>
|
|
||||||
{
|
|
||||||
static_assert(is_value_type_t<ValueType>::value, "first argument is not a value type");
|
|
||||||
static_assert(is_alias_provider_t<AliasProvider>::value, "second argument is not an alias provider");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
template <typename ValueType, typename AliasProvider>
|
||||||
|
auto parameter(const ValueType&, const AliasProvider&) -> parameter_t<wrap_operand_t<ValueType>, AliasProvider>
|
||||||
|
{
|
||||||
|
static_assert(is_value_type_t<ValueType>::value, "first argument is not a value type");
|
||||||
|
static_assert(is_alias_provider_t<AliasProvider>::value, "second argument is not an alias provider");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,39 +34,40 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename T>
|
template <typename T>
|
||||||
struct parameter_list_t
|
struct parameter_list_t
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<parameter_list_t>::value, "Template parameter for parameter_list_t has to be a type_vector");
|
static_assert(wrong_t<parameter_list_t>::value, "Template parameter for parameter_list_t has to be a type_vector");
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Parameter>
|
template <typename... Parameter>
|
||||||
struct parameter_list_t<detail::type_vector<Parameter...>>: public Parameter::_instance_t...
|
struct parameter_list_t<detail::type_vector<Parameter...>> : public Parameter::_instance_t...
|
||||||
{
|
{
|
||||||
using _member_tuple_t = std::tuple<typename Parameter::_instance_t...>;
|
using _member_tuple_t = std::tuple<typename Parameter::_instance_t...>;
|
||||||
using size = std::integral_constant<std::size_t, sizeof...(Parameter)>;
|
using size = std::integral_constant<std::size_t, sizeof...(Parameter)>;
|
||||||
|
|
||||||
parameter_list_t()
|
parameter_list_t()
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Target>
|
template <typename Target>
|
||||||
void _bind(Target& target) const
|
void _bind(Target& target) const
|
||||||
{
|
{
|
||||||
_bind_impl(target, detail::make_index_sequence<size::value>{});
|
_bind_impl(target, detail::make_index_sequence<size::value>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename Target, size_t... Is>
|
template <typename Target, size_t... Is>
|
||||||
void _bind_impl(Target& target, const detail::index_sequence<Is...>&) const
|
void _bind_impl(Target& target, const detail::index_sequence<Is...>&) const
|
||||||
{
|
{
|
||||||
using swallow = int[]; // see interpret_tuple.h
|
using swallow = int[]; // see interpret_tuple.h
|
||||||
(void) swallow{(static_cast<typename std::tuple_element<Is, const _member_tuple_t>::type&>(*this)()._bind(target, Is), 0)...};
|
(void)swallow{(
|
||||||
}
|
static_cast<typename std::tuple_element<Is, const _member_tuple_t>::type&>(*this)()._bind(target, Is), 0)...};
|
||||||
};
|
}
|
||||||
|
};
|
||||||
template<typename Exp>
|
|
||||||
using make_parameter_list_t = parameter_list_t<parameters_of<Exp>>;
|
|
||||||
|
|
||||||
|
template <typename Exp>
|
||||||
|
using make_parameter_list_t = parameter_list_t<parameters_of<Exp>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,43 +32,42 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Needle, typename Replacement>
|
template <typename Needle, typename Replacement>
|
||||||
struct policy_update_impl
|
struct policy_update_impl
|
||||||
{
|
{
|
||||||
template<typename T>
|
template <typename T>
|
||||||
using _policy_t = typename std::conditional<std::is_same<Needle, T>::value, Replacement, T>::type;
|
using _policy_t = typename std::conditional<std::is_same<Needle, T>::value, Replacement, T>::type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename Needle, typename Replacement>
|
template <typename T, typename Needle, typename Replacement>
|
||||||
using policy_update_t = typename policy_update_impl<Needle, Replacement>::template _policy_t<T>;
|
using policy_update_t = typename policy_update_impl<Needle, Replacement>::template _policy_t<T>;
|
||||||
|
|
||||||
template<typename Original, typename Needle, typename Replacement>
|
template <typename Original, typename Needle, typename Replacement>
|
||||||
struct update_policies_impl
|
struct update_policies_impl
|
||||||
{
|
{
|
||||||
using type = typename Original::template _policy_update_t<Needle, Replacement>;
|
using type = typename Original::template _policy_update_t<Needle, Replacement>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Original, typename Needle, typename Replacement>
|
template <typename Original, typename Needle, typename Replacement>
|
||||||
using update_policies_t = typename update_policies_impl<Original, Needle, Replacement>::type;
|
using update_policies_t = typename update_policies_impl<Original, Needle, Replacement>::type;
|
||||||
|
|
||||||
template<typename Policies, typename Needle, typename Replacement>
|
template <typename Policies, typename Needle, typename Replacement>
|
||||||
using new_statement = typename Policies::template _new_statement_t<Needle, Replacement>;
|
using new_statement = typename Policies::template _new_statement_t<Needle, Replacement>;
|
||||||
|
|
||||||
template<bool, typename Policies, typename Needle, typename Replacement>
|
template <bool, typename Policies, typename Needle, typename Replacement>
|
||||||
struct new_statement_impl
|
struct new_statement_impl
|
||||||
{
|
{
|
||||||
using type = typename Policies::template _new_statement_t<Needle, Replacement>;
|
using type = typename Policies::template _new_statement_t<Needle, Replacement>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Policies, typename Needle, typename Replacement>
|
template <typename Policies, typename Needle, typename Replacement>
|
||||||
struct new_statement_impl<false, Policies, Needle, Replacement>
|
struct new_statement_impl<false, Policies, Needle, Replacement>
|
||||||
{
|
{
|
||||||
using type = bad_statement;
|
using type = bad_statement;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<bool Check, typename Policies, typename Needle, typename Replacement>
|
|
||||||
using new_statement_t = typename new_statement_impl<Check, Policies, Needle, Replacement>::type;
|
|
||||||
|
|
||||||
|
template <bool Check, typename Policies, typename Needle, typename Replacement>
|
||||||
|
using new_statement_t = typename new_statement_impl<Check, Policies, Needle, Replacement>::type;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,9 +31,9 @@
|
|||||||
|
|
||||||
// enable the Clang support
|
// enable the Clang support
|
||||||
#if defined(__clang__) && !BOOST_PP_VARIADICS
|
#if defined(__clang__) && !BOOST_PP_VARIADICS
|
||||||
# undef BOOST_PP_VARIADICS
|
#undef BOOST_PP_VARIADICS
|
||||||
# define BOOST_PP_VARIADICS 1
|
#define BOOST_PP_VARIADICS 1
|
||||||
#endif // defined(__clang__)
|
#endif // defined(__clang__)
|
||||||
|
|
||||||
// boost.preprocessor
|
// boost.preprocessor
|
||||||
#include <boost/preprocessor/cat.hpp>
|
#include <boost/preprocessor/cat.hpp>
|
||||||
@ -78,130 +78,112 @@
|
|||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
// tools
|
// tools
|
||||||
|
|
||||||
#define SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \
|
#define SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) BOOST_PP_TUPLE_ELEM(0, BOOST_PP_EXPAND table)
|
||||||
BOOST_PP_TUPLE_ELEM(0, BOOST_PP_EXPAND table)
|
|
||||||
|
|
||||||
#define SQLPP_DECLARE_TABLE_GET_TABLE_PROPS(table) \
|
#define SQLPP_DECLARE_TABLE_GET_TABLE_PROPS(table) SQLPP_BOOST_PP_TUPLE_POP_FRONT(BOOST_PP_EXPAND table)
|
||||||
SQLPP_BOOST_PP_TUPLE_POP_FRONT(BOOST_PP_EXPAND table)
|
|
||||||
|
|
||||||
#define SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(col) \
|
#define SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(col) BOOST_PP_TUPLE_ELEM(0, col)
|
||||||
BOOST_PP_TUPLE_ELEM(0, col)
|
|
||||||
|
|
||||||
#define SQLPP_DECLARE_TABLE_ENUM_COLUMNS(unused, table, elem) \
|
#define SQLPP_DECLARE_TABLE_ENUM_COLUMNS(unused, table, elem) , table::SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem)
|
||||||
,table::SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem)
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
// columns
|
// columns
|
||||||
|
|
||||||
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_AUX(unused, size, idx, elem) \
|
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS_AUX(unused, size, idx, elem) \
|
||||||
BOOST_PP_CAT( \
|
BOOST_PP_CAT(SQLPP_DECLARE_COLUMN_GEN_TRAITS_, BOOST_PP_CAT(SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_, elem))(elem) \
|
||||||
SQLPP_DECLARE_COLUMN_GEN_TRAITS_ \
|
BOOST_PP_COMMA_IF(BOOST_PP_LESS(BOOST_PP_ADD(idx, 1), size))
|
||||||
,BOOST_PP_CAT(SQLPP_DECLARE_COLUMN_GET_TRAITS_LAZY_, elem) \
|
|
||||||
)(elem) \
|
|
||||||
BOOST_PP_COMMA_IF(BOOST_PP_LESS(BOOST_PP_ADD(idx, 1), size))
|
|
||||||
|
|
||||||
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS(props) \
|
#define SQLPP_DECLARE_COLUMN_GEN_TRAITS(props) \
|
||||||
BOOST_PP_SEQ_FOR_EACH_I( \
|
BOOST_PP_SEQ_FOR_EACH_I(SQLPP_DECLARE_COLUMN_GEN_TRAITS_AUX, BOOST_PP_TUPLE_SIZE(props), BOOST_PP_TUPLE_TO_SEQ(props))
|
||||||
SQLPP_DECLARE_COLUMN_GEN_TRAITS_AUX \
|
|
||||||
,BOOST_PP_TUPLE_SIZE(props) \
|
|
||||||
,BOOST_PP_TUPLE_TO_SEQ(props) \
|
|
||||||
)
|
|
||||||
|
|
||||||
#define SQLPP_DECLARE_COLUMN(unused, data, elem) \
|
#define SQLPP_DECLARE_COLUMN(unused, data, elem) \
|
||||||
struct SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem) { \
|
struct SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem) \
|
||||||
struct _alias_t { \
|
{ \
|
||||||
static constexpr const char _literal[] = \
|
struct _alias_t \
|
||||||
BOOST_PP_STRINGIZE(SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem)); \
|
{ \
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>; \
|
static constexpr const char _literal[] = BOOST_PP_STRINGIZE(SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem)); \
|
||||||
\
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>; \
|
||||||
template<typename T> \
|
\
|
||||||
struct _member_t { \
|
template <typename T> \
|
||||||
T SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); \
|
struct _member_t \
|
||||||
\
|
{ \
|
||||||
T& operator()() { return SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); } \
|
T SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); \
|
||||||
const T& operator()() const { return SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); } \
|
\
|
||||||
}; /* struct _member_t */ \
|
T& operator()() \
|
||||||
}; /* struct _alias_t */ \
|
{ \
|
||||||
\
|
return SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); \
|
||||||
using _traits = sqlpp::make_traits< \
|
} \
|
||||||
SQLPP_DECLARE_COLUMN_GEN_TRAITS(SQLPP_BOOST_PP_TUPLE_POP_FRONT(elem)) \
|
const T& operator()() const \
|
||||||
>; \
|
{ \
|
||||||
\
|
return SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem); \
|
||||||
}; /* struct SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem) */
|
} \
|
||||||
|
}; /* struct _member_t */ \
|
||||||
|
}; /* struct _alias_t */ \
|
||||||
|
\
|
||||||
|
using _traits = sqlpp::make_traits<SQLPP_DECLARE_COLUMN_GEN_TRAITS(SQLPP_BOOST_PP_TUPLE_POP_FRONT(elem))>; \
|
||||||
|
\
|
||||||
|
}; /* struct SQLPP_DECLARE_COLUMN_GET_COLUMN_NAME(elem) */
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
// table props
|
// table props
|
||||||
|
|
||||||
#define SQLPP_DECLARE_TABLE_GEN_PROPS_AUX(unused1, unused2, elem) \
|
#define SQLPP_DECLARE_TABLE_GEN_PROPS_AUX(unused1, unused2, elem) \
|
||||||
BOOST_PP_CAT( \
|
BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GEN_, BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_PROC_LAZY_, elem))(elem)
|
||||||
SQLPP_DECLARE_TABLE_GEN_ \
|
|
||||||
,BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_PROC_LAZY_, elem) \
|
|
||||||
)(elem)
|
|
||||||
|
|
||||||
#define SQLPP_DECLARE_TABLE_GEN_PROPS(table) \
|
#define SQLPP_DECLARE_TABLE_GEN_PROPS(table) \
|
||||||
BOOST_PP_SEQ_FOR_EACH( \
|
BOOST_PP_SEQ_FOR_EACH(SQLPP_DECLARE_TABLE_GEN_PROPS_AUX, ~, \
|
||||||
SQLPP_DECLARE_TABLE_GEN_PROPS_AUX \
|
BOOST_PP_TUPLE_TO_SEQ(SQLPP_BOOST_PP_TUPLE_POP_FRONT(table)))
|
||||||
,~ \
|
|
||||||
,BOOST_PP_TUPLE_TO_SEQ(SQLPP_BOOST_PP_TUPLE_POP_FRONT(table)) \
|
|
||||||
)
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
// main
|
// main
|
||||||
|
|
||||||
#define SQLPP_DECLARE_TABLE_IMPL(table, cols) \
|
#define SQLPP_DECLARE_TABLE_IMPL(table, cols) \
|
||||||
namespace SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) { \
|
namespace SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \
|
||||||
namespace BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) { \
|
{ \
|
||||||
BOOST_PP_SEQ_FOR_EACH( \
|
namespace BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) \
|
||||||
SQLPP_DECLARE_COLUMN \
|
{ \
|
||||||
,~ \
|
BOOST_PP_SEQ_FOR_EACH(SQLPP_DECLARE_COLUMN, ~, cols) \
|
||||||
,cols \
|
} /* namespace BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) */ \
|
||||||
) \
|
\
|
||||||
} /* namespace BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) */ \
|
struct SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \
|
||||||
\
|
: sqlpp::table_t<SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) BOOST_PP_SEQ_FOR_EACH( \
|
||||||
struct SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \
|
SQLPP_DECLARE_TABLE_ENUM_COLUMNS, BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _), cols)> \
|
||||||
: sqlpp::table_t< \
|
{ \
|
||||||
SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) \
|
BOOST_PP_IF(BOOST_PP_LESS(BOOST_PP_TUPLE_SIZE(table), 2), \
|
||||||
BOOST_PP_SEQ_FOR_EACH( \
|
BOOST_PP_TUPLE_EAT(), \
|
||||||
SQLPP_DECLARE_TABLE_ENUM_COLUMNS \
|
SQLPP_DECLARE_TABLE_GEN_PROPS)(BOOST_PP_EXPAND table) \
|
||||||
,BOOST_PP_CAT(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table), _) \
|
\
|
||||||
,cols \
|
struct _alias_t \
|
||||||
) \
|
{ \
|
||||||
> \
|
static constexpr const char _literal[] = BOOST_PP_STRINGIZE(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table)); \
|
||||||
{ \
|
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>; \
|
||||||
BOOST_PP_IF( \
|
\
|
||||||
BOOST_PP_LESS(BOOST_PP_TUPLE_SIZE(table), 2) \
|
template <typename T> \
|
||||||
,BOOST_PP_TUPLE_EAT() \
|
struct _member_t \
|
||||||
,SQLPP_DECLARE_TABLE_GEN_PROPS \
|
{ \
|
||||||
)(BOOST_PP_EXPAND table) \
|
T SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); \
|
||||||
\
|
\
|
||||||
struct _alias_t { \
|
T& operator()() \
|
||||||
static constexpr const char _literal[] = \
|
{ \
|
||||||
BOOST_PP_STRINGIZE(SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table)); \
|
return SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); \
|
||||||
using _name_t = sqlpp::make_char_sequence<sizeof(_literal), _literal>; \
|
} \
|
||||||
\
|
const T& operator()() const \
|
||||||
template<typename T> \
|
{ \
|
||||||
struct _member_t { \
|
return SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); \
|
||||||
T SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); \
|
} \
|
||||||
\
|
\
|
||||||
T& operator()() { return SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); } \
|
}; /* struct _member_t */ \
|
||||||
const T& operator()() const { return SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table); } \
|
\
|
||||||
\
|
}; /* struct _alias_t */ \
|
||||||
}; /* struct _member_t */ \
|
\
|
||||||
\
|
}; /* struct SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) */ \
|
||||||
}; /* struct _alias_t */ \
|
}
|
||||||
\
|
|
||||||
}; /* struct SQLPP_DECLARE_TABLE_GET_TABLE_NAME(table) */ \
|
|
||||||
\
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
#define SQLPP_DECLARE_TABLE(table, cols) \
|
#define SQLPP_DECLARE_TABLE(table, cols) \
|
||||||
SQLPP_DECLARE_TABLE_IMPL( \
|
SQLPP_DECLARE_TABLE_IMPL(BOOST_PP_CAT(SQLPP_WRAP_SEQUENCE_X table, 0), BOOST_PP_CAT(SQLPP_WRAP_SEQUENCE_X cols, 0))
|
||||||
BOOST_PP_CAT(SQLPP_WRAP_SEQUENCE_X table, 0) \
|
|
||||||
,BOOST_PP_CAT(SQLPP_WRAP_SEQUENCE_X cols, 0) \
|
|
||||||
)
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
#endif // _sqlpp__ppgen_h
|
#endif // _sqlpp__ppgen_h
|
||||||
|
@ -33,32 +33,30 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db, typename Statement>
|
template <typename Db, typename Statement>
|
||||||
struct prepared_execute_t
|
struct prepared_execute_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
using _parameter_list_t = make_parameter_list_t<Statement>;
|
using _parameter_list_t = make_parameter_list_t<Statement>;
|
||||||
using _prepared_statement_t = typename Db::_prepared_statement_t;
|
using _prepared_statement_t = typename Db::_prepared_statement_t;
|
||||||
|
|
||||||
using _run_check = consistent_t;
|
using _run_check = consistent_t;
|
||||||
|
|
||||||
auto _run(Db& db) const
|
auto _run(Db& db) const -> size_t
|
||||||
-> size_t
|
{
|
||||||
{
|
return db.run_prepared_execute(*this);
|
||||||
return db.run_prepared_execute(*this);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void _bind_params() const
|
void _bind_params() const
|
||||||
{
|
{
|
||||||
params._bind(_prepared_statement);
|
params._bind(_prepared_statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
_parameter_list_t params;
|
|
||||||
mutable _prepared_statement_t _prepared_statement;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
_parameter_list_t params;
|
||||||
|
mutable _prepared_statement_t _prepared_statement;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,32 +33,30 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db, typename Insert>
|
template <typename Db, typename Insert>
|
||||||
struct prepared_insert_t
|
struct prepared_insert_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
using _parameter_list_t = make_parameter_list_t<Insert>;
|
using _parameter_list_t = make_parameter_list_t<Insert>;
|
||||||
using _prepared_statement_t = typename Db::_prepared_statement_t;
|
using _prepared_statement_t = typename Db::_prepared_statement_t;
|
||||||
|
|
||||||
using _run_check = consistent_t;
|
using _run_check = consistent_t;
|
||||||
|
|
||||||
auto _run(Db& db) const
|
auto _run(Db& db) const -> size_t
|
||||||
-> size_t
|
{
|
||||||
{
|
return db.run_prepared_insert(*this);
|
||||||
return db.run_prepared_insert(*this);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void _bind_params() const
|
void _bind_params() const
|
||||||
{
|
{
|
||||||
params._bind(_prepared_statement);
|
params._bind(_prepared_statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
_parameter_list_t params;
|
|
||||||
mutable _prepared_statement_t _prepared_statement;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
_parameter_list_t params;
|
||||||
|
mutable _prepared_statement_t _prepared_statement;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,32 +33,30 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db, typename Remove>
|
template <typename Db, typename Remove>
|
||||||
struct prepared_remove_t
|
struct prepared_remove_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
using _parameter_list_t = make_parameter_list_t<Remove>;
|
using _parameter_list_t = make_parameter_list_t<Remove>;
|
||||||
using _prepared_statement_t = typename Db::_prepared_statement_t;
|
using _prepared_statement_t = typename Db::_prepared_statement_t;
|
||||||
|
|
||||||
using _run_check = consistent_t;
|
using _run_check = consistent_t;
|
||||||
|
|
||||||
auto _run(Db& db) const
|
auto _run(Db& db) const -> size_t
|
||||||
-> size_t
|
{
|
||||||
{
|
return db.run_prepared_insert(*this);
|
||||||
return db.run_prepared_insert(*this);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void _bind_params() const
|
void _bind_params() const
|
||||||
{
|
{
|
||||||
params._bind(_prepared_statement);
|
params._bind(_prepared_statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
_parameter_list_t params;
|
|
||||||
mutable _prepared_statement_t _prepared_statement;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
_parameter_list_t params;
|
||||||
|
mutable _prepared_statement_t _prepared_statement;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,35 +33,33 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Database, typename Statement, typename Composite = Statement>
|
template <typename Database, typename Statement, typename Composite = Statement>
|
||||||
struct prepared_select_t
|
struct prepared_select_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
using _result_row_t = typename Statement::template _result_row_t<Database>;
|
using _result_row_t = typename Statement::template _result_row_t<Database>;
|
||||||
using _parameter_list_t = make_parameter_list_t<Composite>;
|
using _parameter_list_t = make_parameter_list_t<Composite>;
|
||||||
using _dynamic_names_t = typename Statement::_dynamic_names_t;
|
using _dynamic_names_t = typename Statement::_dynamic_names_t;
|
||||||
using _prepared_statement_t = typename Database::_prepared_statement_t;
|
using _prepared_statement_t = typename Database::_prepared_statement_t;
|
||||||
|
|
||||||
using _run_check = consistent_t;
|
using _run_check = consistent_t;
|
||||||
|
|
||||||
auto _run(Database& db) const
|
auto _run(Database& db) const -> result_t<decltype(db.run_prepared_select(*this)), _result_row_t>
|
||||||
-> result_t<decltype(db.run_prepared_select(*this)), _result_row_t>
|
{
|
||||||
{
|
return {db.run_prepared_select(*this), _dynamic_names};
|
||||||
return {db.run_prepared_select(*this), _dynamic_names};
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void _bind_params() const
|
void _bind_params() const
|
||||||
{
|
{
|
||||||
params._bind(_prepared_statement);
|
params._bind(_prepared_statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
_parameter_list_t params;
|
|
||||||
_dynamic_names_t _dynamic_names;
|
|
||||||
mutable _prepared_statement_t _prepared_statement;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
_parameter_list_t params;
|
||||||
|
_dynamic_names_t _dynamic_names;
|
||||||
|
mutable _prepared_statement_t _prepared_statement;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,32 +33,30 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename Db, typename Update>
|
template <typename Db, typename Update>
|
||||||
struct prepared_update_t
|
struct prepared_update_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
using _traits = make_traits<no_value_t, tag::is_prepared_statement>;
|
||||||
using _nodes = detail::type_vector<>;
|
using _nodes = detail::type_vector<>;
|
||||||
|
|
||||||
using _parameter_list_t = make_parameter_list_t<Update>;
|
using _parameter_list_t = make_parameter_list_t<Update>;
|
||||||
using _prepared_statement_t = typename Db::_prepared_statement_t;
|
using _prepared_statement_t = typename Db::_prepared_statement_t;
|
||||||
|
|
||||||
using _run_check = consistent_t;
|
using _run_check = consistent_t;
|
||||||
|
|
||||||
auto _run(Db& db) const
|
auto _run(Db& db) const -> size_t
|
||||||
-> size_t
|
{
|
||||||
{
|
return db.run_prepared_insert(*this);
|
||||||
return db.run_prepared_insert(*this);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void _bind_params() const
|
void _bind_params() const
|
||||||
{
|
{
|
||||||
params._bind(_prepared_statement);
|
params._bind(_prepared_statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
_parameter_list_t params;
|
|
||||||
mutable _prepared_statement_t _prepared_statement;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
_parameter_list_t params;
|
||||||
|
mutable _prepared_statement_t _prepared_statement;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,105 +40,95 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
struct remove_name_t {};
|
struct remove_name_t
|
||||||
struct remove_t: public statement_name_t<remove_name_t>
|
{
|
||||||
{
|
};
|
||||||
using _traits = make_traits<no_value_t, tag::is_return_value>;
|
struct remove_t : public statement_name_t<remove_name_t>
|
||||||
struct _alias_t {};
|
{
|
||||||
|
using _traits = make_traits<no_value_t, tag::is_return_value>;
|
||||||
|
struct _alias_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
template<typename Statement>
|
template <typename Statement>
|
||||||
struct _result_methods_t
|
struct _result_methods_t
|
||||||
{
|
{
|
||||||
using _statement_t = Statement;
|
using _statement_t = Statement;
|
||||||
|
|
||||||
const _statement_t& _get_statement() const
|
const _statement_t& _get_statement() const
|
||||||
{
|
{
|
||||||
return static_cast<const _statement_t&>(*this);
|
return static_cast<const _statement_t&>(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute
|
// Execute
|
||||||
template<typename Db, typename Composite>
|
template <typename Db, typename Composite>
|
||||||
auto _run(Db& db, const Composite& composite) const
|
auto _run(Db& db, const Composite& composite) const -> decltype(db.remove(composite))
|
||||||
-> decltype(db.remove(composite))
|
{
|
||||||
{
|
return db.remove(composite);
|
||||||
return db.remove(composite);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
auto _run(Db& db) const -> decltype(db.remove(this->_get_statement()))
|
auto _run(Db& db) const -> decltype(db.remove(this->_get_statement()))
|
||||||
{
|
{
|
||||||
return db.remove(_get_statement());
|
return db.remove(_get_statement());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
template<typename Db, typename Composite>
|
template <typename Db, typename Composite>
|
||||||
auto _prepare(Db& db, const Composite& composite) const
|
auto _prepare(Db& db, const Composite& composite) const -> prepared_remove_t<Db, Composite>
|
||||||
-> prepared_remove_t<Db, Composite>
|
{
|
||||||
{
|
return {{}, db.prepare_remove(composite)};
|
||||||
return {{}, db.prepare_remove(composite)};
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Db>
|
template <typename Db>
|
||||||
auto _prepare(Db& db) const
|
auto _prepare(Db& db) const -> prepared_remove_t<Db, _statement_t>
|
||||||
-> prepared_remove_t<Db, _statement_t>
|
{
|
||||||
{
|
return {{}, db.prepare_remove(_get_statement())};
|
||||||
return {{}, db.prepare_remove(_get_statement())};
|
}
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
struct serializer_t<Context, remove_name_t>
|
||||||
|
{
|
||||||
|
using _serialize_check = consistent_t;
|
||||||
|
using T = remove_name_t;
|
||||||
|
|
||||||
template<typename Context>
|
static Context& _(const T&, Context& context)
|
||||||
struct serializer_t<Context, remove_name_t>
|
{
|
||||||
{
|
context << "DELETE";
|
||||||
using _serialize_check = consistent_t;
|
|
||||||
using T = remove_name_t;
|
|
||||||
|
|
||||||
static Context& _(const T&, Context& context)
|
return context;
|
||||||
{
|
}
|
||||||
context << "DELETE";
|
};
|
||||||
|
|
||||||
return context;
|
template <typename Database>
|
||||||
}
|
using blank_remove_t = statement_t<Database, remove_t, no_from_t, no_using_t, no_extra_tables_t, no_where_t<true>>;
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Database>
|
inline auto remove() -> blank_remove_t<void>
|
||||||
using blank_remove_t = statement_t<Database,
|
{
|
||||||
remove_t,
|
return {blank_remove_t<void>()};
|
||||||
no_from_t,
|
}
|
||||||
no_using_t,
|
|
||||||
no_extra_tables_t,
|
|
||||||
no_where_t<true>
|
|
||||||
>;
|
|
||||||
|
|
||||||
inline auto remove()
|
template <typename Table>
|
||||||
-> blank_remove_t<void>
|
auto remove_from(Table table) -> decltype(blank_remove_t<void>().from(table))
|
||||||
{
|
{
|
||||||
return { blank_remove_t<void>() };
|
return {blank_remove_t<void>().from(table)};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Table>
|
template <typename Database>
|
||||||
auto remove_from(Table table)
|
auto dynamic_remove(const Database&) -> decltype(blank_remove_t<Database>())
|
||||||
-> decltype(blank_remove_t<void>().from(table))
|
{
|
||||||
{
|
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
||||||
return { blank_remove_t<void>().from(table) };
|
return {blank_remove_t<Database>()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Database>
|
template <typename Database, typename Table>
|
||||||
auto dynamic_remove(const Database&)
|
auto dynamic_remove_from(const Database&, Table table) -> decltype(blank_remove_t<Database>().from(table))
|
||||||
-> decltype(blank_remove_t<Database>())
|
{
|
||||||
{
|
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
||||||
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
return {blank_remove_t<Database>().from(table)};
|
||||||
return { blank_remove_t<Database>() };
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Database, typename Table>
|
|
||||||
auto dynamic_remove_from(const Database&, Table table)
|
|
||||||
-> decltype(blank_remove_t<Database>().from(table))
|
|
||||||
{
|
|
||||||
static_assert(std::is_base_of<connection, Database>::value, "Invalid database parameter");
|
|
||||||
return { blank_remove_t<Database>().from(table) };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,98 +30,94 @@
|
|||||||
// FIXME: include for move?
|
// FIXME: include for move?
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename DbResult, typename ResultRow>
|
template <typename DbResult, typename ResultRow>
|
||||||
class result_t
|
class result_t
|
||||||
{
|
{
|
||||||
using db_result_t = DbResult;
|
using db_result_t = DbResult;
|
||||||
using result_row_t = ResultRow;
|
using result_row_t = ResultRow;
|
||||||
|
|
||||||
db_result_t _result;
|
db_result_t _result;
|
||||||
result_row_t _result_row;
|
result_row_t _result_row;
|
||||||
db_result_t _end;
|
db_result_t _end;
|
||||||
result_row_t _end_row;
|
result_row_t _end_row;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
result_t() = default;
|
result_t() = default;
|
||||||
|
|
||||||
template<typename DynamicNames>
|
template <typename DynamicNames>
|
||||||
result_t(db_result_t&& result, const DynamicNames& dynamic_names):
|
result_t(db_result_t&& result, const DynamicNames& dynamic_names)
|
||||||
_result(std::move(result)),
|
: _result(std::move(result)), _result_row(dynamic_names)
|
||||||
_result_row(dynamic_names)
|
{
|
||||||
{
|
_result.next(_result_row);
|
||||||
_result.next(_result_row);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
result_t(const result_t&) = delete;
|
result_t(const result_t&) = delete;
|
||||||
result_t(result_t&&) = default;
|
result_t(result_t&&) = default;
|
||||||
result_t& operator=(const result_t&) = delete;
|
result_t& operator=(const result_t&) = delete;
|
||||||
result_t& operator=(result_t&&) = default;
|
result_t& operator=(result_t&&) = default;
|
||||||
|
|
||||||
// Iterator
|
// Iterator
|
||||||
class iterator
|
class iterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
iterator(db_result_t& result, result_row_t& result_row):
|
iterator(db_result_t& result, result_row_t& result_row) : _result(result), _result_row(result_row)
|
||||||
_result(result),
|
{
|
||||||
_result_row(result_row)
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const result_row_t& operator*() const
|
const result_row_t& operator*() const
|
||||||
{
|
{
|
||||||
return _result_row;
|
return _result_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
const result_row_t* operator->() const
|
const result_row_t* operator->() const
|
||||||
{
|
{
|
||||||
return &_result_row;
|
return &_result_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const iterator& rhs) const
|
bool operator==(const iterator& rhs) const
|
||||||
{
|
{
|
||||||
return _result_row == rhs._result_row;
|
return _result_row == rhs._result_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const iterator& rhs) const
|
bool operator!=(const iterator& rhs) const
|
||||||
{
|
{
|
||||||
return not (operator==(rhs));
|
return not(operator==(rhs));
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator++()
|
void operator++()
|
||||||
{
|
{
|
||||||
_result.next(_result_row);
|
_result.next(_result_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
db_result_t& _result;
|
db_result_t& _result;
|
||||||
result_row_t& _result_row;
|
result_row_t& _result_row;
|
||||||
};
|
};
|
||||||
|
|
||||||
iterator begin()
|
iterator begin()
|
||||||
{
|
{
|
||||||
return iterator(_result, _result_row);
|
return iterator(_result, _result_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator end()
|
iterator end()
|
||||||
{
|
{
|
||||||
return iterator(_end, _end_row);
|
return iterator(_end, _end_row);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result_row_t& front() const
|
const result_row_t& front() const
|
||||||
{
|
{
|
||||||
return _result_row;
|
return _result_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool empty() const
|
bool empty() const
|
||||||
{
|
{
|
||||||
return _result_row == _end_row;
|
return _result_row == _end_row;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_front()
|
void pop_front()
|
||||||
{
|
{
|
||||||
_result.next(_result_row);
|
_result.next(_result_row);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,32 +32,30 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
template<typename ValueType, typename Db, typename FieldSpec>
|
template <typename ValueType, typename Db, typename FieldSpec>
|
||||||
struct result_field_t
|
struct result_field_t
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<result_field_t>::value, "Missing specialization for result_field_t");
|
static_assert(wrong_t<result_field_t>::value, "Missing specialization for result_field_t");
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Context, typename ValueType, typename Db, typename FieldSpec>
|
|
||||||
struct serializer_t<Context, result_field_t<ValueType, Db, FieldSpec>>
|
|
||||||
{
|
|
||||||
using _serialize_check = consistent_t;
|
|
||||||
using T = result_field_t<ValueType, Db, FieldSpec>;
|
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
if (t.is_null() and not null_is_trivial_value_t<T>::value)
|
|
||||||
{
|
|
||||||
context << "NULL";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context << t.value();
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
template <typename Context, typename ValueType, typename Db, typename FieldSpec>
|
||||||
|
struct serializer_t<Context, result_field_t<ValueType, Db, FieldSpec>>
|
||||||
|
{
|
||||||
|
using _serialize_check = consistent_t;
|
||||||
|
using T = result_field_t<ValueType, Db, FieldSpec>;
|
||||||
|
|
||||||
|
static Context& _(const T& t, Context& context)
|
||||||
|
{
|
||||||
|
if (t.is_null() and not null_is_trivial_value_t<T>::value)
|
||||||
|
{
|
||||||
|
context << "NULL";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context << t.value();
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,58 +32,58 @@
|
|||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template<typename Field>
|
template <typename Field>
|
||||||
struct get_field_spec_impl
|
struct get_field_spec_impl
|
||||||
{
|
{
|
||||||
static_assert(wrong_t<get_field_spec_impl>::value, "Invalid argument for get_field_spec");
|
static_assert(wrong_t<get_field_spec_impl>::value, "Invalid argument for get_field_spec");
|
||||||
};
|
};
|
||||||
|
|
||||||
template<template<typename, typename, typename> class Field, typename ValueType, typename Db, typename FieldSpec>
|
template <template <typename, typename, typename> class Field, typename ValueType, typename Db, typename FieldSpec>
|
||||||
struct get_field_spec_impl<Field<ValueType, Db, FieldSpec>>
|
struct get_field_spec_impl<Field<ValueType, Db, FieldSpec>>
|
||||||
{
|
{
|
||||||
using type = FieldSpec;
|
using type = FieldSpec;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Field>
|
template <typename Field>
|
||||||
using get_field_spec_t = typename get_field_spec_impl<Field>::type;
|
using get_field_spec_t = typename get_field_spec_impl<Field>::type;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Field, typename Enable = void>
|
template <typename Field, typename Enable = void>
|
||||||
struct result_field_methods_base_t
|
struct result_field_methods_base_t
|
||||||
{
|
{
|
||||||
using _field_spec_t = detail::get_field_spec_t<Field>;
|
using _field_spec_t = detail::get_field_spec_t<Field>;
|
||||||
static constexpr bool _null_is_trivial = true;
|
static constexpr bool _null_is_trivial = true;
|
||||||
operator cpp_value_type_of<_field_spec_t>() const { return static_cast<const Field&>(*this).value(); }
|
operator cpp_value_type_of<_field_spec_t>() const
|
||||||
};
|
{
|
||||||
|
return static_cast<const Field&>(*this).value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template<template<typename, typename, typename> class Field, typename ValueType, typename Db, typename FieldSpec>
|
template <template <typename, typename, typename> class Field, typename ValueType, typename Db, typename FieldSpec>
|
||||||
struct result_field_methods_base_t<
|
struct result_field_methods_base_t<Field<ValueType, Db, FieldSpec>,
|
||||||
Field<ValueType, Db, FieldSpec>,
|
typename std::enable_if<enforce_null_result_treatment_t<Db>::value and
|
||||||
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
|
column_spec_can_be_null_t<FieldSpec>::value and
|
||||||
and column_spec_can_be_null_t<FieldSpec>::value
|
not null_is_trivial_value_t<FieldSpec>::value>::type>
|
||||||
and not null_is_trivial_value_t<FieldSpec>::value>::type>
|
{
|
||||||
{
|
using _field_spec_t = FieldSpec;
|
||||||
using _field_spec_t = FieldSpec;
|
static constexpr bool _null_is_trivial = false;
|
||||||
static constexpr bool _null_is_trivial = false;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Field>
|
template <typename Field>
|
||||||
struct result_field_methods_t: public result_field_methods_base_t<Field>,
|
struct result_field_methods_t : public result_field_methods_base_t<Field>, public alias_operators<Field>
|
||||||
public alias_operators<Field>
|
{
|
||||||
{
|
using _base_t = result_field_methods_base_t<Field>;
|
||||||
using _base_t = result_field_methods_base_t<Field>;
|
using _field_spec_t = typename _base_t::_field_spec_t;
|
||||||
using _field_spec_t = typename _base_t::_field_spec_t;
|
|
||||||
|
|
||||||
using _traits = make_traits<value_type_of<_field_spec_t>,
|
using _traits = make_traits<value_type_of<_field_spec_t>,
|
||||||
tag::is_result_field,
|
tag::is_result_field,
|
||||||
tag::is_expression,
|
tag::is_expression,
|
||||||
tag_if<tag::null_is_trivial_value, _base_t::_null_is_trivial>>;
|
tag_if<tag::null_is_trivial_value, _base_t::_null_is_trivial>>;
|
||||||
|
|
||||||
using _nodes = detail::type_vector<>;
|
|
||||||
using _can_be_null = column_spec_can_be_null_t<_field_spec_t>;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
using _nodes = detail::type_vector<>;
|
||||||
|
using _can_be_null = column_spec_can_be_null_t<_field_spec_t>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user