2012-08-26 06:48:39 +00:00
# pragma once
2017-11-24 13:55:31 +00:00
# include <Common/FieldVisitors.h>
2017-04-01 09:19:00 +00:00
# include <DataTypes/DataTypeArray.h>
# include <DataTypes/DataTypesNumber.h>
# include <DataTypes/DataTypeDate.h>
# include <DataTypes/DataTypeDateTime.h>
# include <DataTypes/DataTypeString.h>
# include <DataTypes/DataTypeNullable.h>
# include <Columns/ColumnArray.h>
# include <Columns/ColumnString.h>
2017-07-21 06:35:58 +00:00
# include <Columns/ColumnConst.h>
2017-04-01 09:19:00 +00:00
# include <Columns/ColumnNullable.h>
# include <Functions/IFunction.h>
# include <Functions/ObjectPool.h>
2017-07-21 06:35:58 +00:00
# include <Functions/FunctionHelpers.h>
2017-04-01 09:19:00 +00:00
# include <Common/StringUtils.h>
2012-08-26 06:48:39 +00:00
2017-06-06 17:18:32 +00:00
# include <ext/range.h>
2014-12-02 12:42:20 +00:00
2014-01-08 16:33:28 +00:00
# include <unordered_map>
2016-05-23 00:40:28 +00:00
# include <numeric>
2013-10-11 11:43:50 +00:00
2012-08-26 06:48:39 +00:00
namespace DB
{
2016-01-11 21:46:36 +00:00
namespace ErrorCodes
{
2017-04-01 07:20:54 +00:00
extern const int ZERO_ARRAY_OR_TUPLE_INDEX ;
extern const int SIZES_OF_ARRAYS_DOESNT_MATCH ;
extern const int PARAMETERS_TO_AGGREGATE_FUNCTIONS_MUST_BE_LITERALS ;
2017-07-27 23:23:13 +00:00
extern const int LOGICAL_ERROR ;
2016-01-11 21:46:36 +00:00
}
2017-05-27 15:45:25 +00:00
/** Array functions:
2012-08-26 06:48:39 +00:00
*
2017-06-01 13:41:58 +00:00
* array ( c1 , c2 , . . . ) - create an array .
* arrayElement ( arr , i ) - get the array element by index . If index is not constant and out of range - return default value of data type .
2017-05-27 15:45:25 +00:00
* The index begins with 1. Also , the index can be negative - then it is counted from the end of the array .
* has ( arr , x ) - whether there is an element x in the array .
* indexOf ( arr , x ) - returns the index of the element x ( starting with 1 ) , if it exists in the array , or 0 if it is not .
* arrayEnumerate ( arr ) - Returns the array [ 1 , 2 , 3 , . . . , length ( arr ) ]
2015-07-23 11:11:10 +00:00
*
2017-05-27 15:45:25 +00:00
* arrayUniq ( arr ) - counts the number of different elements in the array ,
* arrayUniq ( arr1 , arr2 , . . . ) - counts the number of different tuples from the elements in the corresponding positions in several arrays .
2015-07-23 11:11:10 +00:00
*
* arrayEnumerateUniq ( arr )
2017-06-01 13:41:58 +00:00
* - outputs an array parallel ( having same size ) to this , where for each element specified
* how much times this element was encountered before ( including this element ) among elements with the same value .
2017-05-27 15:45:25 +00:00
* For example : arrayEnumerateUniq ( [ 10 , 20 , 10 , 30 ] ) = [ 1 , 1 , 2 , 1 ]
2015-07-23 11:11:10 +00:00
* arrayEnumerateUniq ( arr1 , arr2 . . . )
2017-05-27 15:45:25 +00:00
* - for tuples from elements in the corresponding positions in several arrays .
2015-07-26 10:40:32 +00:00
*
2017-05-27 15:45:25 +00:00
* emptyArrayToSingle ( arr ) - replace empty arrays with arrays of one element with a default value .
2015-12-13 10:43:49 +00:00
*
2017-05-27 15:45:25 +00:00
* arrayReduce ( ' agg ' , arr1 , . . . ) - apply the aggregate function ` agg ` to arrays ` arr1 . . . `
2017-06-01 13:41:58 +00:00
* If multiple arrays passed , then elements on corresponding positions are passed as multiple arguments to the aggregate function .
2017-08-25 13:54:08 +00:00
*
* arrayConcat ( arr1 , . . . ) - concatenate arrays .
*
* arraySlice ( arr , offset , length ) - make slice of array . Offsets and length may be < 0 or Null
2017-09-01 12:23:06 +00:00
* - if offset < 0 , indexation from right element
2017-08-25 13:54:08 +00:00
* - if length < 0 , length = len ( array ) - ( positive_index ( offset ) - 1 ) + length
* indexation :
* [ 1 , 2 , 3 , 4 , 5 , 6 ]
2017-09-01 12:23:06 +00:00
* [ - 6 , - 5 , - 4 , - 3 , - 2 , - 1 ]
2017-08-25 13:54:08 +00:00
* examples :
2017-09-01 12:23:06 +00:00
* arraySlice ( [ 1 , 2 , 3 , 4 , 5 , 6 ] , - 4 , 2 ) - > [ 3 , 4 ]
2017-08-25 13:54:08 +00:00
* arraySlice ( [ 1 , 2 , 3 , 4 , 5 , 6 ] , 2 , - 1 ) - > [ 2 , 3 , 4 , 5 ] ( 6 - ( 2 - 1 ) + ( - 1 ) = 4 )
2017-09-01 12:23:06 +00:00
* arraySlice ( [ 1 , 2 , 3 , 4 , 5 , 6 ] , - 5 , - 1 ) = arraySlice ( [ 1 , 2 , 3 , 4 , 5 , 6 ] , 2 , - 1 ) - > [ 2 , 3 , 4 , 5 ]
2017-08-25 13:54:08 +00:00
*
* arrayPushBack ( arr , x ) , arrayPushFront ( arr , x )
* arrayPopBack ( arr ) , arrayPopFront ( arr )
2012-08-26 06:48:39 +00:00
*/
2014-04-10 17:28:06 +00:00
2012-08-26 06:48:39 +00:00
class FunctionArray : public IFunction
{
2014-11-12 17:23:26 +00:00
public :
2017-04-01 07:20:54 +00:00
static constexpr auto name = " array " ;
static FunctionPtr create ( const Context & context ) ;
2016-07-09 06:33:44 +00:00
2017-04-01 07:20:54 +00:00
FunctionArray ( const Context & context ) ;
2014-11-12 17:23:26 +00:00
2017-07-24 01:00:31 +00:00
bool useDefaultImplementationForNulls ( ) const override { return false ; }
2017-12-07 05:53:23 +00:00
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2016-09-11 07:40:47 +00:00
2017-04-01 07:20:54 +00:00
bool isVariadic ( ) const override { return true ; }
size_t getNumberOfArguments ( ) const override { return 0 ; }
2016-12-29 19:38:10 +00:00
2017-04-01 07:20:54 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
2014-04-17 14:37:59 +00:00
2017-04-01 07:20:54 +00:00
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
2014-04-17 14:37:59 +00:00
2016-08-11 16:47:28 +00:00
private :
2017-04-01 07:20:54 +00:00
String getName ( ) const override ;
2014-04-17 14:37:59 +00:00
2017-04-01 07:20:54 +00:00
bool addField ( DataTypePtr type_res , const Field & f , Array & arr ) const ;
2014-04-17 14:37:59 +00:00
2016-08-11 16:47:28 +00:00
private :
2017-04-01 07:20:54 +00:00
const Context & context ;
2016-08-11 16:47:28 +00:00
} ;
2014-04-17 14:37:59 +00:00
2016-09-11 07:40:47 +00:00
namespace ArrayImpl
{
2017-04-01 07:20:54 +00:00
class NullMapBuilder ;
2016-09-11 07:40:47 +00:00
}
2015-02-01 08:19:11 +00:00
2016-08-11 16:47:28 +00:00
class FunctionArrayElement : public IFunction
{
public :
2017-04-01 07:20:54 +00:00
static constexpr auto name = " arrayElement " ;
static FunctionPtr create ( const Context & context ) ;
2015-02-01 08:19:11 +00:00
2017-04-01 07:20:54 +00:00
String getName ( ) const override ;
2015-02-01 08:19:11 +00:00
2017-12-07 05:53:23 +00:00
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2017-04-01 07:20:54 +00:00
size_t getNumberOfArguments ( ) const override { return 2 ; }
2016-12-29 19:38:10 +00:00
2017-04-01 07:20:54 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
2015-02-01 08:19:11 +00:00
2017-04-01 07:20:54 +00:00
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
2015-02-01 08:19:11 +00:00
2016-08-11 16:47:28 +00:00
private :
2017-04-01 07:20:54 +00:00
void perform ( Block & block , const ColumnNumbers & arguments , size_t result , ArrayImpl : : NullMapBuilder & builder ) ;
2016-09-11 07:40:47 +00:00
2017-04-01 07:20:54 +00:00
template < typename DataType >
bool executeNumberConst ( Block & block , const ColumnNumbers & arguments , size_t result , const Field & index ,
ArrayImpl : : NullMapBuilder & builder ) ;
2015-02-01 08:19:11 +00:00
2017-04-01 07:20:54 +00:00
template < typename IndexType , typename DataType >
bool executeNumber ( Block & block , const ColumnNumbers & arguments , size_t result , const PaddedPODArray < IndexType > & indices ,
ArrayImpl : : NullMapBuilder & builder ) ;
2015-02-01 08:19:11 +00:00
2017-04-01 07:20:54 +00:00
bool executeStringConst ( Block & block , const ColumnNumbers & arguments , size_t result , const Field & index ,
ArrayImpl : : NullMapBuilder & builder ) ;
2015-02-01 08:19:11 +00:00
2017-04-01 07:20:54 +00:00
template < typename IndexType >
bool executeString ( Block & block , const ColumnNumbers & arguments , size_t result , const PaddedPODArray < IndexType > & indices ,
ArrayImpl : : NullMapBuilder & builder ) ;
2015-02-01 08:19:11 +00:00
2017-04-01 07:20:54 +00:00
bool executeGenericConst ( Block & block , const ColumnNumbers & arguments , size_t result , const Field & index ,
ArrayImpl : : NullMapBuilder & builder ) ;
2012-11-02 19:10:43 +00:00
2017-04-01 07:20:54 +00:00
template < typename IndexType >
bool executeGeneric ( Block & block , const ColumnNumbers & arguments , size_t result , const PaddedPODArray < IndexType > & indices ,
ArrayImpl : : NullMapBuilder & builder ) ;
2012-11-02 19:10:43 +00:00
2017-04-01 07:20:54 +00:00
template < typename IndexType >
bool executeConst ( Block & block , const ColumnNumbers & arguments , size_t result , const PaddedPODArray < IndexType > & indices ,
ArrayImpl : : NullMapBuilder & builder ) ;
2012-11-02 19:10:43 +00:00
2017-04-01 07:20:54 +00:00
template < typename IndexType >
bool executeArgument ( Block & block , const ColumnNumbers & arguments , size_t result , ArrayImpl : : NullMapBuilder & builder ) ;
2012-11-02 19:10:43 +00:00
2017-05-27 15:45:25 +00:00
/** For a tuple array, the function is evaluated component-wise for each element of the tuple.
2017-04-01 07:20:54 +00:00
*/
bool executeTuple ( Block & block , const ColumnNumbers & arguments , size_t result ) ;
2012-11-02 19:10:43 +00:00
} ;
2016-07-09 04:39:57 +00:00
/// For has.
2012-12-15 20:01:46 +00:00
struct IndexToOne
{
2017-04-01 07:20:54 +00:00
using ResultType = UInt8 ;
2017-12-02 02:47:12 +00:00
static bool apply ( size_t , ResultType & current ) { current = 1 ; return false ; }
2012-12-15 20:01:46 +00:00
} ;
2016-07-09 04:39:57 +00:00
/// For indexOf.
2012-12-15 20:01:46 +00:00
struct IndexIdentity
{
2017-04-01 07:20:54 +00:00
using ResultType = UInt64 ;
2017-05-27 15:45:25 +00:00
/// The index is returned starting from 1.
2017-04-01 07:20:54 +00:00
static bool apply ( size_t j , ResultType & current ) { current = j + 1 ; return false ; }
2012-12-26 15:40:37 +00:00
} ;
2016-07-09 04:39:57 +00:00
/// For countEqual.
2012-12-26 15:40:37 +00:00
struct IndexCount
{
2017-04-01 07:20:54 +00:00
using ResultType = UInt32 ;
2017-12-02 02:47:12 +00:00
static bool apply ( size_t , ResultType & current ) { + + current ; return true ; }
2012-12-15 20:01:46 +00:00
} ;
2015-10-12 07:05:54 +00:00
template < typename T , typename U , typename IndexConv >
2012-12-15 20:01:46 +00:00
struct ArrayIndexNumImpl
{
2016-09-20 15:59:47 +00:00
private :
2015-10-12 07:05:54 +00:00
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wsign-compare"
2017-04-01 07:20:54 +00:00
/// compares `lhs` against `i`-th element of `rhs`
2017-07-21 06:35:58 +00:00
static bool compare ( const T & lhs , const PaddedPODArray < U > & rhs , const size_t i ) { return lhs = = rhs [ i ] ; }
2017-04-01 07:20:54 +00:00
/// compares `lhs against `rhs`, third argument unused
2017-07-21 06:35:58 +00:00
static bool compare ( const T & lhs , const U & rhs , size_t ) { return lhs = = rhs ; }
2015-10-12 07:05:54 +00:00
# pragma GCC diagnostic pop
2015-09-18 12:40:42 +00:00
2017-12-02 02:47:12 +00:00
static bool hasNull ( const PaddedPODArray < UInt8 > & null_map , size_t i )
2017-04-01 07:20:54 +00:00
{
return null_map [ i ] = = 1 ;
}
/// Both function arguments are ordinary.
template < typename ScalarOrVector >
static void vectorCase1 (
const PaddedPODArray < T > & data , const ColumnArray : : Offsets_t & offsets ,
const ScalarOrVector & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
if ( compare ( data [ current_offset + j ] , value , i ) )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
/// The 2nd function argument is nullable.
template < typename ScalarOrVector >
static void vectorCase2 (
const PaddedPODArray < T > & data , const ColumnArray : : Offsets_t & offsets ,
const ScalarOrVector & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > & null_map_item )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
2017-12-02 02:47:12 +00:00
if ( ! hasNull ( null_map_item , i ) & & compare ( data [ current_offset + j ] , value , i ) )
2017-04-01 07:20:54 +00:00
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
/// The 1st function argument is a non-constant array of nullable values.
template < typename ScalarOrVector >
static void vectorCase3 (
const PaddedPODArray < T > & data , const ColumnArray : : Offsets_t & offsets ,
const ScalarOrVector & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > & null_map_data )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
if ( null_map_data [ current_offset + j ] = = 1 )
{
}
else if ( compare ( data [ current_offset + j ] , value , i ) )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
/// The 1st function argument is a non-constant array of nullable values.
/// The 2nd function argument is nullable.
template < typename ScalarOrVector >
static void vectorCase4 (
const PaddedPODArray < T > & data , const ColumnArray : : Offsets_t & offsets ,
const ScalarOrVector & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > & null_map_data ,
const PaddedPODArray < UInt8 > & null_map_item )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
bool hit = false ;
if ( null_map_data [ current_offset + j ] = = 1 )
{
2017-12-02 02:47:12 +00:00
if ( hasNull ( null_map_item , i ) )
2017-04-01 07:20:54 +00:00
hit = true ;
}
else if ( compare ( data [ current_offset + j ] , value , i ) )
hit = true ;
if ( hit )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
2016-09-12 14:16:21 +00:00
2016-09-20 15:59:47 +00:00
public :
2017-04-01 07:20:54 +00:00
template < typename ScalarOrVector >
static void vector (
const PaddedPODArray < T > & data , const ColumnArray : : Offsets_t & offsets ,
const ScalarOrVector & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > * null_map_data ,
const PaddedPODArray < UInt8 > * null_map_item )
{
/// Processing is split into 4 cases.
2017-07-21 06:35:58 +00:00
if ( ! null_map_data & & ! null_map_item )
2017-04-01 07:20:54 +00:00
vectorCase1 ( data , offsets , value , result ) ;
2017-07-21 06:35:58 +00:00
else if ( ! null_map_data & & null_map_item )
2017-04-01 07:20:54 +00:00
vectorCase2 ( data , offsets , value , result , * null_map_item ) ;
2017-07-21 06:35:58 +00:00
else if ( null_map_data & & ! null_map_item )
2017-04-01 07:20:54 +00:00
vectorCase3 ( data , offsets , value , result , * null_map_data ) ;
else
vectorCase4 ( data , offsets , value , result , * null_map_data , * null_map_item ) ;
}
2016-09-12 14:16:21 +00:00
} ;
2016-09-15 21:27:34 +00:00
/// Specialization that catches internal errors.
2016-09-12 14:16:21 +00:00
template < typename T , typename IndexConv >
struct ArrayIndexNumImpl < T , Null , IndexConv >
{
2017-04-01 07:20:54 +00:00
template < typename ScalarOrVector >
static void vector (
2017-12-02 02:47:12 +00:00
const PaddedPODArray < T > & , const ColumnArray : : Offsets_t & ,
const ScalarOrVector & ,
PaddedPODArray < typename IndexConv : : ResultType > & ,
const PaddedPODArray < UInt8 > * ,
const PaddedPODArray < UInt8 > * )
2017-04-01 07:20:54 +00:00
{
throw Exception { " Internal error " , ErrorCodes : : LOGICAL_ERROR } ;
}
2016-09-12 14:16:21 +00:00
} ;
2016-09-15 12:14:25 +00:00
/// Implementation for arrays of numbers when the 2nd function argument
/// is a NULL value.
2016-09-12 14:16:21 +00:00
template < typename T , typename IndexConv >
struct ArrayIndexNumNullImpl
{
2017-04-01 07:20:54 +00:00
static void vector (
2017-12-02 02:47:12 +00:00
const PaddedPODArray < T > & /*data*/ , const ColumnArray : : Offsets_t & offsets ,
2017-04-01 07:20:54 +00:00
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > * null_map_data )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
2017-07-21 06:35:58 +00:00
if ( ! null_map_data )
2017-04-01 07:20:54 +00:00
return ;
const auto & null_map_ref = * null_map_data ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
if ( null_map_ref [ current_offset + j ] = = 1 )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
2012-12-15 20:01:46 +00:00
} ;
2016-09-15 12:14:25 +00:00
/// Implementation for arrays of strings when the 2nd function argument
/// is a NULL value.
template < typename IndexConv >
struct ArrayIndexStringNullImpl
{
2017-04-01 07:20:54 +00:00
static void vector_const (
2017-12-02 02:47:12 +00:00
const ColumnString : : Chars_t & /*data*/ , const ColumnArray : : Offsets_t & offsets , const ColumnString : : Offsets_t & /*string_offsets*/ ,
2017-04-01 07:20:54 +00:00
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > * null_map_data )
{
const auto size = offsets . size ( ) ;
result . resize ( size ) ;
2017-07-21 06:35:58 +00:00
if ( ! null_map_data )
2017-04-01 07:20:54 +00:00
return ;
const auto & null_map_ref = * null_map_data ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
const auto array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
size_t k = ( current_offset = = 0 & & j = = 0 ) ? 0 : current_offset + j - 1 ;
if ( null_map_ref [ k ] = = 1 )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
2016-09-15 12:14:25 +00:00
} ;
2012-12-15 20:01:46 +00:00
template < typename IndexConv >
struct ArrayIndexStringImpl
{
2017-04-01 07:20:54 +00:00
static void vector_const (
const ColumnString : : Chars_t & data , const ColumnArray : : Offsets_t & offsets , const ColumnString : : Offsets_t & string_offsets ,
const String & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > * null_map_data )
{
const auto size = offsets . size ( ) ;
const auto value_size = value . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
const auto array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
ColumnArray : : Offset_t string_pos = current_offset = = 0 & & j = = 0
? 0
: string_offsets [ current_offset + j - 1 ] ;
ColumnArray : : Offset_t string_size = string_offsets [ current_offset + j ] - string_pos ;
size_t k = ( current_offset = = 0 & & j = = 0 ) ? 0 : current_offset + j - 1 ;
if ( null_map_data & & ( ( * null_map_data ) [ k ] = = 1 ) )
{
}
else if ( string_size = = value_size + 1 & & 0 = = memcmp ( value . data ( ) , & data [ string_pos ] , value_size ) )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
static void vector_vector (
const ColumnString : : Chars_t & data , const ColumnArray : : Offsets_t & offsets , const ColumnString : : Offsets_t & string_offsets ,
const ColumnString : : Chars_t & item_values , const ColumnString : : Offsets_t & item_offsets ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > * null_map_data ,
const PaddedPODArray < UInt8 > * null_map_item )
{
const auto size = offsets . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
const auto array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
const auto value_pos = 0 = = i ? 0 : item_offsets [ i - 1 ] ;
const auto value_size = item_offsets [ i ] - value_pos ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
ColumnArray : : Offset_t string_pos = current_offset = = 0 & & j = = 0
? 0
: string_offsets [ current_offset + j - 1 ] ;
ColumnArray : : Offset_t string_size = string_offsets [ current_offset + j ] - string_pos ;
bool hit = false ;
size_t k = ( current_offset = = 0 & & j = = 0 ) ? 0 : current_offset + j - 1 ;
if ( null_map_data & & ( ( * null_map_data ) [ k ] = = 1 ) )
{
if ( null_map_item & & ( ( * null_map_item ) [ i ] = = 1 ) )
hit = true ;
}
else if ( string_size = = value_size & & 0 = = memcmp ( & item_values [ value_pos ] , & data [ string_pos ] , value_size ) )
hit = true ;
if ( hit )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
2012-12-15 20:01:46 +00:00
} ;
2016-09-20 15:59:47 +00:00
/// Catch-all implementation for arrays of arbitary type.
/// To compare with constant value, create non-constant column with single element,
/// and pass is_value_has_single_element_to_compare = true.
2016-07-09 04:39:57 +00:00
template < typename IndexConv , bool is_value_has_single_element_to_compare >
struct ArrayIndexGenericImpl
{
2016-09-20 15:59:47 +00:00
private :
2017-04-01 07:20:54 +00:00
/// Both function arguments are ordinary.
static void vectorCase1 (
const IColumn & data , const ColumnArray : : Offsets_t & offsets ,
const IColumn & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
if ( 0 = = data . compareAt ( current_offset + j , is_value_has_single_element_to_compare ? 0 : i , value , 1 ) )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
/// The 2nd function argument is nullable.
static void vectorCase2 (
const IColumn & data , const ColumnArray : : Offsets_t & offsets ,
const IColumn & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > & null_map_item )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
if ( ( null_map_item [ i ] = = 0 ) & &
( 0 = = data . compareAt ( current_offset + j , is_value_has_single_element_to_compare ? 0 : i , value , 1 ) ) )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
/// The 1st function argument is a non-constant array of nullable values.
static void vectorCase3 (
const IColumn & data , const ColumnArray : : Offsets_t & offsets ,
const IColumn & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > & null_map_data )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
if ( null_map_data [ current_offset + j ] = = 1 )
{
}
else if ( 0 = = data . compareAt ( current_offset + j , is_value_has_single_element_to_compare ? 0 : i , value , 1 ) )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
/// The 1st function argument is a non-constant array of nullable values.
/// The 2nd function argument is nullable.
static void vectorCase4 (
const IColumn & data , const ColumnArray : : Offsets_t & offsets ,
const IColumn & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > & null_map_data ,
const PaddedPODArray < UInt8 > & null_map_item )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
bool hit = false ;
if ( null_map_data [ current_offset + j ] = = 1 )
{
if ( null_map_item [ i ] = = 1 )
hit = true ;
}
else if ( 0 = = data . compareAt ( current_offset + j , is_value_has_single_element_to_compare ? 0 : i , value , 1 ) )
hit = true ;
if ( hit )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
}
}
2016-09-20 15:59:47 +00:00
public :
2017-04-01 07:20:54 +00:00
static void vector (
const IColumn & data , const ColumnArray : : Offsets_t & offsets ,
const IColumn & value ,
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > * null_map_data ,
const PaddedPODArray < UInt8 > * null_map_item )
{
/// Processing is split into 4 cases.
2017-07-21 06:35:58 +00:00
if ( ! null_map_data & & ! null_map_item )
2017-04-01 07:20:54 +00:00
vectorCase1 ( data , offsets , value , result ) ;
2017-07-21 06:35:58 +00:00
else if ( ! null_map_data & & null_map_item )
2017-04-01 07:20:54 +00:00
vectorCase2 ( data , offsets , value , result , * null_map_item ) ;
2017-07-21 06:35:58 +00:00
else if ( null_map_data & & ! null_map_item )
2017-04-01 07:20:54 +00:00
vectorCase3 ( data , offsets , value , result , * null_map_data ) ;
else
vectorCase4 ( data , offsets , value , result , * null_map_data , * null_map_item ) ;
}
2016-07-09 04:39:57 +00:00
} ;
2016-09-20 15:59:47 +00:00
/// Catch-all implementation for arrays of arbitary type
/// when the 2nd function argument is a NULL value.
template < typename IndexConv >
struct ArrayIndexGenericNullImpl
{
2017-04-01 07:20:54 +00:00
static void vector (
2017-12-02 02:47:12 +00:00
const IColumn & /*data*/ , const ColumnArray : : Offsets_t & offsets ,
2017-04-01 07:20:54 +00:00
PaddedPODArray < typename IndexConv : : ResultType > & result ,
const PaddedPODArray < UInt8 > * null_map_data )
{
size_t size = offsets . size ( ) ;
result . resize ( size ) ;
2017-07-21 06:35:58 +00:00
if ( ! null_map_data )
2017-04-01 07:20:54 +00:00
return ;
const auto & null_map_ref = * null_map_data ;
ColumnArray : : Offset_t current_offset = 0 ;
for ( size_t i = 0 ; i < size ; + + i )
{
size_t array_size = offsets [ i ] - current_offset ;
typename IndexConv : : ResultType current = 0 ;
for ( size_t j = 0 ; j < array_size ; + + j )
{
if ( null_map_ref [ current_offset + j ] = = 1 )
{
if ( ! IndexConv : : apply ( j , current ) )
break ;
}
}
result [ i ] = current ;
current_offset = offsets [ i ] ;
}
}
2016-09-20 15:59:47 +00:00
} ;
2012-12-15 20:01:46 +00:00
template < typename IndexConv , typename Name >
class FunctionArrayIndex : public IFunction
2012-11-02 19:10:43 +00:00
{
2014-11-12 17:23:26 +00:00
public :
2017-04-01 07:20:54 +00:00
static constexpr auto name = Name : : name ;
2017-12-02 02:47:12 +00:00
static FunctionPtr create ( const Context & ) { return std : : make_shared < FunctionArrayIndex > ( ) ; }
2014-11-12 17:23:26 +00:00
2012-11-02 19:10:43 +00:00
private :
2017-04-01 07:20:54 +00:00
using ResultColumnType = ColumnVector < typename IndexConv : : ResultType > ;
template < typename T >
bool executeNumber ( Block & block , const ColumnNumbers & arguments , size_t result )
{
2017-07-24 04:14:35 +00:00
return executeNumberNumber < T , UInt8 > ( block , arguments , result )
| | executeNumberNumber < T , UInt16 > ( block , arguments , result )
| | executeNumberNumber < T , UInt32 > ( block , arguments , result )
| | executeNumberNumber < T , UInt64 > ( block , arguments , result )
| | executeNumberNumber < T , Int8 > ( block , arguments , result )
| | executeNumberNumber < T , Int16 > ( block , arguments , result )
| | executeNumberNumber < T , Int32 > ( block , arguments , result )
| | executeNumberNumber < T , Int64 > ( block , arguments , result )
| | executeNumberNumber < T , Float32 > ( block , arguments , result )
| | executeNumberNumber < T , Float64 > ( block , arguments , result )
2017-04-01 07:20:54 +00:00
| | executeNumberNumber < T , Null > ( block , arguments , result ) ;
}
template < typename T , typename U >
bool executeNumberNumber ( Block & block , const ColumnNumbers & arguments , size_t result )
{
2017-07-21 06:35:58 +00:00
const ColumnArray * col_array = checkAndGetColumn < ColumnArray > ( block . getByPosition ( arguments [ 0 ] ) . column . get ( ) ) ;
2017-04-01 07:20:54 +00:00
if ( ! col_array )
return false ;
2017-07-21 06:35:58 +00:00
const ColumnVector < T > * col_nested = checkAndGetColumn < ColumnVector < T > > ( & col_array - > getData ( ) ) ;
2017-04-01 07:20:54 +00:00
if ( ! col_nested )
return false ;
const auto col_res = std : : make_shared < ResultColumnType > ( ) ;
2017-07-21 06:35:58 +00:00
block . getByPosition ( result ) . column = col_res ;
2017-04-01 07:20:54 +00:00
/// Null maps of the 1st and second function arguments,
/// if it applies.
const PaddedPODArray < UInt8 > * null_map_data = nullptr ;
const PaddedPODArray < UInt8 > * null_map_item = nullptr ;
if ( arguments . size ( ) > 2 )
{
2017-07-21 06:35:58 +00:00
const auto & null_map1 = block . getByPosition ( arguments [ 2 ] ) . column ;
2017-04-01 07:20:54 +00:00
if ( null_map1 )
null_map_data = & static_cast < const ColumnUInt8 & > ( * null_map1 ) . getData ( ) ;
2017-07-21 06:35:58 +00:00
const auto & null_map2 = block . getByPosition ( arguments [ 3 ] ) . column ;
2017-04-01 07:20:54 +00:00
if ( null_map2 )
null_map_item = & static_cast < const ColumnUInt8 & > ( * null_map2 ) . getData ( ) ;
}
2017-07-21 06:35:58 +00:00
const auto item_arg = block . getByPosition ( arguments [ 1 ] ) . column . get ( ) ;
2017-04-01 07:20:54 +00:00
2017-12-09 10:14:45 +00:00
if ( item_arg - > onlyNull ( ) )
2017-04-01 07:20:54 +00:00
ArrayIndexNumNullImpl < T , IndexConv > : : vector ( col_nested - > getData ( ) , col_array - > getOffsets ( ) ,
col_res - > getData ( ) , null_map_data ) ;
2017-07-21 06:35:58 +00:00
else if ( const auto item_arg_const = checkAndGetColumnConst < ColumnVector < U > > ( item_arg ) )
2017-04-01 07:20:54 +00:00
ArrayIndexNumImpl < T , U , IndexConv > : : vector ( col_nested - > getData ( ) , col_array - > getOffsets ( ) ,
2017-07-21 06:35:58 +00:00
item_arg_const - > template getValue < U > ( ) , col_res - > getData ( ) , null_map_data , nullptr ) ;
else if ( const auto item_arg_vector = checkAndGetColumn < ColumnVector < U > > ( item_arg ) )
2017-04-01 07:20:54 +00:00
ArrayIndexNumImpl < T , U , IndexConv > : : vector ( col_nested - > getData ( ) , col_array - > getOffsets ( ) ,
item_arg_vector - > getData ( ) , col_res - > getData ( ) , null_map_data , null_map_item ) ;
else
return false ;
return true ;
}
bool executeString ( Block & block , const ColumnNumbers & arguments , size_t result )
{
2017-07-21 06:35:58 +00:00
const ColumnArray * col_array = checkAndGetColumn < ColumnArray > ( block . getByPosition ( arguments [ 0 ] ) . column . get ( ) ) ;
2017-04-01 07:20:54 +00:00
if ( ! col_array )
return false ;
2017-07-21 06:35:58 +00:00
const ColumnString * col_nested = checkAndGetColumn < ColumnString > ( & col_array - > getData ( ) ) ;
2017-04-01 07:20:54 +00:00
if ( ! col_nested )
return false ;
const auto col_res = std : : make_shared < ResultColumnType > ( ) ;
2017-07-21 06:35:58 +00:00
block . getByPosition ( result ) . column = col_res ;
2017-04-01 07:20:54 +00:00
/// Null maps of the 1st and second function arguments,
/// if it applies.
const PaddedPODArray < UInt8 > * null_map_data = nullptr ;
const PaddedPODArray < UInt8 > * null_map_item = nullptr ;
if ( arguments . size ( ) > 2 )
{
2017-07-21 06:35:58 +00:00
const auto & col1 = block . getByPosition ( arguments [ 2 ] ) . column ;
2017-04-01 07:20:54 +00:00
if ( col1 )
null_map_data = & static_cast < const ColumnUInt8 & > ( * col1 ) . getData ( ) ;
2017-07-21 06:35:58 +00:00
const auto & col2 = block . getByPosition ( arguments [ 3 ] ) . column ;
2017-04-01 07:20:54 +00:00
if ( col2 )
null_map_item = & static_cast < const ColumnUInt8 & > ( * col2 ) . getData ( ) ;
}
2017-07-21 06:35:58 +00:00
const auto item_arg = block . getByPosition ( arguments [ 1 ] ) . column . get ( ) ;
2017-04-01 07:20:54 +00:00
2017-12-09 10:14:45 +00:00
if ( item_arg - > onlyNull ( ) )
2017-04-01 07:20:54 +00:00
ArrayIndexStringNullImpl < IndexConv > : : vector_const ( col_nested - > getChars ( ) , col_array - > getOffsets ( ) ,
col_nested - > getOffsets ( ) , col_res - > getData ( ) , null_map_data ) ;
2017-07-21 06:35:58 +00:00
else if ( const auto item_arg_const = checkAndGetColumnConstStringOrFixedString ( item_arg ) )
2017-04-01 07:20:54 +00:00
ArrayIndexStringImpl < IndexConv > : : vector_const ( col_nested - > getChars ( ) , col_array - > getOffsets ( ) ,
2017-07-21 06:35:58 +00:00
col_nested - > getOffsets ( ) , item_arg_const - > getValue < String > ( ) , col_res - > getData ( ) ,
2017-04-01 07:20:54 +00:00
null_map_data ) ;
2017-07-21 06:35:58 +00:00
else if ( const auto item_arg_vector = checkAndGetColumn < ColumnString > ( item_arg ) )
2017-04-01 07:20:54 +00:00
ArrayIndexStringImpl < IndexConv > : : vector_vector ( col_nested - > getChars ( ) , col_array - > getOffsets ( ) ,
col_nested - > getOffsets ( ) , item_arg_vector - > getChars ( ) , item_arg_vector - > getOffsets ( ) ,
col_res - > getData ( ) , null_map_data , null_map_item ) ;
else
return false ;
return true ;
}
bool executeConst ( Block & block , const ColumnNumbers & arguments , size_t result )
{
2017-07-21 06:35:58 +00:00
const ColumnConst * col_array = checkAndGetColumnConst < ColumnArray > ( block . getByPosition ( arguments [ 0 ] ) . column . get ( ) ) ;
2017-04-01 07:20:54 +00:00
if ( ! col_array )
return false ;
2017-07-21 06:35:58 +00:00
Array arr = col_array - > getValue < Array > ( ) ;
2017-04-01 07:20:54 +00:00
2017-07-21 06:35:58 +00:00
const auto item_arg = block . getByPosition ( arguments [ 1 ] ) . column . get ( ) ;
2017-12-09 10:14:45 +00:00
if ( item_arg - > isColumnConst ( ) )
2017-04-01 07:20:54 +00:00
{
typename IndexConv : : ResultType current = 0 ;
const auto & value = ( * item_arg ) [ 0 ] ;
for ( size_t i = 0 , size = arr . size ( ) ; i < size ; + + i )
{
if ( applyVisitor ( FieldVisitorAccurateEquals ( ) , arr [ i ] , value ) )
{
if ( ! IndexConv : : apply ( i , current ) )
break ;
}
}
2017-12-10 22:44:04 +00:00
block . getByPosition ( result ) . column = block . getByPosition ( result ) . type - > createColumnConst (
2017-04-01 07:20:54 +00:00
item_arg - > size ( ) ,
static_cast < typename NearestFieldType < typename IndexConv : : ResultType > : : Type > ( current ) ) ;
}
else
{
/// Null map of the 2nd function argument, if it applies.
const PaddedPODArray < UInt8 > * null_map = nullptr ;
if ( arguments . size ( ) > 2 )
{
2017-07-21 06:35:58 +00:00
const auto & col = block . getByPosition ( arguments [ 3 ] ) . column ;
2017-04-01 07:20:54 +00:00
if ( col )
null_map = & static_cast < const ColumnUInt8 & > ( * col ) . getData ( ) ;
}
const auto size = item_arg - > size ( ) ;
const auto col_res = std : : make_shared < ResultColumnType > ( size ) ;
2017-07-21 06:35:58 +00:00
block . getByPosition ( result ) . column = col_res ;
2017-04-01 07:20:54 +00:00
auto & data = col_res - > getData ( ) ;
for ( size_t row = 0 ; row < size ; + + row )
{
const auto & value = ( * item_arg ) [ row ] ;
data [ row ] = 0 ;
for ( size_t i = 0 , size = arr . size ( ) ; i < size ; + + i )
{
bool hit = false ;
if ( arr [ i ] . isNull ( ) )
{
if ( null_map & & ( ( * null_map ) [ row ] = = 1 ) )
hit = true ;
}
else if ( applyVisitor ( FieldVisitorAccurateEquals ( ) , arr [ i ] , value ) )
hit = true ;
if ( hit )
{
if ( ! IndexConv : : apply ( i , data [ row ] ) )
break ;
}
}
}
}
return true ;
}
bool executeGeneric ( Block & block , const ColumnNumbers & arguments , size_t result )
{
2017-07-21 06:35:58 +00:00
const ColumnArray * col_array = checkAndGetColumn < ColumnArray > ( block . getByPosition ( arguments [ 0 ] ) . column . get ( ) ) ;
2017-04-01 07:20:54 +00:00
if ( ! col_array )
return false ;
const IColumn & col_nested = col_array - > getData ( ) ;
2017-07-21 06:35:58 +00:00
const IColumn & item_arg = * block . getByPosition ( arguments [ 1 ] ) . column ;
2017-04-01 07:20:54 +00:00
const auto col_res = std : : make_shared < ResultColumnType > ( ) ;
2017-07-21 06:35:58 +00:00
block . getByPosition ( result ) . column = col_res ;
2017-04-01 07:20:54 +00:00
/// Null maps of the 1st and second function arguments,
/// if it applies.
const PaddedPODArray < UInt8 > * null_map_data = nullptr ;
const PaddedPODArray < UInt8 > * null_map_item = nullptr ;
if ( arguments . size ( ) > 2 )
{
2017-07-21 06:35:58 +00:00
const auto & null_map1 = block . getByPosition ( arguments [ 2 ] ) . column ;
2017-04-01 07:20:54 +00:00
if ( null_map1 )
null_map_data = & static_cast < const ColumnUInt8 & > ( * null_map1 ) . getData ( ) ;
2017-07-21 06:35:58 +00:00
const auto & null_map2 = block . getByPosition ( arguments [ 3 ] ) . column ;
2017-04-01 07:20:54 +00:00
if ( null_map2 )
null_map_item = & static_cast < const ColumnUInt8 & > ( * null_map2 ) . getData ( ) ;
}
2017-12-09 10:14:45 +00:00
if ( item_arg . onlyNull ( ) )
2017-04-01 07:20:54 +00:00
ArrayIndexGenericNullImpl < IndexConv > : : vector ( col_nested , col_array - > getOffsets ( ) ,
col_res - > getData ( ) , null_map_data ) ;
2017-12-09 10:14:45 +00:00
else if ( item_arg . isColumnConst ( ) )
2017-04-01 07:20:54 +00:00
ArrayIndexGenericImpl < IndexConv , true > : : vector ( col_nested , col_array - > getOffsets ( ) ,
2017-07-21 06:35:58 +00:00
static_cast < const ColumnConst & > ( item_arg ) . getDataColumn ( ) , col_res - > getData ( ) , /// TODO This is wrong.
2017-04-01 07:20:54 +00:00
null_map_data , nullptr ) ;
else
{
/// If item_arg is tuple and have constants.
2017-12-15 03:47:43 +00:00
if ( ColumnPtr materialized_tuple = item_arg . convertToFullColumnIfConst ( ) )
2017-04-01 07:20:54 +00:00
ArrayIndexGenericImpl < IndexConv , false > : : vector (
col_nested , col_array - > getOffsets ( ) , * materialized_tuple , col_res - > getData ( ) ,
null_map_data , null_map_item ) ;
else
ArrayIndexGenericImpl < IndexConv , false > : : vector (
col_nested , col_array - > getOffsets ( ) , item_arg , col_res - > getData ( ) ,
null_map_data , null_map_item ) ;
}
return true ;
}
2016-07-09 04:39:57 +00:00
2012-11-02 19:10:43 +00:00
public :
2017-04-01 07:20:54 +00:00
/// Get function name.
String getName ( ) const override
{
return name ;
}
2017-07-24 01:00:31 +00:00
bool useDefaultImplementationForNulls ( ) const override { return false ; }
2017-04-01 07:20:54 +00:00
size_t getNumberOfArguments ( ) const override { return 2 ; }
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override
{
2017-07-21 06:35:58 +00:00
const DataTypeArray * array_type = checkAndGetDataType < DataTypeArray > ( arguments [ 0 ] . get ( ) ) ;
2017-04-01 07:20:54 +00:00
if ( ! array_type )
throw Exception ( " First argument for function " + getName ( ) + " must be an array. " ,
ErrorCodes : : ILLEGAL_TYPE_OF_ARGUMENT ) ;
2017-12-09 06:32:22 +00:00
if ( ! arguments [ 1 ] - > onlyNull ( ) )
2017-04-01 07:20:54 +00:00
{
2017-12-09 07:32:32 +00:00
DataTypePtr observed_type0 = removeNullable ( array_type - > getNestedType ( ) ) ;
DataTypePtr observed_type1 = removeNullable ( arguments [ 1 ] ) ;
2017-04-01 07:20:54 +00:00
2017-12-09 06:32:22 +00:00
if ( ! ( observed_type0 - > isNumber ( ) & & observed_type1 - > isNumber ( ) )
2017-04-01 07:20:54 +00:00
& & ! observed_type0 - > equals ( * observed_type1 ) )
throw Exception ( " Types of array and 2nd argument of function "
+ getName ( ) + " must be identical up to nullability. Passed: "
+ arguments [ 0 ] - > getName ( ) + " and " + arguments [ 1 ] - > getName ( ) + " . " ,
ErrorCodes : : ILLEGAL_TYPE_OF_ARGUMENT ) ;
}
return std : : make_shared < DataTypeNumber < typename IndexConv : : ResultType > > ( ) ;
}
/// Perform function on the given block.
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override
{
/// If one or both arguments passed to this function are nullable,
2017-06-01 13:41:58 +00:00
/// we create a new block that contains non-nullable arguments:
2017-04-01 07:20:54 +00:00
/// - if the 1st argument is a non-constant array of nullable values,
/// it is turned into a non-constant array of ordinary values + a null
/// byte map;
/// - if the 2nd argument is a nullable value, it is turned into an
/// ordinary value + a null byte map.
/// Note that since constant arrays have quite a specific structure
/// (they are vectors of Fields, which may represent the NULL value),
/// they do not require any preprocessing
/// Check if the 1st function argument is a non-constant array of nullable
/// values.
bool is_nullable ;
const ColumnArray * col_array = nullptr ;
2017-07-21 06:35:58 +00:00
col_array = checkAndGetColumn < ColumnArray > ( block . getByPosition ( arguments [ 0 ] ) . column . get ( ) ) ;
2017-04-01 07:20:54 +00:00
if ( col_array )
2017-12-09 10:14:45 +00:00
is_nullable = col_array - > getData ( ) . isColumnNullable ( ) ;
2017-04-01 07:20:54 +00:00
else
is_nullable = false ;
/// Check nullability of the 2nd function argument.
2017-12-09 10:14:45 +00:00
bool is_arg_nullable = block . getByPosition ( arguments [ 1 ] ) . column - > isColumnNullable ( ) ;
2017-04-01 07:20:54 +00:00
if ( ! is_nullable & & ! is_arg_nullable )
{
/// Simple case: no nullable value is passed.
perform ( block , arguments , result ) ;
}
else
{
/// Template of the block on which we will actually apply the function.
/// Its elements will be filled later.
Block source_block =
{
/// 1st function argument (data)
{
} ,
/// 2nd function argument
{
} ,
/// 1st argument null map
{
} ,
/// 2nd argument null map
{
} ,
/// Function result.
{
nullptr ,
2017-07-21 06:35:58 +00:00
block . getByPosition ( result ) . type ,
2017-04-01 07:20:54 +00:00
" "
}
} ;
if ( is_nullable )
{
const auto & nullable_col = static_cast < const ColumnNullable & > ( col_array - > getData ( ) ) ;
2017-12-14 03:56:56 +00:00
const auto & nested_col = nullable_col . getNestedColumnPtr ( ) ;
2017-04-01 07:20:54 +00:00
auto & data = source_block . getByPosition ( 0 ) ;
2017-12-15 02:36:40 +00:00
data . column = ColumnArray : : create ( nested_col , col_array - > getOffsetsPtr ( ) ) ;
2017-07-21 06:35:58 +00:00
data . type = static_cast < const DataTypeNullable & > ( * block . getByPosition ( arguments [ 0 ] ) . type ) . getNestedType ( ) ;
2017-04-01 07:20:54 +00:00
auto & null_map = source_block . getByPosition ( 2 ) ;
2017-12-14 03:56:56 +00:00
null_map . column = nullable_col . getNullMapColumnPtr ( ) ;
2017-04-01 07:20:54 +00:00
null_map . type = std : : make_shared < DataTypeUInt8 > ( ) ;
}
else
{
auto & data = source_block . getByPosition ( 0 ) ;
2017-07-21 06:35:58 +00:00
data = block . getByPosition ( arguments [ 0 ] ) ;
2017-04-01 07:20:54 +00:00
}
if ( is_arg_nullable )
{
2017-07-21 06:35:58 +00:00
const auto & col = block . getByPosition ( arguments [ 1 ] ) . column ;
2017-04-01 07:20:54 +00:00
const auto & nullable_col = static_cast < const ColumnNullable & > ( * col ) ;
auto & arg = source_block . getByPosition ( 1 ) ;
2017-12-14 03:56:56 +00:00
arg . column = nullable_col . getNestedColumnPtr ( ) ;
2017-07-21 06:35:58 +00:00
arg . type = static_cast < const DataTypeNullable & > ( * block . getByPosition ( arguments [ 1 ] ) . type ) . getNestedType ( ) ;
2017-04-01 07:20:54 +00:00
auto & null_map = source_block . getByPosition ( 3 ) ;
2017-12-14 03:56:56 +00:00
null_map . column = nullable_col . getNullMapColumnPtr ( ) ;
2017-04-01 07:20:54 +00:00
null_map . type = std : : make_shared < DataTypeUInt8 > ( ) ;
}
else
{
auto & arg = source_block . getByPosition ( 1 ) ;
2017-07-21 06:35:58 +00:00
arg = block . getByPosition ( arguments [ 1 ] ) ;
2017-04-01 07:20:54 +00:00
}
/// Now perform the function.
perform ( source_block , { 0 , 1 , 2 , 3 } , 4 ) ;
/// Move the result to its final position.
const ColumnWithTypeAndName & source_col = source_block . getByPosition ( 4 ) ;
ColumnWithTypeAndName & dest_col = block . getByPosition ( result ) ;
dest_col . column = std : : move ( source_col . column ) ;
}
}
2016-09-12 14:16:21 +00:00
private :
2017-04-01 07:20:54 +00:00
/// Perform function on the given block. Internal version.
void perform ( Block & block , const ColumnNumbers & arguments , size_t result )
{
2017-07-24 04:14:35 +00:00
if ( ! ( executeNumber < UInt8 > ( block , arguments , result )
| | executeNumber < UInt16 > ( block , arguments , result )
| | executeNumber < UInt32 > ( block , arguments , result )
| | executeNumber < UInt64 > ( block , arguments , result )
| | executeNumber < Int8 > ( block , arguments , result )
| | executeNumber < Int16 > ( block , arguments , result )
| | executeNumber < Int32 > ( block , arguments , result )
| | executeNumber < Int64 > ( block , arguments , result )
| | executeNumber < Float32 > ( block , arguments , result )
| | executeNumber < Float64 > ( block , arguments , result )
2017-04-01 07:20:54 +00:00
| | executeConst ( block , arguments , result )
| | executeString ( block , arguments , result )
| | executeGeneric ( block , arguments , result ) ) )
throw Exception {
2017-07-21 06:35:58 +00:00
" Illegal column " + block . getByPosition ( arguments [ 0 ] ) . column - > getName ( )
2017-04-01 07:20:54 +00:00
+ " of first argument of function " + getName ( ) ,
ErrorCodes : : ILLEGAL_COLUMN } ;
}
2012-11-02 19:10:43 +00:00
} ;
2016-08-11 16:47:28 +00:00
2013-10-21 11:36:44 +00:00
class FunctionArrayEnumerate : public IFunction
{
public :
2017-04-01 07:20:54 +00:00
static constexpr auto name = " arrayEnumerate " ;
static FunctionPtr create ( const Context & context ) ;
2014-11-12 17:23:26 +00:00
2017-04-01 07:20:54 +00:00
String getName ( ) const override ;
2013-10-21 11:36:44 +00:00
2017-04-01 07:20:54 +00:00
size_t getNumberOfArguments ( ) const override { return 1 ; }
2017-12-09 10:14:45 +00:00
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2016-12-29 19:38:10 +00:00
2017-04-01 07:20:54 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
2013-10-21 11:36:44 +00:00
2017-04-01 07:20:54 +00:00
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
2013-10-21 11:36:44 +00:00
} ;
2015-07-23 11:11:10 +00:00
2017-05-27 15:45:25 +00:00
/// Counts the number of different elements in the array, or the number of different tuples from the elements at the corresponding positions in several arrays.
/// NOTE The implementation partially matches arrayEnumerateUniq.
2015-07-23 11:11:10 +00:00
class FunctionArrayUniq : public IFunction
{
public :
2017-04-01 07:20:54 +00:00
static constexpr auto name = " arrayUniq " ;
static FunctionPtr create ( const Context & context ) ;
2015-07-23 11:11:10 +00:00
2017-04-01 07:20:54 +00:00
String getName ( ) const override ;
2015-07-23 11:11:10 +00:00
2017-04-01 07:20:54 +00:00
bool isVariadic ( ) const override { return true ; }
size_t getNumberOfArguments ( ) const override { return 0 ; }
2017-12-09 10:14:45 +00:00
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2016-12-29 19:38:10 +00:00
2017-04-01 07:20:54 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
2015-07-23 11:11:10 +00:00
2017-04-01 07:20:54 +00:00
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
2015-07-23 11:11:10 +00:00
private :
2017-06-01 13:41:58 +00:00
/// Initially allocate a piece of memory for 512 elements. NOTE: This is just a guess.
2017-04-01 07:20:54 +00:00
static constexpr size_t INITIAL_SIZE_DEGREE = 9 ;
2015-07-23 11:11:10 +00:00
2017-04-01 07:20:54 +00:00
template < typename T >
bool executeNumber ( const ColumnArray * array , const IColumn * null_map , ColumnUInt32 : : Container_t & res_values ) ;
2015-07-23 11:11:10 +00:00
2017-04-01 07:20:54 +00:00
bool executeString ( const ColumnArray * array , const IColumn * null_map , ColumnUInt32 : : Container_t & res_values ) ;
2015-07-23 11:11:10 +00:00
2017-04-01 07:20:54 +00:00
bool execute128bit (
const ColumnArray : : Offsets_t & offsets ,
2017-12-13 01:27:53 +00:00
const ColumnRawPtrs & columns ,
const ColumnRawPtrs & null_maps ,
2017-04-01 07:20:54 +00:00
ColumnUInt32 : : Container_t & res_values ,
bool has_nullable_columns ) ;
2015-07-23 11:11:10 +00:00
2017-04-01 07:20:54 +00:00
void executeHashed (
const ColumnArray : : Offsets_t & offsets ,
2017-12-13 01:27:53 +00:00
const ColumnRawPtrs & columns ,
2017-04-01 07:20:54 +00:00
ColumnUInt32 : : Container_t & res_values ) ;
2015-07-23 11:11:10 +00:00
} ;
2013-10-11 11:43:50 +00:00
class FunctionArrayEnumerateUniq : public IFunction
{
public :
2017-04-01 07:20:54 +00:00
static constexpr auto name = " arrayEnumerateUniq " ;
static FunctionPtr create ( const Context & context ) ;
2014-11-12 17:23:26 +00:00
2017-04-01 07:20:54 +00:00
String getName ( ) const override ;
2013-10-11 11:43:50 +00:00
2017-04-01 07:20:54 +00:00
bool isVariadic ( ) const override { return true ; }
size_t getNumberOfArguments ( ) const override { return 0 ; }
2017-12-09 10:14:45 +00:00
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2016-12-29 19:38:10 +00:00
2017-04-01 07:20:54 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
2013-10-11 11:43:50 +00:00
2017-04-01 07:20:54 +00:00
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
2013-10-24 12:53:24 +00:00
private :
2017-06-01 13:41:58 +00:00
/// Initially allocate a piece of memory for 512 elements. NOTE: This is just a guess.
2017-04-01 07:20:54 +00:00
static constexpr size_t INITIAL_SIZE_DEGREE = 9 ;
2013-10-24 12:53:24 +00:00
2017-04-01 07:20:54 +00:00
template < typename T >
bool executeNumber ( const ColumnArray * array , const IColumn * null_map , ColumnUInt32 : : Container_t & res_values ) ;
2013-10-11 11:43:50 +00:00
2017-04-01 07:20:54 +00:00
bool executeString ( const ColumnArray * array , const IColumn * null_map , ColumnUInt32 : : Container_t & res_values ) ;
2013-10-11 11:43:50 +00:00
2017-04-01 07:20:54 +00:00
bool execute128bit (
const ColumnArray : : Offsets_t & offsets ,
2017-12-13 01:27:53 +00:00
const ColumnRawPtrs & columns ,
const ColumnRawPtrs & null_maps ,
2017-04-01 07:20:54 +00:00
ColumnUInt32 : : Container_t & res_values ,
bool has_nullable_columns ) ;
2013-12-24 11:56:38 +00:00
2017-04-01 07:20:54 +00:00
void executeHashed (
const ColumnArray : : Offsets_t & offsets ,
2017-12-13 01:27:53 +00:00
const ColumnRawPtrs & columns ,
2017-04-01 07:20:54 +00:00
ColumnUInt32 : : Container_t & res_values ) ;
2013-10-11 11:43:50 +00:00
} ;
2012-11-02 19:10:43 +00:00
2014-10-28 13:43:22 +00:00
template < typename Type > struct TypeToColumnType { using ColumnType = ColumnVector < Type > ; } ;
template < > struct TypeToColumnType < String > { using ColumnType = ColumnString ; } ;
template < typename DataType > struct DataTypeToName : TypeName < typename DataType : : FieldType > { } ;
template < > struct DataTypeToName < DataTypeDate > { static std : : string get ( ) { return " Date " ; } } ;
template < > struct DataTypeToName < DataTypeDateTime > { static std : : string get ( ) { return " DateTime " ; } } ;
template < typename DataType >
2014-11-12 17:23:26 +00:00
struct FunctionEmptyArray : public IFunction
2014-10-28 13:43:22 +00:00
{
2017-04-01 07:20:54 +00:00
static constexpr auto base_name = " emptyArray " ;
static const String name ;
2017-12-02 02:47:12 +00:00
static FunctionPtr create ( const Context & ) { return std : : make_shared < FunctionEmptyArray > ( ) ; }
2014-11-12 17:23:26 +00:00
2014-12-02 12:42:20 +00:00
private :
2017-04-01 07:20:54 +00:00
String getName ( ) const override
{
return name ;
}
size_t getNumberOfArguments ( ) const override { return 0 ; }
2017-12-02 02:47:12 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & /*arguments*/ ) const override
2017-04-01 07:20:54 +00:00
{
return std : : make_shared < DataTypeArray > ( std : : make_shared < DataType > ( ) ) ;
}
2017-12-02 02:47:12 +00:00
void executeImpl ( Block & block , const ColumnNumbers & /*arguments*/ , size_t result ) override
2017-04-01 07:20:54 +00:00
{
using UnderlyingColumnType = typename TypeToColumnType < typename DataType : : FieldType > : : ColumnType ;
2017-12-14 01:43:19 +00:00
block . getByPosition ( result ) . column = ColumnArray : : create (
2017-04-01 07:20:54 +00:00
std : : make_shared < UnderlyingColumnType > ( ) ,
std : : make_shared < ColumnArray : : ColumnOffsets_t > ( block . rows ( ) , 0 ) ) ;
}
2014-10-28 13:43:22 +00:00
} ;
2014-11-12 17:23:26 +00:00
template < typename DataType >
2017-07-16 03:05:40 +00:00
const String FunctionEmptyArray < DataType > : : name = FunctionEmptyArray : : base_name + String ( DataTypeToName < DataType > : : get ( ) ) ;
2014-11-12 17:23:26 +00:00
2014-12-02 12:42:20 +00:00
class FunctionRange : public IFunction
{
public :
2017-04-01 07:20:54 +00:00
static constexpr auto name = " range " ;
static FunctionPtr create ( const Context & ) { return std : : make_shared < FunctionRange > ( ) ; }
2014-12-02 12:42:20 +00:00
private :
2017-04-01 07:20:54 +00:00
String getName ( ) const override ;
2014-12-02 12:42:20 +00:00
2017-04-01 07:20:54 +00:00
size_t getNumberOfArguments ( ) const override { return 1 ; }
2017-12-09 10:14:45 +00:00
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2016-12-29 19:38:10 +00:00
2017-04-01 07:20:54 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
2014-12-02 12:42:20 +00:00
2017-04-01 07:20:54 +00:00
template < typename T >
2017-07-21 06:35:58 +00:00
bool executeInternal ( Block & block , const IColumn * arg , const size_t result ) ;
2014-12-02 12:42:20 +00:00
2017-04-01 07:20:54 +00:00
void executeImpl ( Block & block , const ColumnNumbers & arguments , const size_t result ) override ;
2014-12-02 12:42:20 +00:00
} ;
2014-10-28 13:43:22 +00:00
2015-07-26 10:40:32 +00:00
class FunctionEmptyArrayToSingle : public IFunction
{
public :
2017-04-01 07:20:54 +00:00
static constexpr auto name = " emptyArrayToSingle " ;
static FunctionPtr create ( const Context & context ) ;
2015-07-26 10:40:32 +00:00
2017-04-01 07:20:54 +00:00
String getName ( ) const override ;
2015-07-26 10:40:32 +00:00
2017-04-01 07:20:54 +00:00
size_t getNumberOfArguments ( ) const override { return 1 ; }
2017-12-09 10:14:45 +00:00
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2016-12-29 19:38:10 +00:00
2017-04-01 07:20:54 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
2015-07-26 10:40:32 +00:00
2017-04-01 07:20:54 +00:00
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
2015-07-26 10:40:32 +00:00
} ;
2015-10-19 21:07:24 +00:00
class FunctionArrayReverse : public IFunction
{
public :
2017-06-10 09:04:31 +00:00
static constexpr auto name = " arrayReverse " ;
2017-04-01 07:20:54 +00:00
static FunctionPtr create ( const Context & context ) ;
2015-10-19 21:07:24 +00:00
2017-04-01 07:20:54 +00:00
String getName ( ) const override ;
2015-10-19 21:07:24 +00:00
2017-04-01 07:20:54 +00:00
size_t getNumberOfArguments ( ) const override { return 1 ; }
2017-12-09 10:14:45 +00:00
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2016-12-29 19:38:10 +00:00
2017-04-01 07:20:54 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
2015-10-19 21:07:24 +00:00
2017-04-01 07:20:54 +00:00
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
2015-10-19 21:07:24 +00:00
private :
2017-04-01 07:20:54 +00:00
bool executeConst ( Block & block , const ColumnNumbers & arguments , size_t result ) ;
template < typename T >
bool executeNumber (
const IColumn & src_data , const ColumnArray : : Offsets_t & src_offsets ,
IColumn & res_data_col ,
const ColumnNullable * nullable_col ,
ColumnNullable * nullable_res_col ) ;
bool executeFixedString (
const IColumn & src_data , const ColumnArray : : Offsets_t & src_offsets ,
IColumn & res_data_col ,
const ColumnNullable * nullable_col ,
ColumnNullable * nullable_res_col ) ;
bool executeString (
const IColumn & src_data , const ColumnArray : : Offsets_t & src_array_offsets ,
IColumn & res_data_col ,
const ColumnNullable * nullable_col ,
ColumnNullable * nullable_res_col ) ;
2015-10-19 21:07:24 +00:00
} ;
2017-01-21 04:24:28 +00:00
class IAggregateFunction ;
using AggregateFunctionPtr = std : : shared_ptr < IAggregateFunction > ;
2017-02-01 14:00:12 +00:00
/** Applies an aggregate function to array and returns its result.
2017-06-01 13:41:58 +00:00
* If aggregate function has multiple arguments , then this function can be applied to multiple arrays of the same size .
2015-12-13 10:43:49 +00:00
*/
class FunctionArrayReduce : public IFunction
{
public :
2017-04-01 07:20:54 +00:00
static constexpr auto name = " arrayReduce " ;
static FunctionPtr create ( const Context & context ) ;
2015-12-13 10:43:49 +00:00
2017-04-01 07:20:54 +00:00
String getName ( ) const override ;
2015-12-13 10:43:49 +00:00
2017-04-01 07:20:54 +00:00
bool isVariadic ( ) const override { return true ; }
size_t getNumberOfArguments ( ) const override { return 0 ; }
2016-12-29 19:38:10 +00:00
2017-04-01 07:20:54 +00:00
void getReturnTypeAndPrerequisitesImpl (
const ColumnsWithTypeAndName & arguments ,
DataTypePtr & out_return_type ,
std : : vector < ExpressionAction > & out_prerequisites ) override ;
2015-12-13 10:43:49 +00:00
2017-04-01 07:20:54 +00:00
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
2015-12-13 10:43:49 +00:00
private :
2017-04-01 07:20:54 +00:00
AggregateFunctionPtr aggregate_function ;
2015-12-13 10:43:49 +00:00
} ;
2017-08-16 17:50:12 +00:00
class FunctionArrayConcat : public IFunction
{
public :
static constexpr auto name = " arrayConcat " ;
static FunctionPtr create ( const Context & context ) ;
2017-12-08 03:52:33 +00:00
FunctionArrayConcat ( const Context & context ) : context ( context ) { } ;
2017-08-16 17:50:12 +00:00
String getName ( ) const override ;
2017-08-17 19:33:02 +00:00
bool isVariadic ( ) const override { return true ; }
size_t getNumberOfArguments ( ) const override { return 0 ; }
2017-08-16 17:50:12 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2017-12-08 03:52:33 +00:00
private :
const Context & context ;
2017-08-16 17:50:12 +00:00
} ;
2017-08-22 17:54:14 +00:00
class FunctionArraySlice : public IFunction
{
public :
static constexpr auto name = " arraySlice " ;
static FunctionPtr create ( const Context & context ) ;
String getName ( ) const override ;
2017-08-25 13:54:08 +00:00
bool isVariadic ( ) const override { return true ; }
size_t getNumberOfArguments ( ) const override { return 0 ; }
2017-08-22 17:54:14 +00:00
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
bool useDefaultImplementationForConstants ( ) const override { return true ; }
2017-08-24 13:00:23 +00:00
bool useDefaultImplementationForNulls ( ) const override { return false ; }
} ;
class FunctionArrayPush : public IFunction
{
public :
2017-12-08 03:52:33 +00:00
FunctionArrayPush ( const Context & context , bool push_front , const char * name )
: context ( context ) , push_front ( push_front ) , name ( name ) { }
2017-08-24 13:00:23 +00:00
String getName ( ) const override { return name ; }
bool isVariadic ( ) const override { return false ; }
size_t getNumberOfArguments ( ) const override { return 2 ; }
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
bool useDefaultImplementationForConstants ( ) const override { return true ; }
bool useDefaultImplementationForNulls ( ) const override { return false ; }
private :
2017-12-08 03:52:33 +00:00
const Context & context ;
2017-08-24 13:00:23 +00:00
bool push_front ;
const char * name ;
} ;
class FunctionArrayPushFront : public FunctionArrayPush
{
public :
static constexpr auto name = " arrayPushFront " ;
static FunctionPtr create ( const Context & context ) ;
2017-12-08 03:52:33 +00:00
FunctionArrayPushFront ( const Context & context ) : FunctionArrayPush ( context , true , name ) { }
2017-08-22 17:54:14 +00:00
} ;
2017-08-24 13:00:23 +00:00
class FunctionArrayPushBack : public FunctionArrayPush
{
public :
static constexpr auto name = " arrayPushBack " ;
static FunctionPtr create ( const Context & context ) ;
2017-12-08 03:52:33 +00:00
FunctionArrayPushBack ( const Context & context ) : FunctionArrayPush ( context , false , name ) { }
2017-08-24 13:00:23 +00:00
} ;
class FunctionArrayPop : public IFunction
{
public :
FunctionArrayPop ( bool pop_front , const char * name ) : pop_front ( pop_front ) , name ( name ) { }
String getName ( ) const override { return name ; }
bool isVariadic ( ) const override { return false ; }
size_t getNumberOfArguments ( ) const override { return 1 ; }
DataTypePtr getReturnTypeImpl ( const DataTypes & arguments ) const override ;
void executeImpl ( Block & block , const ColumnNumbers & arguments , size_t result ) override ;
bool useDefaultImplementationForConstants ( ) const override { return true ; }
bool useDefaultImplementationForNulls ( ) const override { return false ; }
private :
bool pop_front ;
const char * name ;
} ;
class FunctionArrayPopFront : public FunctionArrayPop
{
public :
static constexpr auto name = " arrayPopFront " ;
static FunctionPtr create ( const Context & context ) ;
FunctionArrayPopFront ( ) : FunctionArrayPop ( true , name ) { }
} ;
class FunctionArrayPopBack : public FunctionArrayPop
{
public :
static constexpr auto name = " arrayPopBack " ;
static FunctionPtr create ( const Context & context ) ;
FunctionArrayPopBack ( ) : FunctionArrayPop ( false , name ) { }
} ;
2017-08-22 17:54:14 +00:00
2017-06-01 13:41:58 +00:00
struct NameHas { static constexpr auto name = " has " ; } ;
struct NameIndexOf { static constexpr auto name = " indexOf " ; } ;
struct NameCountEqual { static constexpr auto name = " countEqual " ; } ;
2012-12-15 20:01:46 +00:00
2016-05-30 21:41:41 +00:00
using FunctionHas = FunctionArrayIndex < IndexToOne , NameHas > ;
using FunctionIndexOf = FunctionArrayIndex < IndexIdentity , NameIndexOf > ;
using FunctionCountEqual = FunctionArrayIndex < IndexCount , NameCountEqual > ;
2012-12-15 20:01:46 +00:00
2014-11-12 17:23:26 +00:00
using FunctionEmptyArrayUInt8 = FunctionEmptyArray < DataTypeUInt8 > ;
using FunctionEmptyArrayUInt16 = FunctionEmptyArray < DataTypeUInt16 > ;
using FunctionEmptyArrayUInt32 = FunctionEmptyArray < DataTypeUInt32 > ;
using FunctionEmptyArrayUInt64 = FunctionEmptyArray < DataTypeUInt64 > ;
using FunctionEmptyArrayInt8 = FunctionEmptyArray < DataTypeInt8 > ;
using FunctionEmptyArrayInt16 = FunctionEmptyArray < DataTypeInt16 > ;
using FunctionEmptyArrayInt32 = FunctionEmptyArray < DataTypeInt32 > ;
using FunctionEmptyArrayInt64 = FunctionEmptyArray < DataTypeInt64 > ;
using FunctionEmptyArrayFloat32 = FunctionEmptyArray < DataTypeFloat32 > ;
using FunctionEmptyArrayFloat64 = FunctionEmptyArray < DataTypeFloat64 > ;
using FunctionEmptyArrayDate = FunctionEmptyArray < DataTypeDate > ;
using FunctionEmptyArrayDateTime = FunctionEmptyArray < DataTypeDateTime > ;
using FunctionEmptyArrayString = FunctionEmptyArray < DataTypeString > ;
2014-10-28 13:43:22 +00:00
2012-12-15 20:01:46 +00:00
2012-08-26 06:48:39 +00:00
}