2013-08-14 04:43:10 +08:00
/*
2014-03-27 23:43:36 +08:00
* Copyright ( c ) 2013 - 2014 , Roland Bock
2013-08-14 04:43:10 +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_JOIN_H
# define SQLPP_JOIN_H
# include <sqlpp11/type_traits.h>
2013-10-05 23:35:40 +08:00
# include <sqlpp11/on.h>
2014-01-18 22:50:16 +08:00
# include <sqlpp11/vendor/noop.h>
2013-08-14 04:43:10 +08:00
namespace sqlpp
{
struct inner_join_t
{
2013-11-01 19:23:50 +08:00
template < typename Db >
struct _is_supported
{
static constexpr bool value = Db : : _supports_inner_join ;
} ;
2013-10-05 23:35:40 +08:00
static constexpr const char * _name = " INNER " ;
2013-08-14 04:43:10 +08:00
} ;
struct outer_join_t
{
2013-11-01 19:23:50 +08:00
template < typename Db >
struct _is_supported
{
static constexpr bool value = Db : : _supports_outer_join ;
} ;
2013-10-05 23:35:40 +08:00
static constexpr const char * _name = " OUTER " ;
2013-08-14 04:43:10 +08:00
} ;
2013-10-05 23:35:40 +08:00
struct left_outer_join_t
2013-08-14 04:43:10 +08:00
{
2013-11-01 19:23:50 +08:00
template < typename Db >
struct _is_supported
{
static constexpr bool value = Db : : _supports_left_outer_join ;
} ;
2013-10-05 23:35:40 +08:00
static constexpr const char * _name = " LEFT OUTER " ;
2013-08-14 04:43:10 +08:00
} ;
2013-10-05 23:35:40 +08:00
struct right_outer_join_t
2013-08-14 04:43:10 +08:00
{
2013-11-01 19:23:50 +08:00
template < typename Db >
struct _is_supported
{
static constexpr bool value = Db : : _supports_right_outer_join ;
} ;
2013-10-05 23:35:40 +08:00
static constexpr const char * _name = " RIGHT OUTER " ;
2013-08-14 04:43:10 +08:00
} ;
2014-01-18 22:50:16 +08:00
template < typename JoinType , typename Lhs , typename Rhs , typename On = vendor : : noop >
struct join_t
{
2014-05-16 05:47:16 +08:00
using _traits = make_traits < no_value_t , tag : : table , tag : : join > ;
using _recursive_traits = make_recursive_traits < Lhs , Rhs > ;
2014-05-15 14:00:03 +08:00
2014-01-27 18:45:46 +08:00
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 ( not is_join_t < Rhs > : : value , " rhs argument for join must not be a join " ) ;
2014-01-18 22:50:16 +08:00
static_assert ( vendor : : is_noop < On > : : value or is_on_t < On > : : value , " invalid on expression in join().on() " ) ;
2014-05-15 14:00:03 +08:00
static_assert ( : : sqlpp : : detail : : is_disjunct_from < typename Lhs : : _provided_tables , typename Rhs : : _provided_tables > : : value , " joined tables must not be identical " ) ;
2014-01-18 22:50:16 +08:00
2014-05-15 14:00:03 +08:00
static_assert ( _recursive_traits : : _required_tables : : size : : value = = 0 , " joined tables must not depend on other tables " ) ;
2014-01-18 22:50:16 +08:00
template < typename OnT >
using set_on_t = join_t < JoinType , Lhs , Rhs , OnT > ;
template < typename . . . Expr >
2014-01-30 15:43:55 +08:00
auto on ( Expr . . . expr )
- > set_on_t < on_t < void , Expr . . . > >
2014-01-18 22:50:16 +08:00
{
static_assert ( vendor : : is_noop < On > : : value , " cannot call on() twice for a single join() " ) ;
return { _lhs ,
_rhs ,
2014-01-30 15:43:55 +08:00
{ std : : tuple < Expr . . . > { expr . . . } }
2014-01-18 22:50:16 +08:00
} ;
}
template < typename T >
2014-01-30 15:43:55 +08:00
join_t < inner_join_t , join_t , T > join ( T t )
2014-01-18 22:50:16 +08:00
{
static_assert ( not vendor : : is_noop < On > : : value , " join type requires on() " ) ;
2014-01-30 15:43:55 +08:00
return { * this , t } ;
2014-01-18 22:50:16 +08:00
}
template < typename T >
2014-01-30 15:43:55 +08:00
join_t < inner_join_t , join_t , T > inner_join ( T t )
2014-01-18 22:50:16 +08:00
{
static_assert ( not vendor : : is_noop < On > : : value , " join type requires on() " ) ;
2014-01-30 15:43:55 +08:00
return { * this , t } ;
2014-01-18 22:50:16 +08:00
}
template < typename T >
2014-01-30 15:43:55 +08:00
join_t < outer_join_t , join_t , T > outer_join ( T t )
2014-01-18 22:50:16 +08:00
{
static_assert ( not vendor : : is_noop < On > : : value , " join type requires on() " ) ;
2014-01-30 15:43:55 +08:00
return { * this , t } ;
2014-01-18 22:50:16 +08:00
}
template < typename T >
2014-01-30 15:43:55 +08:00
join_t < left_outer_join_t , join_t , T > left_outer_join ( T t )
2014-01-18 22:50:16 +08:00
{
static_assert ( not vendor : : is_noop < On > : : value , " join type requires on() " ) ;
2014-01-30 15:43:55 +08:00
return { * this , t } ;
2014-01-18 22:50:16 +08:00
}
template < typename T >
2014-01-30 15:43:55 +08:00
join_t < right_outer_join_t , join_t , T > right_outer_join ( T t )
2014-01-18 22:50:16 +08:00
{
static_assert ( not vendor : : is_noop < On > : : value , " join type requires on() " ) ;
2014-01-30 15:43:55 +08:00
return { * this , t } ;
2014-01-18 22:50:16 +08:00
}
Lhs _lhs ;
Rhs _rhs ;
On _on ;
} ;
2014-01-17 16:56:35 +08:00
2014-01-18 23:10:46 +08:00
namespace vendor
{
template < typename Context , typename JoinType , typename Lhs , typename Rhs , typename On >
2014-02-19 00:45:08 +08:00
struct serializer_t < Context , join_t < JoinType , Lhs , Rhs , On > >
2014-01-17 16:56:35 +08:00
{
2014-01-18 23:10:46 +08:00
using T = join_t < JoinType , Lhs , Rhs , On > ;
static Context & _ ( const T & t , Context & context )
{
static_assert ( not vendor : : is_noop < On > : : value , " joined tables require on() " ) ;
2014-02-19 00:45:08 +08:00
serialize ( t . _lhs , context ) ;
2014-01-18 23:10:46 +08:00
context < < JoinType : : _name ;
context < < " JOIN " ;
2014-02-19 00:45:08 +08:00
serialize ( t . _rhs , context ) ;
serialize ( t . _on , context ) ;
2014-01-18 23:10:46 +08:00
return context ;
}
} ;
2014-01-17 16:56:35 +08:00
2014-01-18 23:10:46 +08:00
}
2013-08-14 04:43:10 +08:00
}
# endif