2014-01-18 22:50:16 +08:00
/*
2015-02-16 02:00:21 +08:00
* Copyright ( c ) 2013 - 2015 , 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>
2014-06-14 00:51:51 +08:00
# include <sqlpp11/expression.h>
# include <sqlpp11/interpret_tuple.h>
# include <sqlpp11/interpretable_list.h>
# include <sqlpp11/policy_update.h>
2014-11-29 21:29:54 +08:00
# include <sqlpp11/logic.h>
2014-01-18 22:50:16 +08:00
namespace sqlpp
{
2014-06-14 13:45:10 +08:00
// GROUP BY DATA
template < typename Database , typename . . . Expressions >
struct group_by_data_t
{
group_by_data_t ( Expressions . . . expressions ) :
_expressions ( expressions . . . )
{ }
group_by_data_t ( const 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 = ( group_by_data_t & & ) = default ;
~ group_by_data_t ( ) = default ;
std : : tuple < Expressions . . . > _expressions ;
interpretable_list_t < Database > _dynamic_expressions ;
} ;
2014-02-08 05:52:02 +08:00
2014-11-26 04:46:09 +08:00
struct assert_no_unknown_tables_in_group_by_t
{
using type = std : : false_type ;
template < typename T = 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 " ) ;
}
} ;
2014-06-14 13:45:10 +08:00
// GROUP BY
template < typename Database , typename . . . Expressions >
struct group_by_t
{
2014-08-28 02:43:09 +08:00
using _traits = make_traits < no_value_t , tag : : is_group_by > ;
2015-02-17 15:03:19 +08:00
using _nodes = detail : : type_vector < Expressions . . . > ;
2014-05-30 19:43:59 +08:00
2014-06-15 02:25:11 +08:00
using _is_dynamic = is_database < Database > ;
2014-05-30 19:43:59 +08:00
// Data
2014-06-14 13:45:10 +08:00
using _data_t = group_by_data_t < Database , Expressions . . . > ;
2014-05-30 19:43:59 +08:00
// Member implementation with data and methods
template < typename Policies >
struct _impl_t
{
2014-06-14 13:45:10 +08:00
template < typename Expression >
void add_ntc ( Expression expression )
{
add < Expression , std : : false_type > ( expression ) ;
}
template < typename Expression , typename TableCheckRequired = std : : true_type >
void add ( Expression expression )
{
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 ( TableCheckRequired : : value or Policies : : template _no_unknown_tables < Expression > : : value , " expression uses tables unknown to this statement in group_by::add() " ) ;
2014-11-26 17:02:48 +08:00
using _serialize_check = sqlpp : : serialize_check_t < typename Database : : _serializer_context_t , Expression > ;
_serialize_check : : _ ( ) ;
2014-06-14 13:45:10 +08:00
2014-11-29 21:29:54 +08:00
using ok = logic : : all_t < _is_dynamic : : value , is_expression_t < Expression > : : value , _serialize_check : : type : : value > ;
2014-06-14 13:45:10 +08:00
_add_impl ( expression , ok ( ) ) ; // dispatch to prevent compile messages after the static_assert
}
private :
template < typename Expression >
void _add_impl ( Expression expression , const std : : true_type & )
{
return _data . _dynamic_expressions . emplace_back ( expression ) ;
}
template < typename Expression >
void _add_impl ( Expression expression , const std : : false_type & ) ;
public :
2014-05-30 19:43:59 +08:00
_data_t _data ;
} ;
2014-11-29 18:10:01 +08:00
// Base template to be inherited by the statement
2014-05-30 19:43:59 +08:00
template < typename Policies >
2014-11-29 18:10:01 +08:00
struct _base_t
2014-05-30 19:43:59 +08:00
{
2014-06-14 13:45:10 +08:00
using _data_t = group_by_data_t < Database , Expressions . . . > ;
2014-05-30 19:43:59 +08:00
2014-06-14 13:45:10 +08:00
_impl_t < Policies > group_by ;
_impl_t < Policies > & operator ( ) ( ) { return group_by ; }
const _impl_t < Policies > & operator ( ) ( ) const { return group_by ; }
2014-05-30 19:43:59 +08:00
template < typename T >
2014-06-14 13:45:10 +08:00
static auto _get_member ( T t ) - > decltype ( t . group_by )
2014-05-30 19:43:59 +08:00
{
2014-06-14 13:45:10 +08:00
return t . group_by ;
2014-05-30 19:43:59 +08:00
}
2014-11-26 04:46:09 +08:00
using _consistency_check = typename std : : conditional < Policies : : template _no_unknown_tables < group_by_t > : : value ,
consistent_t ,
assert_no_unknown_tables_in_group_by_t > : : type ;
2014-04-09 04:26:45 +08:00
} ;
2014-02-08 05:52:02 +08:00
} ;
2014-06-14 13:45:10 +08:00
// NO GROUP BY YET
struct no_group_by_t
{
2014-08-28 02:43:09 +08:00
using _traits = make_traits < no_value_t , tag : : is_noop > ;
2015-02-17 15:03:19 +08:00
using _nodes = detail : : type_vector < > ;
2014-06-14 13:45:10 +08:00
// Data
using _data_t = no_data_t ;
// Member implementation with data and methods
template < typename Policies >
struct _impl_t
2014-01-18 22:50:16 +08:00
{
2014-06-14 13:45:10 +08:00
_data_t _data ;
} ;
2014-01-18 22:50:16 +08:00
2014-11-29 18:10:01 +08:00
// Base template to be inherited by the statement
2014-06-14 13:45:10 +08:00
template < typename Policies >
2014-11-29 18:10:01 +08:00
struct _base_t
2014-06-14 13:45:10 +08:00
{
using _data_t = no_data_t ;
_impl_t < Policies > no_group_by ;
_impl_t < Policies > & operator ( ) ( ) { return no_group_by ; }
const _impl_t < Policies > & operator ( ) ( ) const { return no_group_by ; }
template < typename T >
static auto _get_member ( T t ) - > decltype ( t . no_group_by )
{
return t . no_group_by ;
}
using _database_t = typename Policies : : _database_t ;
2014-11-28 06:11:46 +08:00
template < typename . . . T >
2014-11-29 21:29:54 +08:00
using _check = logic : : all_t < is_expression_t < T > : : value . . . > ;
2014-11-28 06:11:46 +08:00
template < typename Check , typename T >
using _new_statement_t = new_statement_t < Check : : value , Policies , no_group_by_t , T > ;
2014-06-14 13:45:10 +08:00
2014-11-18 02:05:22 +08:00
using _consistency_check = consistent_t ;
2014-06-25 03:53:25 +08:00
2014-11-28 05:16:12 +08:00
template < typename . . . Expressions >
auto group_by ( Expressions . . . expressions ) const
2014-11-28 06:11:46 +08:00
- > _new_statement_t < _check < Expressions . . . > , group_by_t < void , Expressions . . . > >
2014-06-14 13:45:10 +08:00
{
2014-11-28 05:16:12 +08:00
static_assert ( sizeof . . . ( Expressions ) , " at least one expression (e.g. a column) required in group_by() " ) ;
2014-11-28 17:10:34 +08:00
static_assert ( _check < Expressions . . . > : : value , " at least one argument is not an expression in group_by() " ) ;
2014-11-28 06:11:46 +08:00
return _group_by_impl < void > ( _check < Expressions . . . > { } , expressions . . . ) ;
2014-06-14 13:45:10 +08:00
}
2014-11-28 05:16:12 +08:00
template < typename . . . Expressions >
auto dynamic_group_by ( Expressions . . . expressions ) const
2014-11-28 06:11:46 +08:00
- > _new_statement_t < _check < Expressions . . . > , group_by_t < _database_t , Expressions . . . > >
2014-06-14 13:45:10 +08:00
{
static_assert ( not std : : is_same < _database_t , void > : : value , " dynamic_group_by must not be called in a static statement " ) ;
2014-11-28 17:10:34 +08:00
static_assert ( _check < Expressions . . . > : : value , " at least one argument is not an expression in group_by() " ) ;
2014-11-28 06:11:46 +08:00
return _group_by_impl < _database_t > ( _check < Expressions . . . > { } , expressions . . . ) ;
2014-06-14 13:45:10 +08:00
}
2014-11-28 05:16:12 +08:00
private :
template < typename Database , typename . . . Expressions >
2014-11-28 06:11:46 +08:00
auto _group_by_impl ( const std : : false_type & , Expressions . . . expressions ) const
- > bad_statement ;
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 . . . > >
2014-11-28 05:16:12 +08:00
{
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 . . . } } ;
2015-02-10 01:39:03 +08:00
}
2014-06-14 13:45:10 +08:00
} ;
} ;
// Interpreters
template < typename Context , typename Database , typename . . . Expressions >
struct serializer_t < Context , group_by_data_t < Database , Expressions . . . > >
{
2014-11-26 00:43:55 +08:00
using _serialize_check = serialize_check_of < Context , Expressions . . . > ;
2014-06-14 13:45:10 +08:00
using T = group_by_data_t < Database , Expressions . . . > ;
static Context & _ ( const T & t , Context & 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 ;
}
} ;
2014-01-18 22:50:16 +08:00
}
# endif