2014-01-18 22:50:16 +08:00
/*
2014-03-27 23:43:36 +08:00
* Copyright ( c ) 2013 - 2014 , Roland Bock
2014-01-18 22:50:16 +08:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without modification ,
* are permitted provided that the following conditions are met :
*
* Redistributions of source code must retain the above copyright notice , this
* list of conditions and the following disclaimer .
*
* Redistributions in binary form must reproduce the above copyright notice , this
* list of conditions and the following disclaimer in the documentation and / or
* other materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND
* ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES
* ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ;
* LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
# ifndef SQLPP_GROUP_BY_H
# define SQLPP_GROUP_BY_H
# include <tuple>
# include <sqlpp11/type_traits.h>
# include <sqlpp11/vendor/expression.h>
# include <sqlpp11/vendor/interpret_tuple.h>
# include <sqlpp11/vendor/interpretable_list.h>
2014-02-08 05:52:02 +08:00
# include <sqlpp11/vendor/policy_update.h>
2014-02-03 01:45:21 +08:00
# include <sqlpp11/detail/logic.h>
2014-01-18 22:50:16 +08:00
namespace sqlpp
{
namespace vendor
{
2014-02-08 05:52:02 +08:00
// GROUP BY
template < typename Database , typename . . . Expressions >
2014-01-18 22:50:16 +08:00
struct group_by_t
{
using _is_group_by = std : : true_type ;
using _is_dynamic = typename std : : conditional < std : : is_same < Database , void > : : value , std : : false_type , std : : true_type > : : type ;
2014-02-08 05:52:02 +08:00
using _parameter_tuple_t = std : : tuple < Expressions . . . > ;
2014-04-12 00:23:20 +08:00
using _parameter_list_t = typename make_parameter_list_t < _parameter_tuple_t > : : type ;
2014-05-15 14:00:03 +08:00
using _provided_tables = detail : : type_set < > ;
using _required_tables = typename : : sqlpp : : detail : : make_joined_set < typename Expressions : : _required_tables . . . > : : type ;
2014-01-18 22:50:16 +08:00
2014-02-08 05:52:02 +08:00
static_assert ( _is_dynamic : : value or sizeof . . . ( Expressions ) , " at least one expression (e.g. a column) required in group_by() " ) ;
2014-01-18 22:50:16 +08:00
2014-02-08 05:52:02 +08:00
static_assert ( not : : sqlpp : : detail : : has_duplicates < Expressions . . . > : : value , " at least one duplicate argument detected in group_by() " ) ;
2014-01-18 22:50:16 +08:00
2014-05-01 23:34:47 +08:00
static_assert ( : : sqlpp : : detail : : all_t < is_expression_t < Expressions > : : value . . . > : : value , " at least one argument is not an expression in group_by() " ) ;
2014-01-18 22:50:16 +08:00
2014-02-08 05:52:02 +08:00
group_by_t ( Expressions . . . expressions ) :
_expressions ( expressions . . . )
{ }
group_by_t ( const group_by_t & ) = default ;
group_by_t ( group_by_t & & ) = default ;
group_by_t & operator = ( const group_by_t & ) = default ;
group_by_t & operator = ( group_by_t & & ) = default ;
~ group_by_t ( ) = default ;
2014-04-09 04:26:45 +08:00
template < typename Policies >
struct _methods_t
2014-01-18 22:50:16 +08:00
{
2014-04-09 04:26:45 +08:00
template < typename Expression >
2014-04-23 02:46:32 +08:00
void add_group_by_ntc ( Expression expression )
{
add_group_by < Expression , std : : false_type > ( expression ) ;
}
template < typename Expression , typename TableCheckRequired = std : : true_type >
2014-04-09 04:26:45 +08:00
void add_group_by ( Expression expression )
{
2014-04-09 04:45:19 +08:00
static_assert ( _is_dynamic : : value , " add_group_by must not be called for static group_by " ) ;
2014-04-09 04:26:45 +08:00
static_assert ( is_expression_t < Expression > : : value , " invalid expression argument in add_group_by() " ) ;
2014-04-23 02:46:32 +08:00
static_assert ( TableCheckRequired : : value or Policies : : template _no_unknown_tables < Expression > : : value , " expression uses tables unknown to this statement in add_group_by() " ) ;
2014-04-10 22:09:54 +08:00
2014-05-01 23:34:47 +08:00
using ok = : : sqlpp : : detail : : all_t < _is_dynamic : : value , is_expression_t < Expression > : : value > ;
2014-04-10 22:09:54 +08:00
_add_group_by_impl ( expression , ok ( ) ) ; // dispatch to prevent compile messages after the static_assert
}
private :
template < typename Expression >
void _add_group_by_impl ( Expression expression , const std : : true_type & )
{
2014-04-10 02:54:28 +08:00
return static_cast < typename Policies : : _statement_t * > ( this ) - > _group_by . _dynamic_expressions . emplace_back ( expression ) ;
2014-04-09 04:26:45 +08:00
}
2014-04-10 22:09:54 +08:00
template < typename Expression >
void _add_group_by_impl ( Expression expression , const std : : false_type & ) ;
2014-04-09 04:26:45 +08:00
} ;
2014-01-18 22:50:16 +08:00
2014-02-08 07:43:20 +08:00
const group_by_t & _group_by ( ) const { return * this ; }
2014-01-18 22:50:16 +08:00
_parameter_tuple_t _expressions ;
vendor : : interpretable_list_t < Database > _dynamic_expressions ;
2014-02-08 05:52:02 +08:00
} ;
struct no_group_by_t
{
2014-02-10 06:30:30 +08:00
using _is_noop = std : : true_type ;
2014-05-15 14:00:03 +08:00
using _provided_tables = detail : : type_set < > ;
using _required_tables = : : sqlpp : : detail : : type_set < > ;
2014-04-09 04:26:45 +08:00
template < typename Policies >
struct _methods_t
{
using _database_t = typename Policies : : _database_t ;
template < typename T >
2014-04-11 02:20:59 +08:00
using _new_statement_t = typename Policies : : template _new_statement_t < no_group_by_t , T > ;
2014-04-09 04:26:45 +08:00
template < typename . . . Args >
auto group_by ( Args . . . args )
2014-04-11 02:20:59 +08:00
- > _new_statement_t < group_by_t < void , Args . . . > >
2014-04-09 04:26:45 +08:00
{
2014-04-10 02:54:28 +08:00
return { * static_cast < typename Policies : : _statement_t * > ( this ) , group_by_t < void , Args . . . > { args . . . } } ;
2014-04-09 04:26:45 +08:00
}
template < typename . . . Args >
auto dynamic_group_by ( Args . . . args )
2014-04-11 02:20:59 +08:00
- > _new_statement_t < group_by_t < _database_t , Args . . . > >
2014-04-09 04:26:45 +08:00
{
static_assert ( not std : : is_same < _database_t , void > : : value , " dynamic_group_by must not be called in a static statement " ) ;
2014-04-10 02:54:28 +08:00
return { * static_cast < typename Policies : : _statement_t * > ( this ) , vendor : : group_by_t < _database_t , Args . . . > { args . . . } } ;
2014-04-09 04:26:45 +08:00
}
} ;
2014-02-08 05:52:02 +08:00
} ;
// Interpreters
template < typename Context , typename Database , typename . . . Expressions >
2014-02-19 00:45:08 +08:00
struct serializer_t < Context , group_by_t < Database , Expressions . . . > >
2014-01-18 22:50:16 +08:00
{
2014-02-08 05:52:02 +08:00
using T = group_by_t < Database , Expressions . . . > ;
2014-01-18 22:50:16 +08:00
static Context & _ ( const T & t , Context & context )
{
2014-02-08 05:52:02 +08:00
if ( sizeof . . . ( Expressions ) = = 0 and t . _dynamic_expressions . empty ( ) )
2014-01-18 22:50:16 +08:00
return context ;
context < < " GROUP BY " ;
interpret_tuple ( t . _expressions , ' , ' , context ) ;
2014-02-08 05:52:02 +08:00
if ( sizeof . . . ( Expressions ) and not t . _dynamic_expressions . empty ( ) )
2014-01-18 22:50:16 +08:00
context < < ' , ' ;
interpret_list ( t . _dynamic_expressions , ' , ' , context ) ;
return context ;
}
} ;
2014-02-08 05:52:02 +08:00
template < typename Context >
2014-02-19 00:45:08 +08:00
struct serializer_t < Context , no_group_by_t >
2014-02-08 05:52:02 +08:00
{
using T = no_group_by_t ;
static Context & _ ( const T & t , Context & context )
{
return context ;
}
} ;
2014-01-18 22:50:16 +08:00
}
}
# endif