Merge remote-tracking branch 'upstream/master' into fix14

This commit is contained in:
proller 2017-12-04 14:27:19 +03:00
commit 67765264c2
333 changed files with 2427 additions and 7529 deletions

View File

@ -9,15 +9,12 @@ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
message (FATAL_ERROR "GCC version must be at least 7! For example, if GCC 7 is available under gcc-7, g++-7 names, do the following: export CC=gcc-7 CXX=g++-7; rm -rf CMakeCache.txt CMakeFiles; and re run cmake or ./release.")
endif ()
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Require at least clang 3.9
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.9)
message (FATAL_ERROR "Clang version must be at least 3.9! Recommended 4+")
endif ()
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4)
message (WARNING "Compilation has only been tested with Clang 4+")
# Require at least clang 5
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5)
message (FATAL_ERROR "Clang version must be at least 5!")
endif ()
else ()
message (WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang 4+ and GCC 7+.")
message (WARNING "You are using an unsupported compiler! Compilation has only been tested with Clang 5+ and GCC 7+.")
endif ()
if (CMAKE_SYSTEM MATCHES "FreeBSD")
@ -52,7 +49,7 @@ if (CMAKE_LIBRARY_ARCHITECTURE MATCHES "i386")
endif ()
if ( ( ARCH_ARM AND NOT ARCH_AARCH64 ) OR ARCH_I386)
set (ARCH_32 1)
message (WARNING "Support 32bit platforms is highly experimental")
message (WARNING "Support for 32bit platforms is highly experimental")
endif ()
set (COMMON_WARNING_FLAGS "${COMMON_WARNING_FLAGS} -Wall") # -Werror is also added inside directories with our own code.
@ -133,11 +130,11 @@ endif ()
#endif ()
if (CMAKE_VERSION VERSION_LESS "3.8.0")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++1z")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1z")
else ()
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set (CXX_FLAGS_INTERNAL_COMPILER "-std=gnu++1z")
set (CXX_FLAGS_INTERNAL_COMPILER "-std=c++1z")
endif ()
set (CMAKE_BUILD_COLOR_MAKEFILE ON)

View File

@ -1220,14 +1220,14 @@ namespace libdivide_internal {
#endif
/* Some bogus unswitch functions for unsigned types so the same (presumably templated) code can work for both signed and unsigned. */
uint32_t crash_u32(uint32_t, const libdivide_u32_t *) { abort(); return *(uint32_t *)NULL; }
uint64_t crash_u64(uint64_t, const libdivide_u64_t *) { abort(); return *(uint64_t *)NULL; }
uint32_t crash_u32(uint32_t, const libdivide_u32_t *) { abort(); }
uint64_t crash_u64(uint64_t, const libdivide_u64_t *) { abort(); }
#ifdef __APPLE__
UInt64 crash_u64(UInt64, const libdivide_u64_t *) { abort(); return *(UInt64 *)NULL; }
UInt64 crash_u64(UInt64, const libdivide_u64_t *) { abort(); }
#endif
#if LIBDIVIDE_USE_SSE2
__m128i crash_u32_vector(__m128i, const libdivide_u32_t *) { abort(); return *(__m128i *)NULL; }
__m128i crash_u64_vector(__m128i, const libdivide_u64_t *) { abort(); return *(__m128i *)NULL; }
__m128i crash_u32_vector(__m128i, const libdivide_u32_t *) { abort(); }
__m128i crash_u64_vector(__m128i, const libdivide_u64_t *) { abort(); }
#endif
template<typename IntType, typename DenomType, DenomType gen_func(IntType), int get_algo(const DenomType *), IntType do_func(IntType, const DenomType *), MAYBE_VECTOR_PARAM>

View File

@ -33,7 +33,7 @@ START_HEADERS=$(echo \
# Опция -mcx16 для того, чтобы выбиралось больше заголовочных файлов (с запасом).
# The latter options are the same that are added while building packages.
for src_file in $(echo | $CLANG -M -xc++ -std=gnu++1z -Wall -Werror -msse4 -mcx16 -mpopcnt -O3 -g -fPIC -fstack-protector -D_FORTIFY_SOURCE=2 \
for src_file in $(echo | $CLANG -M -xc++ -std=c++1z -Wall -Werror -msse4 -mcx16 -mpopcnt -O3 -g -fPIC -fstack-protector -D_FORTIFY_SOURCE=2 \
$(cat "$BUILD_PATH/include_directories.txt") \
$(echo $START_HEADERS | sed -r -e 's/[^ ]+/-include \0/g') \
- |

View File

@ -18,7 +18,7 @@ get_property (BUILD_INCLUDE_DIRECTORIES DIRECTORY ${ClickHouse_SOURCE_DIR} PROPE
string (TIMESTAMP BUILD_DATE "%Y-%m-%d" UTC)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/src/Common/config_build.cpp.in ${CONFIG_BUILD})
#set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
if (NOT NO_WERROR)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
@ -29,6 +29,8 @@ find_package (Threads)
add_subdirectory (src)
# These files are located in separate library, because they are used by Yandex.Metrika code
# in places when no dependency on whole "dbms" library is possible.
add_library(string_utils
src/Common/StringUtils.h
src/Common/StringUtils.cpp)

View File

@ -47,7 +47,7 @@ public:
this->data(place).result.change(column_arg, row_num);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
if (this->data(place).value.changeIfBetter(this->data(rhs).value))
this->data(place).result.change(this->data(rhs).result);

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionAvg(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionAvg(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

View File

@ -47,7 +47,7 @@ public:
++this->data(place).count;
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).sum += this->data(rhs).sum;
this->data(place).count += this->data(rhs).count;

View File

@ -9,7 +9,7 @@ namespace
{
template <template <typename> class Data>
AggregateFunctionPtr createAggregateFunctionBitwise(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionBitwise(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

View File

@ -62,7 +62,7 @@ public:
this->data(place).update(static_cast<const ColumnVector<T> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).update(this->data(rhs).value);
}

View File

@ -7,7 +7,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionCount(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionCount(const std::string & /*name*/, const DataTypes & /*argument_types*/, const Array & /*parameters*/)
{
return std::make_shared<AggregateFunctionCount>();
}

View File

@ -30,7 +30,7 @@ class AggregateFunctionCount final : public INullaryAggregateFunction<AggregateF
public:
String getName() const override { return "count"; }
void setArguments(const DataTypes & arguments) override
void setArguments(const DataTypes & /*arguments*/) override
{
/// You may pass some arguments. All of them are ignored.
}
@ -45,7 +45,7 @@ public:
++data(place).count;
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
data(place).count += data(rhs).count;
}
@ -86,7 +86,7 @@ public:
return std::make_shared<DataTypeUInt64>();
}
void addImpl(AggregateDataPtr place, const IColumn & column, size_t row_num, Arena * arena) const
void addImpl(AggregateDataPtr place, const IColumn & column, size_t row_num, Arena *) const
{
data(place).count += !static_cast<const ColumnNullable &>(column).isNullAt(row_num);
}
@ -97,7 +97,7 @@ public:
throw Exception("Not Nullable argument passed to aggregate function count", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
data(place).count += data(rhs).count;
}
@ -147,7 +147,7 @@ public:
is_nullable[i] = arguments[i]->isNullable() || arguments[i]->isNull();
}
void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena * arena) const override
void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena *) const override
{
for (size_t i = 0; i < number_of_arguments; ++i)
if (is_nullable[i] && static_cast<const ColumnNullable &>(*columns[i]).isNullAt(row_num))
@ -167,7 +167,7 @@ public:
return &addFree;
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
data(place).count += data(rhs).count;
}

View File

@ -62,7 +62,7 @@ public:
return std::make_shared<DataTypeArray>(data_type);
}
void setArgument(const DataTypePtr & argument) {}
void setArgument(const DataTypePtr & /*argument*/) {}
void setParameters(const Array & params) override
{

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionGroupArrayInsertAt(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionGroupArrayInsertAt(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name + ", should be 2",

View File

@ -125,7 +125,7 @@ public:
column_value.get(row_num, arr[position]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
Array & arr_lhs = data(place).value;
const Array & arr_rhs = data(rhs).value;

View File

@ -42,7 +42,7 @@ static IAggregateFunction * createWithExtraTypes(const IDataType & argument_type
}
}
AggregateFunctionPtr createAggregateFunctionGroupUniqArray(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionGroupUniqArray(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name,

View File

@ -51,7 +51,7 @@ public:
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeNumber<T>>());
}
void setArgument(const DataTypePtr & argument)
void setArgument(const DataTypePtr & /*argument*/)
{
}
@ -61,7 +61,7 @@ public:
this->data(place).value.insert(static_cast<const ColumnVector<T> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).value.merge(this->data(rhs).value);
}

View File

@ -7,37 +7,37 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionAny(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionAny(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
return AggregateFunctionPtr(createAggregateFunctionSingleValue<AggregateFunctionsSingleValue, AggregateFunctionAnyData>(name, argument_types));
}
AggregateFunctionPtr createAggregateFunctionAnyLast(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionAnyLast(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
return AggregateFunctionPtr(createAggregateFunctionSingleValue<AggregateFunctionsSingleValue, AggregateFunctionAnyLastData>(name, argument_types));
}
AggregateFunctionPtr createAggregateFunctionAnyHeavy(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionAnyHeavy(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
return AggregateFunctionPtr(createAggregateFunctionSingleValue<AggregateFunctionsSingleValue, AggregateFunctionAnyHeavyData>(name, argument_types));
}
AggregateFunctionPtr createAggregateFunctionMin(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionMin(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
return AggregateFunctionPtr(createAggregateFunctionSingleValue<AggregateFunctionsSingleValue, AggregateFunctionMinData>(name, argument_types));
}
AggregateFunctionPtr createAggregateFunctionMax(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionMax(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
return AggregateFunctionPtr(createAggregateFunctionSingleValue<AggregateFunctionsSingleValue, AggregateFunctionMaxData>(name, argument_types));
}
AggregateFunctionPtr createAggregateFunctionArgMin(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionArgMin(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
return AggregateFunctionPtr(createAggregateFunctionArgMinMax<AggregateFunctionMinData>(name, argument_types));
}
AggregateFunctionPtr createAggregateFunctionArgMax(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionArgMax(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
return AggregateFunctionPtr(createAggregateFunctionArgMinMax<AggregateFunctionMaxData>(name, argument_types));
}

View File

@ -42,14 +42,14 @@ struct SingleValueDataFixed
static_cast<ColumnVector<T> &>(to).insertDefault();
}
void write(WriteBuffer & buf, const IDataType & data_type) const
void write(WriteBuffer & buf, const IDataType & /*data_type*/) const
{
writeBinary(has(), buf);
if (has())
writeBinary(value, buf);
}
void read(ReadBuffer & buf, const IDataType & data_type)
void read(ReadBuffer & buf, const IDataType & /*data_type*/)
{
readBinary(has_value, buf);
if (has())
@ -212,14 +212,14 @@ struct __attribute__((__packed__, __aligned__(1))) SingleValueDataString
static_cast<ColumnString &>(to).insertDefault();
}
void write(WriteBuffer & buf, const IDataType & data_type) const
void write(WriteBuffer & buf, const IDataType & /*data_type*/) const
{
writeBinary(size, buf);
if (has())
buf.write(getData(), size);
}
void read(ReadBuffer & buf, const IDataType & data_type)
void read(ReadBuffer & buf, const IDataType & /*data_type*/)
{
Int32 rhs_size;
readBinary(rhs_size, buf);
@ -707,7 +707,7 @@ public:
this->data(place).changeIfBetter(column, row_num);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).changeIfBetter(this->data(rhs));
}

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionQuantile(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantile(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -34,7 +34,7 @@ AggregateFunctionPtr createAggregateFunctionQuantile(const std::string & name, c
}
AggregateFunctionPtr createAggregateFunctionQuantiles(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantiles(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

View File

@ -74,7 +74,7 @@ public:
this->data(place).sample.insert(static_cast<const ColumnVector<ArgumentFieldType> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).sample.merge(this->data(rhs).sample);
}
@ -153,7 +153,7 @@ public:
this->data(place).sample.insert(static_cast<const ColumnVector<ArgumentFieldType> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).sample.merge(this->data(rhs).sample);
}

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionQuantileDeterministic(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantileDeterministic(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -27,24 +27,24 @@ AggregateFunctionPtr createAggregateFunctionQuantileDeterministic(const std::str
const IDataType & argument_type = *argument_types[0];
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<UInt8>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<UInt16>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<UInt32>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<UInt64>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Int8>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Int16>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Int32>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Int64>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Float32>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Float64>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<DataTypeDate::FieldType, false>>();
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<UInt8>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<UInt16>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<UInt32>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<UInt64>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Int8>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Int16>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Int32>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Int64>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Float32>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<Float64>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<DataTypeDate::FieldType, false>>();
else if (typeid_cast<const DataTypeDateTime*>(&argument_type)) return std::make_shared<AggregateFunctionQuantileDeterministic<DataTypeDateTime::FieldType, false>>();
else
throw Exception("Illegal type " + argument_types[0]->getName() + " of argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
}
AggregateFunctionPtr createAggregateFunctionQuantilesDeterministic(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantilesDeterministic(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -63,17 +63,17 @@ AggregateFunctionPtr createAggregateFunctionQuantilesDeterministic(const std::st
const IDataType & argument_type = *argument_types[0];
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<UInt8>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<UInt16>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<UInt32>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<UInt64>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Int8>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Int16>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Int32>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Int64>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Float32>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Float64>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<DataTypeDate::FieldType, false>>();
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<UInt8>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<UInt16>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<UInt32>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<UInt64>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Int8>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Int16>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Int32>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Int64>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Float32>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<Float64>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<DataTypeDate::FieldType, false>>();
else if (typeid_cast<const DataTypeDateTime*>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesDeterministic<DataTypeDateTime::FieldType, false>>();
else
throw Exception("Illegal type " + argument_types[0]->getName() + " of argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);

View File

@ -80,7 +80,7 @@ public:
determinator.get64(row_num));
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).sample.merge(this->data(rhs).sample);
}
@ -165,7 +165,7 @@ public:
determinator.get64(row_num));
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).sample.merge(this->data(rhs).sample);
}

View File

@ -8,24 +8,24 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionQuantileExact(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantileExact(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
const IDataType & argument_type = *argument_types[0];
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<UInt8>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<UInt16>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<UInt32>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<UInt64>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Int8>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Int16>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Int32>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Int64>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Float32>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Float64>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type))
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<UInt8>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<UInt16>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<UInt32>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<UInt64>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Int8>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Int16>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Int32>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Int64>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Float32>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantileExact<Float64>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type))
return std::make_shared<AggregateFunctionQuantileExact<DataTypeDate::FieldType>>();
else if (typeid_cast<const DataTypeDateTime*>(&argument_type))
return std::make_shared<AggregateFunctionQuantileExact<DataTypeDateTime::FieldType>>();
@ -34,24 +34,24 @@ AggregateFunctionPtr createAggregateFunctionQuantileExact(const std::string & na
}
AggregateFunctionPtr createAggregateFunctionQuantilesExact(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantilesExact(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
const IDataType & argument_type = *argument_types[0];
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<UInt8>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<UInt16>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<UInt32>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<UInt64>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Int8>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Int16>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Int32>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Int64>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Float32>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Float64>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type))
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<UInt8>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<UInt16>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<UInt32>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<UInt64>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Int8>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Int16>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Int32>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Int64>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Float32>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<AggregateFunctionQuantilesExact<Float64>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type))
return std::make_shared<AggregateFunctionQuantilesExact<DataTypeDate::FieldType>>();
else if (typeid_cast<const DataTypeDateTime*>(&argument_type))
return std::make_shared<AggregateFunctionQuantilesExact<DataTypeDateTime::FieldType>>();

View File

@ -73,7 +73,7 @@ public:
this->data(place).array.push_back(static_cast<const ColumnVector<T> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).array.insert(this->data(rhs).array.begin(), this->data(rhs).array.end());
}
@ -157,7 +157,7 @@ public:
this->data(place).array.push_back(static_cast<const ColumnVector<T> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).array.insert(this->data(rhs).array.begin(), this->data(rhs).array.end());
}

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionQuantileExactWeighted(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantileExactWeighted(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -22,7 +22,7 @@ AggregateFunctionPtr createAggregateFunctionQuantileExactWeighted(const std::str
return res;
}
AggregateFunctionPtr createAggregateFunctionQuantilesExactWeighted(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantilesExactWeighted(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

View File

@ -81,7 +81,7 @@ public:
+= static_cast<const ColumnVector<WeightType> &>(column_weight).getData()[row_num];
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
auto & map = this->data(place).map;
const auto & rhs_map = this->data(rhs).map;
@ -198,7 +198,7 @@ public:
+= static_cast<const ColumnVector<WeightType> &>(column_weight).getData()[row_num];
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
auto & map = this->data(place).map;
const auto & rhs_map = this->data(rhs).map;

View File

@ -9,44 +9,44 @@ namespace
{
template <template <typename, bool> class FunctionTemplate>
AggregateFunctionPtr createAggregateFunctionQuantileTDigest(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantileTDigest(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
const IDataType & argument_type = *argument_types[0];
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<FunctionTemplate<UInt8, true>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<FunctionTemplate<UInt16, true>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<FunctionTemplate<UInt32, true>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<FunctionTemplate<UInt64, true>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<FunctionTemplate<Int8, true>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<FunctionTemplate<Int16, true>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<FunctionTemplate<Int32, true>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<FunctionTemplate<Int64, true>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<FunctionTemplate<Float32, true>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<FunctionTemplate<Float64, true>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type)) return std::make_shared<FunctionTemplate<DataTypeDate::FieldType, false>>();
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<FunctionTemplate<UInt8, true>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<FunctionTemplate<UInt16, true>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<FunctionTemplate<UInt32, true>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<FunctionTemplate<UInt64, true>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<FunctionTemplate<Int8, true>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<FunctionTemplate<Int16, true>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<FunctionTemplate<Int32, true>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<FunctionTemplate<Int64, true>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<FunctionTemplate<Float32, true>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<FunctionTemplate<Float64, true>>();
else if (typeid_cast<const DataTypeDate *>(&argument_type)) return std::make_shared<FunctionTemplate<DataTypeDate::FieldType, false>>();
else if (typeid_cast<const DataTypeDateTime *>(&argument_type)) return std::make_shared<FunctionTemplate<DataTypeDateTime::FieldType, false>>();
else
throw Exception("Illegal type " + argument_type.getName() + " of argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
}
template <template <typename, typename, bool> class FunctionTemplate, typename T, bool returns_float>
AggregateFunctionPtr createAggregateFunctionQuantileTDigestWeightedImpl(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantileTDigestWeightedImpl(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
const IDataType & argument_type = *argument_types[1];
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, UInt8, returns_float>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, UInt16, returns_float>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, UInt32, returns_float>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, UInt64, returns_float>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Int8, returns_float>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Int16, returns_float>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Int32, returns_float>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Int64, returns_float>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Float32, returns_float>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Float64, returns_float>>();
if (typeid_cast<const DataTypeUInt8 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, UInt8, returns_float>>();
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, UInt16, returns_float>>();
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, UInt32, returns_float>>();
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, UInt64, returns_float>>();
else if (typeid_cast<const DataTypeInt8 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Int8, returns_float>>();
else if (typeid_cast<const DataTypeInt16 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Int16, returns_float>>();
else if (typeid_cast<const DataTypeInt32 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Int32, returns_float>>();
else if (typeid_cast<const DataTypeInt64 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Int64, returns_float>>();
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Float32, returns_float>>();
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type)) return std::make_shared<FunctionTemplate<T, Float64, returns_float>>();
else
throw Exception("Illegal type " + argument_type.getName() + " of second argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
}
@ -59,27 +59,27 @@ AggregateFunctionPtr createAggregateFunctionQuantileTDigestWeighted(const std::s
const IDataType & argument_type = *argument_types[0];
if (typeid_cast<const DataTypeUInt8 *>(&argument_type))
if (typeid_cast<const DataTypeUInt8 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, UInt8, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type))
else if (typeid_cast<const DataTypeUInt16 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, UInt16, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type))
else if (typeid_cast<const DataTypeUInt32 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, UInt32, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type))
else if (typeid_cast<const DataTypeUInt64 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, UInt64, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeInt8 *>(&argument_type))
else if (typeid_cast<const DataTypeInt8 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, Int8, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeInt16 *>(&argument_type))
else if (typeid_cast<const DataTypeInt16 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, Int16, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeInt32 *>(&argument_type))
else if (typeid_cast<const DataTypeInt32 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, Int32, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeInt64 *>(&argument_type))
else if (typeid_cast<const DataTypeInt64 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, Int64, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeFloat32 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, Float32, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeFloat64 *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, Float64, true>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeDate *>(&argument_type))
else if (typeid_cast<const DataTypeDate *>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, DataTypeDate::FieldType, false>(name, argument_types, parameters);
else if (typeid_cast<const DataTypeDateTime*>(&argument_type))
return createAggregateFunctionQuantileTDigestWeightedImpl<FunctionTemplate, DataTypeDateTime::FieldType, false>(name, argument_types, parameters);

View File

@ -387,7 +387,7 @@ public:
this->data(place).digest.add(params, static_cast<const ColumnVector<T> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).digest.merge(params, this->data(rhs).digest);
}
@ -458,7 +458,7 @@ public:
static_cast<const ColumnVector<Weight> &>(column_weight).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).digest.merge(params, this->data(rhs).digest);
}
@ -522,7 +522,7 @@ public:
this->data(place).digest.add(params, static_cast<const ColumnVector<T> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).digest.merge(params, this->data(rhs).digest);
}
@ -609,7 +609,7 @@ public:
static_cast<const ColumnVector<Weight> &>(column_weight).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).digest.merge(params, this->data(rhs).digest);
}

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionQuantileTiming(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantileTiming(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -21,7 +21,7 @@ AggregateFunctionPtr createAggregateFunctionQuantileTiming(const std::string & n
return res;
}
AggregateFunctionPtr createAggregateFunctionQuantilesTiming(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantilesTiming(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -34,7 +34,7 @@ AggregateFunctionPtr createAggregateFunctionQuantilesTiming(const std::string &
return res;
}
AggregateFunctionPtr createAggregateFunctionQuantileTimingWeighted(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantileTimingWeighted(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -48,7 +48,7 @@ AggregateFunctionPtr createAggregateFunctionQuantileTimingWeighted(const std::st
return res;
}
AggregateFunctionPtr createAggregateFunctionQuantilesTimingWeighted(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionQuantilesTimingWeighted(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

View File

@ -806,7 +806,7 @@ public:
return std::make_shared<DataTypeFloat32>();
}
void setArgument(const DataTypePtr & argument)
void setArgument(const DataTypePtr & /*argument*/)
{
}
@ -824,7 +824,7 @@ public:
this->data(place).insert(static_cast<const ColumnVector<ArgumentFieldType> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).merge(this->data(rhs));
}
@ -867,7 +867,7 @@ public:
return std::make_shared<DataTypeFloat32>();
}
void setArgumentsImpl(const DataTypes & arguments)
void setArgumentsImpl(const DataTypes & /*arguments*/)
{
}
@ -886,7 +886,7 @@ public:
static_cast<const ColumnVector<WeightFieldType> &>(column_weight).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).merge(this->data(rhs));
}
@ -928,7 +928,7 @@ public:
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeFloat32>());
}
void setArgument(const DataTypePtr & argument)
void setArgument(const DataTypePtr & /*argument*/)
{
}
@ -943,7 +943,7 @@ public:
this->data(place).insert(static_cast<const ColumnVector<ArgumentFieldType> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).merge(this->data(rhs));
}
@ -995,7 +995,7 @@ public:
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeFloat32>());
}
void setArgumentsImpl(const DataTypes & arguments)
void setArgumentsImpl(const DataTypes & /*arguments*/)
{
}
@ -1011,7 +1011,7 @@ public:
static_cast<const ColumnVector<WeightFieldType> &>(column_weight).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).merge(this->data(rhs));
}

View File

@ -7,7 +7,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionSequenceCount(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionSequenceCount(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (!AggregateFunctionSequenceCount::sufficientArgs(argument_types.size()))
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -15,7 +15,7 @@ AggregateFunctionPtr createAggregateFunctionSequenceCount(const std::string & na
return std::make_shared<AggregateFunctionSequenceCount>();
}
AggregateFunctionPtr createAggregateFunctionSequenceMatch(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionSequenceMatch(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (!AggregateFunctionSequenceMatch::sufficientArgs(argument_types.size()))
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

View File

@ -203,7 +203,7 @@ public:
data(place).add(timestamp, events);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
data(place).merge(data(rhs));
}

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionVarPop(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionVarPop(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -21,7 +21,7 @@ AggregateFunctionPtr createAggregateFunctionVarPop(const std::string & name, con
return res;
}
AggregateFunctionPtr createAggregateFunctionVarSamp(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionVarSamp(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -34,7 +34,7 @@ AggregateFunctionPtr createAggregateFunctionVarSamp(const std::string & name, co
return res;
}
AggregateFunctionPtr createAggregateFunctionStdDevPop(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionStdDevPop(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -47,7 +47,7 @@ AggregateFunctionPtr createAggregateFunctionStdDevPop(const std::string & name,
return res;
}
AggregateFunctionPtr createAggregateFunctionStdDevSamp(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionStdDevSamp(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -60,7 +60,7 @@ AggregateFunctionPtr createAggregateFunctionStdDevSamp(const std::string & name,
return res;
}
AggregateFunctionPtr createAggregateFunctionCovarPop(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionCovarPop(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -73,7 +73,7 @@ AggregateFunctionPtr createAggregateFunctionCovarPop(const std::string & name, c
return res;
}
AggregateFunctionPtr createAggregateFunctionCovarSamp(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionCovarSamp(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -87,7 +87,7 @@ AggregateFunctionPtr createAggregateFunctionCovarSamp(const std::string & name,
}
AggregateFunctionPtr createAggregateFunctionCorr(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionCorr(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 2)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

View File

@ -134,7 +134,7 @@ public:
this->data(place).update(column, row_num);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).mergeWith(this->data(rhs));
}
@ -220,10 +220,10 @@ template <bool compute_marginal_moments>
class BaseCovarianceData
{
protected:
void incrementMarginalMoments(Float64 left_incr, Float64 right_incr) {}
void mergeWith(const BaseCovarianceData & source) {}
void serialize(WriteBuffer & buf) const {}
void deserialize(const ReadBuffer & buf) {}
void incrementMarginalMoments(Float64, Float64) {}
void mergeWith(const BaseCovarianceData &) {}
void serialize(WriteBuffer &) const {}
void deserialize(const ReadBuffer &) {}
};
template <>
@ -350,16 +350,12 @@ public:
Base::deserialize(buf);
}
template <bool compute = compute_marginal_moments>
void publish(IColumn & to, typename std::enable_if<compute>::type * = nullptr) const
void publish(IColumn & to) const
{
static_cast<ColumnFloat64 &>(to).getData().push_back(Op::apply(co_moment, Base::left_m2, Base::right_m2, count));
}
template <bool compute = compute_marginal_moments>
void publish(IColumn & to, typename std::enable_if<!compute>::type * = nullptr) const
{
static_cast<ColumnFloat64 &>(to).getData().push_back(Op::apply(co_moment, count));
if constexpr (compute_marginal_moments)
static_cast<ColumnFloat64 &>(to).getData().push_back(Op::apply(co_moment, Base::left_m2, Base::right_m2, count));
else
static_cast<ColumnFloat64 &>(to).getData().push_back(Op::apply(co_moment, count));
}
private:
@ -399,7 +395,7 @@ public:
this->data(place).update(column_left, column_right, row_num);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).mergeWith(this->data(rhs));
}

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionSum(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionSum(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -21,7 +21,7 @@ AggregateFunctionPtr createAggregateFunctionSum(const std::string & name, const
return res;
}
AggregateFunctionPtr createAggregateFunctionSumWithOverflow(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionSumWithOverflow(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);

View File

@ -44,7 +44,7 @@ public:
this->data(place).sum += static_cast<const ColumnVector<T> &>(column).getData()[row_num];
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).sum += this->data(rhs).sum;
}

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionSumMap(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionSumMap(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() < 2)
throw Exception("Incorrect number of arguments for aggregate function " + name + ", should be at least 2",

View File

@ -98,7 +98,7 @@ public:
ErrorCodes::LOGICAL_ERROR);
}
void add(AggregateDataPtr place, const IColumn ** columns, const size_t row_num, Arena * arena) const override final
void add(AggregateDataPtr place, const IColumn ** columns, const size_t row_num, Arena *) const override final
{
// Column 0 contains array of keys of known type
const ColumnArray & array_column = static_cast<const ColumnArray &>(*columns[0]);
@ -144,7 +144,7 @@ public:
}
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
auto & merged_maps = this->data(place).merged_maps;
const auto & rhs_maps = this->data(rhs).merged_maps;

View File

@ -42,7 +42,7 @@ static IAggregateFunction * createWithExtraTypes(const IDataType & argument_type
}
}
AggregateFunctionPtr createAggregateFunctionTopK(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionTopK(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() != 1)
throw Exception("Incorrect number of arguments for aggregate function " + name,

View File

@ -57,7 +57,7 @@ public:
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeNumber<T>>());
}
void setArgument(const DataTypePtr & argument)
void setArgument(const DataTypePtr & /*argument*/)
{
}
@ -84,7 +84,7 @@ public:
set.insert(static_cast<const ColumnVector<T> &>(column).getData()[row_num]);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).value.merge(this->data(rhs).value);
}
@ -213,7 +213,7 @@ public:
set.readAlphaMap(buf);
}
void addImpl(AggregateDataPtr place, const IColumn & column, size_t row_num, Arena * arena) const
void addImpl(AggregateDataPtr place, const IColumn & column, size_t row_num, Arena *) const
{
auto & set = this->data(place).value;
if (set.capacity() != reserved)
@ -225,7 +225,7 @@ public:
set.insert(str_serialized);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).value.merge(this->data(rhs).value);
}

View File

@ -13,7 +13,7 @@ namespace
*/
template <typename Data, typename DataForVariadic>
AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() == 1)
{
@ -53,7 +53,7 @@ AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const
}
template <template <typename> class Data, typename DataForVariadic>
AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionUniq(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() == 1)
{

View File

@ -273,81 +273,63 @@ template <> struct AggregateFunctionUniqCombinedTraits<Float64>
}
};
/** The structure for the delegation work to add one element to the `uniq` aggregate functions.
* Used for partial specialization to add strings.
*/
template <typename T, typename Data, typename Enable = void>
struct OneAdder;
template <typename T, typename Data>
struct OneAdder<T, Data, typename std::enable_if<
std::is_same<Data, AggregateFunctionUniqUniquesHashSetData>::value ||
std::is_same<Data, AggregateFunctionUniqHLL12Data<T>>::value>::type>
struct OneAdder
{
template <typename T2 = T>
static void ALWAYS_INLINE addImpl(Data & data, const IColumn & column, size_t row_num,
typename std::enable_if<!std::is_same<T2, String>::value>::type * = nullptr)
static void ALWAYS_INLINE addImpl(Data & data, const IColumn & column, size_t row_num)
{
const auto & value = static_cast<const ColumnVector<T2> &>(column).getData()[row_num];
data.set.insert(AggregateFunctionUniqTraits<T2>::hash(value));
}
if constexpr (std::is_same<Data, AggregateFunctionUniqUniquesHashSetData>::value
|| std::is_same<Data, AggregateFunctionUniqHLL12Data<T>>::value)
{
if constexpr (!std::is_same<T, String>::value)
{
const auto & value = static_cast<const ColumnVector<T> &>(column).getData()[row_num];
data.set.insert(AggregateFunctionUniqTraits<T>::hash(value));
}
else
{
StringRef value = column.getDataAt(row_num);
data.set.insert(CityHash_v1_0_2::CityHash64(value.data, value.size));
}
}
else if constexpr (std::is_same<Data, AggregateFunctionUniqCombinedRawData<T>>::value
|| std::is_same<Data, AggregateFunctionUniqCombinedLinearCountingData<T>>::value
|| std::is_same<Data, AggregateFunctionUniqCombinedBiasCorrectedData<T>>::value
|| std::is_same<Data, AggregateFunctionUniqCombinedData<T>>::value)
{
if constexpr (!std::is_same<T, String>::value)
{
const auto & value = static_cast<const ColumnVector<T> &>(column).getData()[row_num];
data.set.insert(AggregateFunctionUniqCombinedTraits<T>::hash(value));
}
else
{
StringRef value = column.getDataAt(row_num);
data.set.insert(CityHash_v1_0_2::CityHash64(value.data, value.size));
}
}
else if constexpr (std::is_same<Data, AggregateFunctionUniqExactData<T>>::value)
{
if constexpr (!std::is_same<T, String>::value)
{
data.set.insert(static_cast<const ColumnVector<T> &>(column).getData()[row_num]);
}
else
{
StringRef value = column.getDataAt(row_num);
template <typename T2 = T>
static void ALWAYS_INLINE addImpl(Data & data, const IColumn & column, size_t row_num,
typename std::enable_if<std::is_same<T2, String>::value>::type * = nullptr)
{
StringRef value = column.getDataAt(row_num);
data.set.insert(CityHash_v1_0_2::CityHash64(value.data, value.size));
}
};
UInt128 key;
SipHash hash;
hash.update(value.data, value.size);
hash.get128(key.low, key.high);
template <typename T, typename Data>
struct OneAdder<T, Data, typename std::enable_if<
std::is_same<Data, AggregateFunctionUniqCombinedRawData<T>>::value ||
std::is_same<Data, AggregateFunctionUniqCombinedLinearCountingData<T>>::value ||
std::is_same<Data, AggregateFunctionUniqCombinedBiasCorrectedData<T>>::value ||
std::is_same<Data, AggregateFunctionUniqCombinedData<T>>::value>::type>
{
template <typename T2 = T>
static void ALWAYS_INLINE addImpl(Data & data, const IColumn & column, size_t row_num,
typename std::enable_if<!std::is_same<T2, String>::value>::type * = nullptr)
{
const auto & value = static_cast<const ColumnVector<T2> &>(column).getData()[row_num];
data.set.insert(AggregateFunctionUniqCombinedTraits<T2>::hash(value));
}
template <typename T2 = T>
static void ALWAYS_INLINE addImpl(Data & data, const IColumn & column, size_t row_num,
typename std::enable_if<std::is_same<T2, String>::value>::type * = nullptr)
{
StringRef value = column.getDataAt(row_num);
data.set.insert(CityHash_v1_0_2::CityHash64(value.data, value.size));
}
};
template <typename T, typename Data>
struct OneAdder<T, Data, typename std::enable_if<
std::is_same<Data, AggregateFunctionUniqExactData<T>>::value>::type>
{
template <typename T2 = T>
static void ALWAYS_INLINE addImpl(Data & data, const IColumn & column, size_t row_num,
typename std::enable_if<!std::is_same<T2, String>::value>::type * = nullptr)
{
data.set.insert(static_cast<const ColumnVector<T2> &>(column).getData()[row_num]);
}
template <typename T2 = T>
static void ALWAYS_INLINE addImpl(Data & data, const IColumn & column, size_t row_num,
typename std::enable_if<std::is_same<T2, String>::value>::type * = nullptr)
{
StringRef value = column.getDataAt(row_num);
UInt128 key;
SipHash hash;
hash.update(value.data, value.size);
hash.get128(key.low, key.high);
data.set.insert(key);
data.set.insert(key);
}
}
}
};
@ -366,7 +348,7 @@ public:
return std::make_shared<DataTypeUInt64>();
}
void setArgument(const DataTypePtr & argument)
void setArgument(const DataTypePtr & /*argument*/)
{
}
@ -375,7 +357,7 @@ public:
detail::OneAdder<T, Data>::addImpl(this->data(place), column, row_num);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).set.merge(this->data(rhs).set);
}
@ -432,7 +414,7 @@ public:
this->data(place).set.insert(UniqVariadicHash<is_exact, argument_is_tuple>::apply(num_args, columns, row_num));
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).set.merge(this->data(rhs).set);
}

View File

@ -8,7 +8,7 @@ namespace DB
namespace
{
AggregateFunctionPtr createAggregateFunctionUniqUpTo(const std::string & name, const DataTypes & argument_types, const Array & parameters)
AggregateFunctionPtr createAggregateFunctionUniqUpTo(const std::string & name, const DataTypes & argument_types, const Array & /*parameters*/)
{
if (argument_types.size() == 1)
{

View File

@ -146,7 +146,7 @@ public:
return std::make_shared<DataTypeUInt64>();
}
void setArgument(const DataTypePtr & argument)
void setArgument(const DataTypePtr & /*argument*/)
{
}
@ -169,7 +169,7 @@ public:
this->data(place).addImpl(column, row_num, threshold);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).merge(this->data(rhs), threshold);
}
@ -244,7 +244,7 @@ public:
this->data(place).insert(UniqVariadicHash<false, argument_is_tuple>::apply(num_args, columns, row_num), threshold);
}
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).merge(this->data(rhs), threshold);
}

View File

@ -43,7 +43,7 @@ static IAggregateFunction * createAggregateFunctionSingleValue(const String & na
/// argMin, argMax
template <template <typename> class MinMaxData, typename ResData>
static IAggregateFunction * createAggregateFunctionArgMinMaxSecond(const String & name, const IDataType & val_type)
static IAggregateFunction * createAggregateFunctionArgMinMaxSecond(const String & /*name*/, const IDataType & val_type)
{
if (typeid_cast<const DataTypeUInt8 *>(&val_type))
return new AggregateFunctionArgMinMax<AggregateFunctionArgMinMaxData<ResData, MinMaxData<SingleValueDataFixed<UInt8>>>>;

View File

@ -60,7 +60,7 @@ public:
* If no parameters are provided, or the passed parameters are not valid, throw an exception.
* If there are parameters - it is necessary to call before other calls, otherwise - do not call.
*/
virtual void setParameters(const Array & params)
virtual void setParameters(const Array & /*params*/)
{
throw Exception("Aggregate function " + getName() + " doesn't allow parameters.",
ErrorCodes::AGGREGATE_FUNCTION_DOESNT_ALLOW_PARAMETERS);

View File

@ -26,12 +26,12 @@ public:
}
/// Accumulate a value.
void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena *) const override final
void add(AggregateDataPtr place, const IColumn ** /*columns*/, size_t /*row_num*/, Arena *) const override final
{
getDerived().addImpl(place);
}
static void addFree(const IAggregateFunction * that, AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena *)
static void addFree(const IAggregateFunction * that, AggregateDataPtr place, const IColumn ** /*columns*/, size_t /*row_num*/, Arena *)
{
return static_cast<const Derived &>(*that).addImpl(place);
}

View File

@ -182,8 +182,7 @@ void createASTsForAllColumnsInTable(const CollectTables::TableInfo & table, ASTs
}
ASTs expandUnqualifiedAsterisk(
AnalyzeColumns::Columns & columns, const CollectAliases & aliases, const CollectTables & tables)
ASTs expandUnqualifiedAsterisk(const CollectTables & tables)
{
ASTs res;
for (const auto & table : tables.tables)
@ -193,7 +192,7 @@ ASTs expandUnqualifiedAsterisk(
ASTs expandQualifiedAsterisk(
const IAST & ast, AnalyzeColumns::Columns & columns, const CollectAliases & aliases, const CollectTables & tables)
const IAST & ast, const CollectTables & tables)
{
if (ast.children.size() != 1)
throw Exception("Logical error: AST node for qualified asterisk has number of children not equal to one", ErrorCodes::LOGICAL_ERROR);
@ -353,13 +352,13 @@ void processImpl(ASTPtr & ast, AnalyzeColumns::Columns & columns, const CollectA
{
if (typeid_cast<ASTAsterisk *>(asts[i].get()))
{
ASTs expanded = expandUnqualifiedAsterisk(columns, aliases, tables);
ASTs expanded = expandUnqualifiedAsterisk(tables);
asts.erase(asts.begin() + i);
asts.insert(asts.begin() + i, expanded.begin(), expanded.end());
}
else if (ASTQualifiedAsterisk * asterisk = typeid_cast<ASTQualifiedAsterisk *>(asts[i].get()))
{
ASTs expanded = expandQualifiedAsterisk(*asterisk, columns, aliases, tables);
ASTs expanded = expandQualifiedAsterisk(*asterisk, tables);
asts.erase(asts.begin() + i);
asts.insert(asts.begin() + i, expanded.begin(), expanded.end());
}

View File

@ -92,7 +92,7 @@ static CollectTables::TableInfo processSubquery(ASTPtr & ast_subquery, const Con
}
void CollectTables::process(ASTPtr & ast, const Context & context, const CollectAliases & aliases, ExecuteTableFunctions & table_functions)
void CollectTables::process(ASTPtr & ast, const Context & context, const CollectAliases & /*aliases*/, ExecuteTableFunctions & table_functions)
{
const ASTSelectQuery * select = typeid_cast<const ASTSelectQuery *>(ast.get());
if (!select)

View File

@ -318,7 +318,7 @@ void processScalarSubquery(const String & column_name, ASTPtr & ast, TypeAndCons
}
void processHigherOrderFunction(const String & column_name,
void processHigherOrderFunction(
ASTPtr & ast, const Context & context,
CollectAliases & aliases, const AnalyzeColumns & columns,
TypeAndConstantInference::Info & info,
@ -459,7 +459,7 @@ void processImpl(
{
/// If this is higher-order function, determine types of lambda arguments and infer types of subexpressions inside lambdas.
if (lambdas.higher_order_functions.end() != std::find(lambdas.higher_order_functions.begin(), lambdas.higher_order_functions.end(), ast))
processHigherOrderFunction(column_name, ast, context, aliases, columns, info, lambdas, table_functions);
processHigherOrderFunction(ast, context, aliases, columns, info, lambdas, table_functions);
processFunction(column_name, ast, info, context);
}

View File

@ -18,7 +18,7 @@
/// Parses query from stdin and print found columns and corresponding tables.
int main(int argc, char ** argv)
int main(int, char **)
try
{
using namespace DB;

View File

@ -11,7 +11,7 @@
/// Parses query from stdin and print found higher order functions and query with rewritten names of lambda parameters.
int main(int argc, char ** argv)
int main(int, char **)
try
{
using namespace DB;

View File

@ -14,7 +14,7 @@
/// Parses query from stdin and print names and types of result columns.
int main(int argc, char ** argv)
int main(int, char **)
try
{
using namespace DB;

View File

@ -9,7 +9,7 @@
/// Parses query from stdin and print found aliases.
int main(int argc, char ** argv)
int main(int, char **)
try
{
using namespace DB;

View File

@ -15,7 +15,7 @@
/// Parses query from stdin and print found tables.
int main(int argc, char ** argv)
int main(int, char **)
try
{
using namespace DB;

View File

@ -21,7 +21,7 @@
/// Parses query from stdin and print same query with optimized GROUP BY, ORDER BY, LIMIT BY.
int main(int argc, char ** argv)
int main(int, char **)
try
{
using namespace DB;

View File

@ -10,7 +10,7 @@
/// Parses query from stdin and print same query with translated positional arguments.
int main(int argc, char ** argv)
int main(int, char **)
try
{
using namespace DB;

View File

@ -22,7 +22,7 @@
/// Parses query from stdin and print data types of expressions; and for constant expressions, print its values.
int main(int argc, char ** argv)
int main(int, char **)
try
{
using namespace DB;

View File

@ -1,3 +0,0 @@
if (ENABLE_TESTS)
add_subdirectory (tests)
endif ()

View File

@ -50,7 +50,7 @@ ConnectionPoolWithFailover::ConnectionPoolWithFailover(
}
}
IConnectionPool::Entry ConnectionPoolWithFailover::get(const Settings * settings, bool force_connected)
IConnectionPool::Entry ConnectionPoolWithFailover::get(const Settings * settings, bool /*force_connected*/)
{
TryGetEntryFunc try_get_entry = [&](NestedPool & pool, std::string & fail_message)
{

View File

@ -1,2 +0,0 @@
add_executable(test-connect test_connect.cpp)
target_link_libraries (test-connect dbms)

View File

@ -1,59 +0,0 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <iostream>
#include <Poco/Net/StreamSocket.h>
#include <Common/Exception.h>
#include <IO/ReadHelpers.h>
/** In a loop it connects to the server and immediately breaks the connection.
  * Using the SO_LINGER option, we ensure that the connection is terminated by sending a RST packet (not FIN).
  * This behavior causes a bug in the TCPServer implementation in the Poco library.
  */
int main(int argc, char ** argv)
try
{
for (size_t i = 0; i < DB::parse<size_t>(argv[1]); ++i)
{
std::cerr << ".";
Poco::Net::SocketAddress address("localhost", 9000);
int fd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
if (fd < 0)
DB::throwFromErrno("Cannot create socket");
linger linger_value;
linger_value.l_onoff = 1;
linger_value.l_linger = 0;
if (0 != setsockopt(fd, SOL_SOCKET, SO_LINGER, &linger_value, sizeof(linger_value)))
DB::throwFromErrno("Cannot set linger");
try
{
int res = connect(fd, address.addr(), address.length());
if (res != 0 && errno != EINPROGRESS && errno != EWOULDBLOCK)
{
close(fd);
DB::throwFromErrno("Cannot connect");
}
close(fd);
}
catch (const Poco::Exception & e)
{
std::cerr << e.displayText() << "\n";
}
}
std::cerr << "\n";
}
catch (const Poco::Exception & e)
{
std::cerr << e.displayText() << "\n";
}

View File

@ -222,7 +222,7 @@ StringRef ColumnAggregateFunction::getDataAt(size_t n) const
return StringRef(reinterpret_cast<const char *>(&getData()[n]), sizeof(getData()[n]));
}
void ColumnAggregateFunction::insertData(const char * pos, size_t length)
void ColumnAggregateFunction::insertData(const char * pos, size_t /*length*/)
{
getData().push_back(*reinterpret_cast<const AggregateDataPtr *>(pos));
}
@ -281,12 +281,12 @@ void ColumnAggregateFunction::insertDefault()
function->create(getData().back());
}
StringRef ColumnAggregateFunction::serializeValueIntoArena(size_t n, Arena & arena, const char *& begin) const
StringRef ColumnAggregateFunction::serializeValueIntoArena(size_t, Arena &, const char *&) const
{
throw Exception("Method serializeValueIntoArena is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
}
const char * ColumnAggregateFunction::deserializeAndInsertFromArena(const char * pos)
const char * ColumnAggregateFunction::deserializeAndInsertFromArena(const char *)
{
throw Exception("Method deserializeAndInsertFromArena is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
}
@ -353,7 +353,7 @@ Columns ColumnAggregateFunction::scatter(IColumn::ColumnIndex num_columns, const
return columns;
}
void ColumnAggregateFunction::getPermutation(bool reverse, size_t limit, int nan_direction_hint, IColumn::Permutation & res) const
void ColumnAggregateFunction::getPermutation(bool /*reverse*/, size_t /*limit*/, int /*nan_direction_hint*/, IColumn::Permutation & res) const
{
size_t s = getData().size();
res.resize(s);

View File

@ -64,7 +64,8 @@ private:
public:
/// Create a new column that has another column as a source.
ColumnAggregateFunction(const ColumnAggregateFunction & other)
: arenas(other.arenas), func(other.func), src(other.shared_from_this())
: std::enable_shared_from_this<ColumnAggregateFunction>(other),
arenas(other.arenas), func(other.func), src(other.shared_from_this())
{
}
@ -153,7 +154,7 @@ public:
void gather(ColumnGathererStream & gatherer_stream) override;
int compareAt(size_t n, size_t m, const IColumn & rhs_, int nan_direction_hint) const override
int compareAt(size_t, size_t, const IColumn &, int) const override
{
return 0;
}

View File

@ -82,57 +82,57 @@ public:
return s;
}
Field operator[](size_t n) const override
Field operator[](size_t) const override
{
return (*data)[0];
}
void get(size_t n, Field & res) const override
void get(size_t, Field & res) const override
{
data->get(0, res);
}
StringRef getDataAt(size_t n) const override
StringRef getDataAt(size_t) const override
{
return data->getDataAt(0);
}
StringRef getDataAtWithTerminatingZero(size_t n) const override
StringRef getDataAtWithTerminatingZero(size_t) const override
{
return data->getDataAtWithTerminatingZero(0);
}
UInt64 get64(size_t n) const override
UInt64 get64(size_t) const override
{
return data->get64(0);
}
UInt64 getUInt(size_t n) const override
UInt64 getUInt(size_t) const override
{
return data->getUInt(0);
}
Int64 getInt(size_t n) const override
Int64 getInt(size_t) const override
{
return data->getInt(0);
}
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override
void insertRangeFrom(const IColumn &, size_t /*start*/, size_t length) override
{
s += length;
}
void insert(const Field & x) override
void insert(const Field &) override
{
++s;
}
void insertData(const char * pos, size_t length) override
void insertData(const char *, size_t) override
{
++s;
}
void insertFrom(const IColumn & src, size_t n) override
void insertFrom(const IColumn &, size_t) override
{
++s;
}
@ -147,7 +147,7 @@ public:
s -= n;
}
StringRef serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const override
StringRef serializeValueIntoArena(size_t, Arena & arena, char const *& begin) const override
{
return data->serializeValueIntoArena(0, arena, begin);
}
@ -160,12 +160,12 @@ public:
return res;
}
void updateHashWithValue(size_t n, SipHash & hash) const override
void updateHashWithValue(size_t, SipHash & hash) const override
{
data->updateHashWithValue(0, hash);
}
ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override
ColumnPtr filter(const Filter & filt, ssize_t /*result_size_hint*/) const override
{
if (s != filt.size())
throw Exception("Size of filter doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
@ -205,12 +205,12 @@ public:
return std::make_shared<ColumnConst>(data, limit);
}
int compareAt(size_t n, size_t m, const IColumn & rhs, int nan_direction_hint) const override
int compareAt(size_t, size_t, const IColumn & rhs, int nan_direction_hint) const override
{
return data->compareAt(0, 0, *static_cast<const ColumnConst &>(rhs).data, nan_direction_hint);
}
void getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const override
void getPermutation(bool /*reverse*/, size_t /*limit*/, int /*nan_direction_hint*/, Permutation & res) const override
{
res.resize(s);
for (size_t i = 0; i < s; ++i)

View File

@ -111,7 +111,7 @@ struct ColumnFixedString::less
}
};
void ColumnFixedString::getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const
void ColumnFixedString::getPermutation(bool reverse, size_t limit, int /*nan_direction_hint*/, Permutation & res) const
{
size_t s = size();
res.resize(s);

View File

@ -113,12 +113,12 @@ void ColumnNullable::get(size_t n, Field & res) const
nested_column->get(n, res);
}
StringRef ColumnNullable::getDataAt(size_t n) const
StringRef ColumnNullable::getDataAt(size_t /*n*/) const
{
throw Exception{"Method getDataAt is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED};
}
void ColumnNullable::insertData(const char * pos, size_t length)
void ColumnNullable::insertData(const char * /*pos*/, size_t /*length*/)
{
throw Exception{"Method insertData is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED};
}

View File

@ -181,7 +181,7 @@ struct ColumnString::less
}
};
void ColumnString::getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const
void ColumnString::getPermutation(bool reverse, size_t limit, int /*nan_direction_hint*/, Permutation & res) const
{
size_t s = offsets.size();
res.resize(s);

View File

@ -208,7 +208,7 @@ public:
offsets.push_back(offsets.size() == 0 ? 1 : (offsets.back() + 1));
}
int compareAt(size_t n, size_t m, const IColumn & rhs_, int nan_direction_hint) const override
int compareAt(size_t n, size_t m, const IColumn & rhs_, int /*nan_direction_hint*/) const override
{
const ColumnString & rhs = static_cast<const ColumnString &>(rhs_);

View File

@ -41,12 +41,12 @@ void ColumnTuple::get(size_t n, Field & res) const
columns[i]->get(n, res_arr[i]);
}
StringRef ColumnTuple::getDataAt(size_t n) const
StringRef ColumnTuple::getDataAt(size_t) const
{
throw Exception("Method getDataAt is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
}
void ColumnTuple::insertData(const char * pos, size_t length)
void ColumnTuple::insertData(const char *, size_t)
{
throw Exception("Method insertData is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
}

View File

@ -147,16 +147,16 @@ namespace
struct NoResultOffsetsBuilder
{
explicit NoResultOffsetsBuilder(IColumn::Offsets_t * res_offsets_) {}
void reserve(ssize_t result_size_hint, size_t src_size) {}
void insertOne(size_t array_size) {}
explicit NoResultOffsetsBuilder(IColumn::Offsets_t *) {}
void reserve(ssize_t, size_t) {}
void insertOne(size_t) {}
template <size_t SIMD_BYTES>
void insertChunk(
const IColumn::Offset_t * src_offsets_pos,
bool first,
IColumn::Offset_t chunk_offset,
size_t chunk_size)
const IColumn::Offset_t *,
bool,
IColumn::Offset_t,
size_t)
{
}
};

View File

@ -31,35 +31,35 @@ public:
void popBack(size_t n) override { s -= n; }
size_t byteSize() const override { return 0; }
size_t allocatedBytes() const override { return 0; }
int compareAt(size_t n, size_t m, const IColumn & rhs_, int nan_direction_hint) const override { return 0; }
int compareAt(size_t, size_t, const IColumn &, int) const override { return 0; }
Field operator[](size_t n) const override { throw Exception("Cannot get value from " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
void get(size_t n, Field & res) const override { throw Exception("Cannot get value from " + getName(), ErrorCodes::NOT_IMPLEMENTED); };
void insert(const Field & x) override { throw Exception("Cannot insert element into " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
StringRef getDataAt(size_t n) const override { throw Exception("Method getDataAt is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
void insertData(const char * pos, size_t length) override { throw Exception("Method insertData is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
Field operator[](size_t) const override { throw Exception("Cannot get value from " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
void get(size_t, Field &) const override { throw Exception("Cannot get value from " + getName(), ErrorCodes::NOT_IMPLEMENTED); };
void insert(const Field &) override { throw Exception("Cannot insert element into " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
StringRef getDataAt(size_t) const override { throw Exception("Method getDataAt is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
void insertData(const char *, size_t) override { throw Exception("Method insertData is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED); }
StringRef serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const override
StringRef serializeValueIntoArena(size_t /*n*/, Arena & /*arena*/, char const *& /*begin*/) const override
{
throw Exception("Method serializeValueIntoArena is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
}
const char * deserializeAndInsertFromArena(const char * pos) override
const char * deserializeAndInsertFromArena(const char * /*pos*/) override
{
throw Exception("Method deserializeAndInsertFromArena is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
}
void updateHashWithValue(size_t n, SipHash & hash) const override
void updateHashWithValue(size_t /*n*/, SipHash & /*hash*/) const override
{
throw Exception("Method updateHashWithValue is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
}
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override
void insertRangeFrom(const IColumn & /*src*/, size_t /*start*/, size_t length) override
{
s += length;
}
ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override
ColumnPtr filter(const Filter & filt, ssize_t /*result_size_hint*/) const override
{
return cloneDummy(countBytesInFilter(filt));
}
@ -72,7 +72,7 @@ public:
return cloneDummy(limit ? std::min(s, limit) : s);
}
void getPermutation(bool reverse, size_t limit, int nan_direction_hint, Permutation & res) const override
void getPermutation(bool /*reverse*/, size_t /*limit*/, int /*nan_direction_hint*/, Permutation & res) const override
{
res.resize(s);
for (size_t i = 0; i < s; ++i)
@ -108,7 +108,7 @@ public:
throw Exception("Method gather is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
}
void getExtremes(Field & min, Field & max) const override
void getExtremes(Field &, Field &) const override
{
throw Exception("Method getExtremes is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
}

View File

@ -31,9 +31,9 @@ public:
}
}
static void free(void * buf, size_t size)
static void free(void * /*buf*/, size_t /*size*/)
{
// Remains trash in arena
// Do nothing, trash in arena remains.
}
};
@ -100,7 +100,7 @@ public:
return new_buf;
}
void free(void * buf, size_t size) {}
void free(void * /*buf*/, size_t /*size*/) {}
};
}

View File

@ -45,26 +45,11 @@ public:
/// Initialize read_buffer, depending on the data source. By default, does nothing.
virtual void initReadBuffer() {};
/// Initialize sample_block according to the structure of the table stored in the `structure`
virtual void initSampleBlock(const Context & context)
{
const DataTypeFactory & data_type_factory = DataTypeFactory::instance();
for (size_t i = 0; i < structure.size(); ++i)
{
ColumnWithTypeAndName column;
column.name = structure[i].first;
column.type = data_type_factory.get(structure[i].second);
column.column = column.type->createColumn();
sample_block.insert(std::move(column));
}
}
/// Get the table data - a pair (a thread with the contents of the table, the name of the table)
virtual ExternalTableData getData(const Context & context)
ExternalTableData getData(const Context & context)
{
initReadBuffer();
initSampleBlock(context);
initSampleBlock();
ExternalTableData res = std::make_pair(std::make_shared<AsynchronousBlockInputStream>(context.getInputFormat(
format, *read_buffer, sample_block, DEFAULT_BLOCK_SIZE)), name);
return res;
@ -120,6 +105,22 @@ protected:
for (size_t i = 0; i < vals.size(); ++i)
structure.emplace_back("_" + toString(i + 1), vals[i]);
}
private:
/// Initialize sample_block according to the structure of the table stored in the `structure`
void initSampleBlock()
{
const DataTypeFactory & data_type_factory = DataTypeFactory::instance();
for (size_t i = 0; i < structure.size(); ++i)
{
ColumnWithTypeAndName column;
column.name = structure[i].first;
column.type = data_type_factory.get(structure[i].second);
column.column = column.type->createColumn();
sample_block.insert(std::move(column));
}
}
};
@ -127,7 +128,7 @@ protected:
class ExternalTable : public BaseExternalTable
{
public:
void initReadBuffer()
void initReadBuffer() override
{
if (file == "-")
read_buffer = std::make_unique<ReadBufferFromFileDescriptor>(STDIN_FILENO);

View File

@ -36,7 +36,7 @@ struct ClearableHashTableCell : public BaseCell
UInt32 version;
bool isZero(const State & state) const { return version != state.version; }
static bool isZero(const Key & key, const State & state) { return false; }
static bool isZero(const Key & /*key*/, const State & /*state*/) { return false; }
/// Set the key value to zero.
void setZero() { version = 0; }

View File

@ -101,7 +101,7 @@ struct TrivialBiasEstimator
return 0.0;
}
static double getBias(double raw_estimate)
static double getBias(double /*raw_estimate*/)
{
return 0.0;
}

View File

@ -13,7 +13,7 @@ inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type isN
}
template <typename T>
inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type isNaN(T x)
inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type isNaN(T)
{
return false;
}
@ -25,7 +25,7 @@ inline typename std::enable_if<std::is_floating_point<T>::value, bool>::type isF
}
template <typename T>
inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type isFinite(T x)
inline typename std::enable_if<!std::is_floating_point<T>::value, bool>::type isFinite(T)
{
return true;
}

View File

@ -162,7 +162,10 @@ void OptimizedRegularExpressionImpl<thread_safe>::analyze(
/// Quantifiers that allow a zero number of occurences.
case '{':
in_curly_braces = true;
case '?': case '*':
[[fallthrough]];
case '?':
[[fallthrough]];
case '*':
is_trivial = false;
if (!last_substring->first.empty() && !in_square_braces)
{
@ -182,6 +185,7 @@ void OptimizedRegularExpressionImpl<thread_safe>::analyze(
break;
ordinary: /// Normal, not escaped symbol.
[[fallthrough]];
default:
if (depth == 0 && !in_curly_braces && !in_square_braces)
{

View File

@ -119,13 +119,13 @@ public:
current_word = 0;
switch (end - data)
{
case 7: current_bytes[6] = data[6];
case 6: current_bytes[5] = data[5];
case 5: current_bytes[4] = data[4];
case 4: current_bytes[3] = data[3];
case 3: current_bytes[2] = data[2];
case 2: current_bytes[1] = data[1];
case 1: current_bytes[0] = data[0];
case 7: current_bytes[6] = data[6]; [[fallthrough]];
case 6: current_bytes[5] = data[5]; [[fallthrough]];
case 5: current_bytes[4] = data[4]; [[fallthrough]];
case 4: current_bytes[3] = data[3]; [[fallthrough]];
case 3: current_bytes[2] = data[2]; [[fallthrough]];
case 2: current_bytes[1] = data[1]; [[fallthrough]];
case 1: current_bytes[0] = data[0]; [[fallthrough]];
case 0: break;
}
}

View File

@ -76,7 +76,7 @@ class SpaceSaving
private:
// Suggested constants in the paper "Finding top-k elements in data streams", chap 6. equation (24)
// Round to nearest power of 2 for cheaper binning without modulo
constexpr uint64_t nextAlphaSize (uint64_t x)
constexpr uint64_t nextAlphaSize(uint64_t x)
{
constexpr uint64_t ALPHA_MAP_ELEMENTS_PER_COUNTER = 6;
return 1ULL<<(sizeof(uint64_t) * 8 - __builtin_clzll(x * ALPHA_MAP_ELEMENTS_PER_COUNTER));

View File

@ -16,7 +16,7 @@ struct TypeList
using At = std::nullptr_t;
template <typename Func, size_t index = 0>
static void forEach(Func && func)
static void forEach(Func && /*func*/)
{
}
};

View File

@ -199,7 +199,7 @@ template <bool ASCII> struct VolnitskyImpl<true, ASCII> : VolnitskyBase<Volnitsk
{
}
void putNGram(const UInt8 * const pos, const int offset, const UInt8 * const begin)
void putNGram(const UInt8 * const pos, const int offset, const UInt8 * const /*begin*/)
{
this->putNGramBase(this->toNGram(pos), offset);
}
@ -226,7 +226,7 @@ template <> struct VolnitskyImpl<false, true> : VolnitskyBase<VolnitskyImpl<fals
{
}
void putNGram(const UInt8 * const pos, const int offset, const UInt8 * const begin)
void putNGram(const UInt8 * const pos, const int offset, const UInt8 * const /*begin*/)
{
putNGramASCIICaseInsensitive(pos, offset);
}

View File

@ -11,7 +11,7 @@
#include <IO/ReadHelpers.h>
int main(int argc, char ** argv)
int main(int, char **)
{
using Strings = std::vector<std::string>;
using Hashes = std::vector<char>;

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2016 Tessil
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,303 +0,0 @@
[![Build Status](https://travis-ci.org/Tessil/hopscotch-map.svg?branch=master)](https://travis-ci.org/Tessil/hopscotch-map) [![Build status](https://ci.appveyor.com/api/projects/status/e97rjkcn3qwrhpvf/branch/master?svg=true)](https://ci.appveyor.com/project/Tessil/hopscotch-map/branch/master)
## A C++ implementation of a fast hash map using hopscotch hashing
The hopscotch-map library is a C++ implementation of a fast hash map and hash set using open-addressing and hopscotch hashing to resolve collisions. It is a cache-friendly data structure offering better performances than `std::unordered_map` in most cases and is closely similar to `google::dense_hash_map` while using less memory and providing more functionalities.
The library provides four classes: `tsl::hopscotch_map`, `tsl::hopscotch_set`, `tsl::hopscotch_sc_map` and `tsl::hopscotch_sc_set`. The `tsl::hopscotch_sc_map` and `tsl::hopscotch_sc_set` classes have an additional requirement for the key, must be `LessThanComparable`, but provide a better upper bound, see [details](https://github.com/Tessil/hopscotch-map#deny-of-service-dos-attack) in example. Nonetheless, `tsl::hopscotch_map` and `tsl::hopscotch_set` should be sufficient in most cases and should be your default pick as they perform better in general.
An overview of hopscotch hashing and some implementation details may be found [here](https://tessil.github.io/2016/08/29/hopscotch-hashing.html).
A **benchmark** of `tsl::hopscotch_map` against other hash maps may be found [there](https://tessil.github.io/2016/08/29/benchmark-hopscotch-map.html).
**Note**: By default the library uses a power of two for the size of its buckets array to take advantage of the [fast modulo](https://en.wikipedia.org/wiki/Modulo_operation#Performance_issues). For good performance, it requires the hash table to have a well-distributed hash function. If you encounter performance issues check the [GrowthPolicy](https://github.com/Tessil/hopscotch-map#growth-policy) section to change the default behaviour or change your hash function.
### Key features
- Header-only library, just include [src/](src/) to your include path and you are ready to go.
- Fast hash table, see [benchmark](https://tessil.github.io/2016/08/29/benchmark-hopscotch-map.html) for some numbers.
- Support for move-only and non-default constructible key/value.
- Support for heterogeneous lookups (e.g. if you have a map that uses `std::unique_ptr<int>` as key, you could use an `int*` or a `std::uintptr_t` as key parameter to `find`, see [example](https://github.com/Tessil/hopscotch-map#heterogeneous-lookups)).
- No need to reserve any sentinel value from the keys.
- Possibility to store the hash value on insert for faster rehash and lookup if the hash or the key equal functions are expensive to compute (see the [StoreHash](https://tessil.github.io/hopscotch-map/doc/html/classtsl_1_1hopscotch__map.html#details) template parameter).
- If the hash is known before a lookup, it is possible to pass it as parameter to speed-up the lookup.
- The `tsl::hopscotch_sc_map` and `tsl::hopscotch_sc_set` provide a worst-case of O(log n) on lookup and delete making these classes resistant to hash table Deny of Service (DoS) attacks (see [details](https://github.com/Tessil/hopscotch-map#deny-of-service-dos-attack) in example).
- API closely similar to `std::unordered_map` and `std::unordered_set`.
### Differences compare to `std::unordered_map`
`tsl::hopscotch_map` tries to have an interface similar to `std::unordered_map`, but some differences exist.
- Iterator invalidation on insert doesn't behave in the same way (see [API](https://tessil.github.io/hopscotch-map/doc/html/classtsl_1_1hopscotch__map.html#details) for details).
- References and pointers to keys or values in the map are invalidated in the same way as iterators to these keys-values on insert.
- The size of the bucket array in the map grows by a factor of two, the size will always be a power of two, which may be a too steep growth rate for some purposes. The growth policy is modifiable (see the [`GrowthPolicy`](https://github.com/Tessil/hopscotch-map#growth-policy) template parameter) but it may reduce the speed of the hash map.
- For iterators, `operator*()` and `operator->()` return a reference and a pointer to `const std::pair<Key, T>` instead of `std::pair<const Key, T>` making the value `T` not modifiable. To modify the value you have to call the `value()` method of the iterator to get a mutable reference. Example:
```c++
tsl::hopscotch_map<int, int> map = {{1, 1}, {2, 1}, {3, 1}};
for(auto it = map.begin(); it != map.end(); ++it) {
//it->second = 2; // Illegal
it.value() = 2; // Ok
}
```
- Move-only types must have a nothrow move constructor (with open addressing, it is not possible to keep the strong exception guarantee on rehash if the move constructor may throw).
- No support for some buckets related methods (like bucket_size, bucket, ...).
These differences also apply between `std::unordered_set` and `tsl::hopscotch_set`.
Thread-safety and exceptions guarantees are the same as `std::unordered_map/set`.
### Differences compare to `google::dense_hash_map`
`tsl::hopscotch_map` has comparable performances to `google::dense_hash_map` (see [benchmark](https://tessil.github.io/2016/08/29/benchmark-hopscotch-map.html)), but come with some advantages.
- There is no need to reserve sentinel values for the key as it is required by `google::dense_hash_map` where you need to have a sentinel for empty and deleted keys.
- The type of the value in the map doesn't need a default constructor.
- The key and the value of the map don't need a copy constructor/operator, move-only types are supported.
- It uses less memory for its speed as it can sustain a load factor of 0.95 (which is the default value in the library compare to the 0.5 of `google::dense_hash_map`) while keeping good performances.
### Growth policy
By default `tsl::hopscotch_map/set` uses `tsl::power_of_two_growth_policy` as `GrowthPolicy`. This policy keeps the size of the map to a power of two by doubling the size of the map when a rehash is required. It allows the map to avoid the usage of the slow modulo operation, instead of <code>hash % 2<sup>n</sup></code>, it uses <code>hash & (2<sup>n</sup> - 1)</code>.
This may cause a lot of collisions with a poor hash function as the modulo just masks the most significant bits.
If you encounter poor performances, check `overflow_size()`. If it is not zero, you may have a lot of collisions due to a common pattern in the least significant bits. Either change the hash function for something more uniform or use `tsl::prime_growth_policy` which keeps the size of the map to a prime size.
You can also use `tsl::mod_growth_policy` if you want a more configurable growth rate or you could even define your own policy (see [API](https://tessil.github.io/hopscotch-map/doc/html/classtsl_1_1hopscotch__map.html#details)).
A bad distribution may lead to a runtime complexity of O(n) for lookups. Unfortunately it is sometimes difficult to guard yourself against it (e.g. DoS attack on the hash map). If needed, check `tsl::hopscotch_sc_map/set` which offer a worst-case scenario of O(log n) on lookups, see [details](https://github.com/Tessil/hopscotch-map#deny-of-service-dos-attack) in example.
### Installation
To use hopscotch-map, just add the [src/](src/) directory to your include path. It is a **header-only** library.
The code should work with any C++11 standard-compliant compiler and has been tested with GCC 4.8.4, Clang 3.5.0 and Visual Studio 2015.
To run the tests you will need the Boost Test library and CMake.
```bash
git clone https://github.com/Tessil/hopscotch-map.git
cd hopscotch-map
mkdir build
cd build
cmake ..
make
./test_hopscotch_map
```
### Usage
The API can be found [here](https://tessil.github.io/hopscotch-map/doc/html/).
All methods are not documented yet, but they replicate the behaviour of the ones in `std::unordered_map` and `std::unordered_set`, except if specified otherwise.
### Example
```c++
#include <cstdint>
#include <iostream>
#include <string>
#include "hopscotch_map.h"
#include "hopscotch_set.h"
int main() {
tsl::hopscotch_map<std::string, int> map = {{"a", 1}, {"b", 2}};
map["c"] = 3;
map["d"] = 4;
map.insert({"e", 5});
map.erase("b");
for(auto it = map.begin(); it != map.end(); ++it) {
//it->second += 2; // Not valid.
it.value() += 2;
}
// {d, 6} {a, 3} {e, 7} {c, 5}
for(const auto& key_value : map) {
std::cout << "{" << key_value.first << ", " << key_value.second << "}" << std::endl;
}
/*
* Calculating the hash and comparing two std::string may be slow.
* We can store the hash of each std::string in the hash map to make
* the inserts and lookups faster by setting StoreHash to true.
*/
tsl::hopscotch_map<std::string, int, std::hash<std::string>,
std::equal_to<std::string>,
std::allocator<std::pair<std::string, int>>,
30, true> map2;
map2["a"] = 1;
map2["b"] = 2;
// {a, 1} {b, 2}
for(const auto& key_value : map2) {
std::cout << "{" << key_value.first << ", " << key_value.second << "}" << std::endl;
}
tsl::hopscotch_set<int> set;
set.insert({1, 9, 0});
set.insert({2, -1, 9});
// {0} {1} {2} {9} {-1}
for(const auto& key : set) {
std::cout << "{" << key << "}" << std::endl;
}
}
```
#### Heterogeneous lookups
Heterogeneous overloads allow the usage of other types than `Key` for lookup and erase operations as long as the used types are hashable and comparable to `Key`.
To activate the heterogeneous overloads in `tsl::hopscotch_map/set`, the qualified-id `KeyEqual::is_transparent` must be valid. It works the same way as for [`std::map::find`](http://en.cppreference.com/w/cpp/container/map/find). You can either use [`std::equal_to<>`](http://en.cppreference.com/w/cpp/utility/functional/equal_to_void) or define your own function object.
Both `KeyEqual` and `Hash` will need to be able to deal with the different types.
```c++
#include <functional>
#include <iostream>
#include <string>
#include "hopscotch_map.h"
struct employee {
employee(int id, std::string name) : m_id(id), m_name(std::move(name)) {
}
friend bool operator==(const employee& empl, int empl_id) {
return empl.m_id == empl_id;
}
friend bool operator==(int empl_id, const employee& empl) {
return empl_id == empl.m_id;
}
friend bool operator==(const employee& empl1, const employee& empl2) {
return empl1.m_id == empl2.m_id;
}
int m_id;
std::string m_name;
};
struct hash_employee {
std::size_t operator()(const employee& empl) const {
return std::hash<int>()(empl.m_id);
}
std::size_t operator()(int id) const {
return std::hash<int>()(id);
}
};
struct equal_employee {
using is_transparent = void;
bool operator()(const employee& empl, int empl_id) const {
return empl.m_id == empl_id;
}
bool operator()(int empl_id, const employee& empl) const {
return empl_id == empl.m_id;
}
bool operator()(const employee& empl1, const employee& empl2) const {
return empl1.m_id == empl2.m_id;
}
};
int main() {
// Use std::equal_to<> which will automatically deduce and forward the parameters
tsl::hopscotch_map<employee, int, hash_employee, std::equal_to<>> map;
map.insert({employee(1, "John Doe"), 2001});
map.insert({employee(2, "Jane Doe"), 2002});
map.insert({employee(3, "John Smith"), 2003});
// John Smith 2003
auto it = map.find(3);
if(it != map.end()) {
std::cout << it->first.m_name << " " << it->second << std::endl;
}
map.erase(1);
// Use a custom KeyEqual which has an is_transparent member type
tsl::hopscotch_map<employee, int, hash_employee, equal_employee> map2;
map2.insert({employee(4, "Johnny Doe"), 2004});
// 2004
std::cout << map2.at(4) << std::endl;
}
```
#### Deny of Service (DoS) attack
In addition to `tsl::hopscotch_map` and `tsl::hopscotch_set`, the library provides two more "secure" options: `tsl::hopscotch_sc_map` and `tsl::hopscotch_sc_set`.
These two additions have a worst-case runtime of O(log n) for lookups and deletions and an amortized worst case of O(log n) for insertions (amortized due to the possibility of rehash which would be in O(n)). Even if the hash function maps all the elements to the same bucket, the O(log n) would still hold.
This provides a security against hash table Deny of Service attacks.
To achieve this, the "secure" versions use a binary search tree for the overflown elements (see [implementation details](https://tessil.github.io/2016/08/29/hopscotch-hashing.html)) and thus need the elements to be `LessThanComparable`. An additional `Compare` template parameter is needed.
```c++
#include <chrono>
#include <cstdint>
#include <iostream>
#include "hopscotch_map.h"
#include "hopscotch_sc_map.h"
/*
* Poor hash function which always returns 1 to simulate
* a Deny of Service attack.
*/
struct dos_attack_simulation_hash {
std::size_t operator()(int id) const {
return 1;
}
};
int main() {
/*
* Slow due to the hash function, insertions are done in O(n).
*/
tsl::hopscotch_map<int, int, dos_attack_simulation_hash> map;
auto start = std::chrono::high_resolution_clock::now();
for(int i=0; i < 10000; i++) {
map.insert({i, 0});
}
auto end = std::chrono::high_resolution_clock::now();
// 110 ms
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end-start);
std::cout << duration.count() << " ms" << std::endl;
/*
* Faster. Even with the poor hash function, insertions end-up to
* be O(log n) in average (and O(n) when a rehash occurs).
*/
tsl::hopscotch_sc_map<int, int, dos_attack_simulation_hash> map_secure;
start = std::chrono::high_resolution_clock::now();
for(int i=0; i < 10000; i++) {
map_secure.insert({i, 0});
}
end = std::chrono::high_resolution_clock::now();
// 2 ms
duration = std::chrono::duration_cast<std::chrono::milliseconds>(end-start);
std::cout << duration.count() << " ms" << std::endl;
}
```
### License
The code is licensed under the MIT license, see the [LICENSE file](LICENSE) for details.

File diff suppressed because it is too large Load Diff

View File

@ -1,666 +0,0 @@
/**
* MIT License
*
* Copyright (c) 2017 Tessil
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef TSL_HOPSCOTCH_MAP_H
#define TSL_HOPSCOTCH_MAP_H
#include <algorithm>
#include <cstddef>
#include <functional>
#include <initializer_list>
#include <list>
#include <memory>
#include <type_traits>
#include <utility>
#include "hopscotch_hash.h"
namespace tsl {
/**
* Implementation of a hash map using the hopscotch hashing algorithm.
*
* The Key and the value T must be either nothrow move-constructible, copy-constuctible or both.
*
* The size of the neighborhood (NeighborhoodSize) must be > 0 and <= 62 if StoreHash is false.
* When StoreHash is true, 32-bits of the hash will be stored alongside the neighborhood limiting
* the NeighborhoodSize to <= 30. There is no memory usage difference between
* 'NeighborhoodSize 62; StoreHash false' and 'NeighborhoodSize 30; StoreHash true'.
*
* Storing the hash may improve performance on insert during the rehash process if the hash takes time
* to compute. It may also improve read performance if the KeyEqual function takes time (or incurs a cache-miss).
* If used with simple Hash and KeyEqual it may slow things down.
*
* StoreHash can only be set if the GrowthPolicy is set to tsl::power_of_two_growth_policy.
*
* GrowthPolicy defines how the map grows and consequently how a hash value is mapped to a bucket.
* By default the map uses tsl::power_of_two_growth_policy. This policy keeps the number of buckets
* to a power of two and uses a mask to map the hash to a bucket instead of the slow modulo.
* You may define your own growth policy, check tsl::power_of_two_growth_policy for the interface.
*
* If the destructors of Key or T throw an exception, behaviour of the class is undefined.
*
* Iterators invalidation:
* - clear, operator=, reserve, rehash: always invalidate the iterators.
* - insert, emplace, emplace_hint, operator[]: if there is an effective insert, invalidate the iterators
* if a displacement is needed to resolve a collision (which mean that most of the time,
* insert will invalidate the iterators). Or if there is a rehash.
* - erase: iterator on the erased element is the only one which become invalid.
*/
template <typename Key,
class T,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<std::pair<Key, T>>,
unsigned int NeighborhoodSize = 62,
bool StoreHash = false,
class GrowthPolicy = tsl::power_of_two_growth_policy>
class hopscotch_map {
private:
template <typename U>
using has_is_transparent = tsl::detail_hopscotch_hash::has_is_transparent<U>;
class KeySelect {
public:
using key_type = Key;
const key_type& operator()(const std::pair<Key, T>& key_value) const {
return key_value.first;
}
key_type& operator()(std::pair<Key, T>& key_value) {
return key_value.first;
}
};
class ValueSelect {
public:
using value_type = T;
const value_type& operator()(const std::pair<Key, T>& key_value) const {
return key_value.second;
}
value_type& operator()(std::pair<Key, T>& key_value) {
return key_value.second;
}
};
using overflow_container_type = std::list<std::pair<Key, T>, Allocator>;
using ht = detail_hopscotch_hash::hopscotch_hash<std::pair<Key, T>, KeySelect, ValueSelect,
Hash, KeyEqual,
Allocator, NeighborhoodSize,
StoreHash, GrowthPolicy,
overflow_container_type>;
public:
using key_type = typename ht::key_type;
using mapped_type = T;
using value_type = typename ht::value_type;
using size_type = typename ht::size_type;
using difference_type = typename ht::difference_type;
using hasher = typename ht::hasher;
using key_equal = typename ht::key_equal;
using allocator_type = typename ht::allocator_type;
using reference = typename ht::reference;
using const_reference = typename ht::const_reference;
using pointer = typename ht::pointer;
using const_pointer = typename ht::const_pointer;
using iterator = typename ht::iterator;
using const_iterator = typename ht::const_iterator;
/*
* Constructors
*/
hopscotch_map() : hopscotch_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {
}
explicit hopscotch_map(size_type bucket_count,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) :
m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)
{
}
hopscotch_map(size_type bucket_count,
const Allocator& alloc) : hopscotch_map(bucket_count, Hash(), KeyEqual(), alloc)
{
}
hopscotch_map(size_type bucket_count,
const Hash& hash,
const Allocator& alloc) : hopscotch_map(bucket_count, hash, KeyEqual(), alloc)
{
}
explicit hopscotch_map(const Allocator& alloc) : hopscotch_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
}
template <typename InputIt>
hopscotch_map(InputIt first, InputIt last,
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) : hopscotch_map(bucket_count, hash, equal, alloc)
{
insert(first, last);
}
template <typename InputIt>
hopscotch_map(InputIt first, InputIt last,
size_type bucket_count,
const Allocator& alloc) : hopscotch_map(first, last, bucket_count, Hash(), KeyEqual(), alloc)
{
}
template <typename InputIt>
hopscotch_map(InputIt first, InputIt last,
size_type bucket_count,
const Hash& hash,
const Allocator& alloc) : hopscotch_map(first, last, bucket_count, hash, KeyEqual(), alloc)
{
}
hopscotch_map(std::initializer_list<value_type> init,
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) :
hopscotch_map(init.begin(), init.end(), bucket_count, hash, equal, alloc)
{
}
hopscotch_map(std::initializer_list<value_type> init,
size_type bucket_count,
const Allocator& alloc) :
hopscotch_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
{
}
hopscotch_map(std::initializer_list<value_type> init,
size_type bucket_count,
const Hash& hash,
const Allocator& alloc) :
hopscotch_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
{
}
hopscotch_map& operator=(std::initializer_list<value_type> ilist) {
m_ht.clear();
m_ht.reserve(ilist.size());
m_ht.insert(ilist.begin(), ilist.end());
return *this;
}
allocator_type get_allocator() const { return m_ht.get_allocator(); }
/*
* Iterators
*/
iterator begin() noexcept { return m_ht.begin(); }
const_iterator begin() const noexcept { return m_ht.begin(); }
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
iterator end() noexcept { return m_ht.end(); }
const_iterator end() const noexcept { return m_ht.end(); }
const_iterator cend() const noexcept { return m_ht.cend(); }
/*
* Capacity
*/
bool empty() const noexcept { return m_ht.empty(); }
size_type size() const noexcept { return m_ht.size(); }
size_type max_size() const noexcept { return m_ht.max_size(); }
/*
* Modifiers
*/
void clear() noexcept { m_ht.clear(); }
std::pair<iterator, bool> insert(const value_type& value) {
return m_ht.insert(value);
}
template <typename P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
std::pair<iterator, bool> insert(P&& value) {
return m_ht.insert(std::forward<P>(value));
}
std::pair<iterator, bool> insert(value_type&& value) {
return m_ht.insert(std::move(value));
}
iterator insert(const_iterator hint, const value_type& value) {
return m_ht.insert(hint, value);
}
template <typename P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
iterator insert(const_iterator hint, P&& value) {
return m_ht.insert(hint, std::forward<P>(value));
}
iterator insert(const_iterator hint, value_type&& value) {
return m_ht.insert(hint, std::move(value));
}
template <typename InputIt>
void insert(InputIt first, InputIt last) {
m_ht.insert(first, last);
}
void insert(std::initializer_list<value_type> ilist) {
m_ht.insert(ilist.begin(), ilist.end());
}
template <typename M>
std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj) {
return m_ht.insert_or_assign(k, std::forward<M>(obj));
}
template <typename M>
std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj) {
return m_ht.insert_or_assign(std::move(k), std::forward<M>(obj));
}
template <typename M>
iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj) {
return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));
}
template <typename M>
iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj) {
return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));
}
/**
* Due to the way elements are stored, emplace will need to move or copy the key-value once.
* The method is equivalent to insert(value_type(std::forward<Args>(args)...));
*
* Mainly here for compatibility with the std::unordered_map interface.
*/
template <typename... Args>
std::pair<iterator, bool> emplace(Args&&... args) {
return m_ht.emplace(std::forward<Args>(args)...);
}
/**
* Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
* The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));
*
* Mainly here for compatibility with the std::unordered_map interface.
*/
template <typename... Args>
iterator emplace_hint(const_iterator hint, Args&&... args) {
return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
}
template <typename... Args>
std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args) {
return m_ht.try_emplace(k, std::forward<Args>(args)...);
}
template <typename... Args>
std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args) {
return m_ht.try_emplace(std::move(k), std::forward<Args>(args)...);
}
template <typename... Args>
iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args) {
return m_ht.try_emplace(hint, k, std::forward<Args>(args)...);
}
template <typename... Args>
iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args) {
return m_ht.try_emplace(hint, std::move(k), std::forward<Args>(args)...);
}
iterator erase(iterator pos) { return m_ht.erase(pos); }
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
size_type erase(const key_type& key) { return m_ht.erase(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
*/
size_type erase(const key_type& key, std::size_t precalculated_hash) {
return m_ht.erase(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
size_type erase(const K& key) { return m_ht.erase(key); }
/**
* @copydoc erase(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
size_type erase(const K& key, std::size_t precalculated_hash) {
return m_ht.erase(key, precalculated_hash);
}
void swap(hopscotch_map& other) { other.m_ht.swap(m_ht); }
/*
* Lookup
*/
T& at(const Key& key) { return m_ht.at(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
T& at(const Key& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
const T& at(const Key& key) const { return m_ht.at(key); }
/**
* @copydoc at(const Key& key, std::size_t precalculated_hash)
*/
const T& at(const Key& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
T& at(const K& key) { return m_ht.at(key); }
/**
* @copydoc at(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
T& at(const K& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
/**
* @copydoc at(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
const T& at(const K& key) const { return m_ht.at(key); }
/**
* @copydoc at(const K& key, std::size_t precalculated_hash)
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
const T& at(const K& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
T& operator[](const Key& key) { return m_ht[key]; }
T& operator[](Key&& key) { return m_ht[std::move(key)]; }
size_type count(const Key& key) const { return m_ht.count(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
size_type count(const Key& key, std::size_t precalculated_hash) const {
return m_ht.count(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
size_type count(const K& key) const { return m_ht.count(key); }
/**
* @copydoc count(const K& key) const
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
size_type count(const K& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
iterator find(const Key& key) { return m_ht.find(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
const_iterator find(const Key& key) const { return m_ht.find(key); }
/**
* @copydoc find(const Key& key, std::size_t precalculated_hash)
*/
const_iterator find(const Key& key, std::size_t precalculated_hash) const {
return m_ht.find(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
iterator find(const K& key) { return m_ht.find(key); }
/**
* @copydoc find(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
/**
* @copydoc find(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
const_iterator find(const K& key) const { return m_ht.find(key); }
/**
* @copydoc find(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
const_iterator find(const K& key, std::size_t precalculated_hash) const {
return m_ht.find(key, precalculated_hash);
}
std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
return m_ht.equal_range(key, precalculated_hash);
}
std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
*/
std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
return m_ht.equal_range(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
return m_ht.equal_range(key, precalculated_hash);
}
/**
* @copydoc equal_range(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const K& key, std::size_t precalculated_hash)
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
return m_ht.equal_range(key, precalculated_hash);
}
/*
* Bucket interface
*/
size_type bucket_count() const { return m_ht.bucket_count(); }
size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
/*
* Hash policy
*/
float load_factor() const { return m_ht.load_factor(); }
float max_load_factor() const { return m_ht.max_load_factor(); }
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
void rehash(size_type count) { m_ht.rehash(count); }
void reserve(size_type count) { m_ht.reserve(count); }
/*
* Observers
*/
hasher hash_function() const { return m_ht.hash_function(); }
key_equal key_eq() const { return m_ht.key_eq(); }
/*
* Other
*/
/**
* Convert a const_iterator to an iterator.
*/
iterator mutable_iterator(const_iterator pos) {
return m_ht.mutable_iterator(pos);
}
size_type overflow_size() const noexcept { return m_ht.overflow_size(); }
friend bool operator==(const hopscotch_map& lhs, const hopscotch_map& rhs) {
if(lhs.size() != rhs.size()) {
return false;
}
for(const auto& element_lhs : lhs) {
const auto it_element_rhs = rhs.find(element_lhs.first);
if(it_element_rhs == rhs.cend() || element_lhs.second != it_element_rhs->second) {
return false;
}
}
return true;
}
friend bool operator!=(const hopscotch_map& lhs, const hopscotch_map& rhs) {
return !operator==(lhs, rhs);
}
friend void swap(hopscotch_map& lhs, hopscotch_map& rhs) {
lhs.swap(rhs);
}
private:
ht m_ht;
};
} // end namespace tsl
#endif

View File

@ -1,663 +0,0 @@
/**
* MIT License
*
* Copyright (c) 2017 Tessil
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef TSL_HOPSCOTCH_SC_MAP_H
#define TSL_HOPSCOTCH_SC_MAP_H
#include <algorithm>
#include <cstddef>
#include <functional>
#include <initializer_list>
#include <map>
#include <memory>
#include <type_traits>
#include <utility>
#include "hopscotch_hash.h"
namespace tsl {
/**
* Similar to tsl::hopscotch_map but instead of using a list for overflowing elements it uses
* a binary search tree. It thus needs an additional template parameter Compare. Compare should
* be arithmetically coherent with KeyEqual.
*
* The binary search tree allows the map to have a worst-case scenario of O(log n) for search
* and delete, even if the hash function maps all the elements to the same bucket.
* For insert, the amortized worst case is O(log n), but the worst case is O(n) in case of rehash.
*
* This makes the map resistant to DoS attacks (but doesn't preclude you to have a good hash function,
* as an element in the bucket array is faster to retrieve than in the tree).
*
* @copydoc hopscotch_map
*/
template <typename Key,
class T,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Compare = std::less<Key>,
class Allocator = std::allocator<std::pair<const Key, T>>,
unsigned int NeighborhoodSize = 62,
bool StoreHash = false,
class GrowthPolicy = tsl::power_of_two_growth_policy>
class hopscotch_sc_map {
private:
template <typename U>
using has_is_transparent = tsl::detail_hopscotch_hash::has_is_transparent<U>;
class KeySelect {
public:
using key_type = Key;
const key_type& operator()(const std::pair<const Key, T>& key_value) const {
return key_value.first;
}
const key_type& operator()(std::pair<const Key, T>& key_value) {
return key_value.first;
}
};
class ValueSelect {
public:
using value_type = T;
const value_type& operator()(const std::pair<const Key, T>& key_value) const {
return key_value.second;
}
value_type& operator()(std::pair<Key, T>& key_value) {
return key_value.second;
}
};
// TODO Not optimal as we have to use std::pair<const Key, T> as ValueType which forbid
// us to move the key in the bucket array, we have to use copy. Optimize.
using overflow_container_type = std::map<Key, T, Compare, Allocator>;
using ht = detail_hopscotch_hash::hopscotch_hash<std::pair<const Key, T>, KeySelect, ValueSelect,
Hash, KeyEqual,
Allocator, NeighborhoodSize,
StoreHash, GrowthPolicy,
overflow_container_type>;
public:
using key_type = typename ht::key_type;
using mapped_type = T;
using value_type = typename ht::value_type;
using size_type = typename ht::size_type;
using difference_type = typename ht::difference_type;
using hasher = typename ht::hasher;
using key_equal = typename ht::key_equal;
using key_compare = Compare;
using allocator_type = typename ht::allocator_type;
using reference = typename ht::reference;
using const_reference = typename ht::const_reference;
using pointer = typename ht::pointer;
using const_pointer = typename ht::const_pointer;
using iterator = typename ht::iterator;
using const_iterator = typename ht::const_iterator;
/*
* Constructors
*/
hopscotch_sc_map() : hopscotch_sc_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {
}
explicit hopscotch_sc_map(size_type bucket_count,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator(),
const Compare& comp = Compare()) :
m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR, comp)
{
}
hopscotch_sc_map(size_type bucket_count,
const Allocator& alloc) : hopscotch_sc_map(bucket_count, Hash(), KeyEqual(), alloc)
{
}
hopscotch_sc_map(size_type bucket_count,
const Hash& hash,
const Allocator& alloc) : hopscotch_sc_map(bucket_count, hash, KeyEqual(), alloc)
{
}
explicit hopscotch_sc_map(const Allocator& alloc) : hopscotch_sc_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
}
template <typename InputIt>
hopscotch_sc_map(InputIt first, InputIt last,
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) : hopscotch_sc_map(bucket_count, hash, equal, alloc)
{
insert(first, last);
}
template <typename InputIt>
hopscotch_sc_map(InputIt first, InputIt last,
size_type bucket_count,
const Allocator& alloc) : hopscotch_sc_map(first, last, bucket_count, Hash(), KeyEqual(), alloc)
{
}
template <typename InputIt>
hopscotch_sc_map(InputIt first, InputIt last,
size_type bucket_count,
const Hash& hash,
const Allocator& alloc) : hopscotch_sc_map(first, last, bucket_count, hash, KeyEqual(), alloc)
{
}
hopscotch_sc_map(std::initializer_list<value_type> init,
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) :
hopscotch_sc_map(init.begin(), init.end(), bucket_count, hash, equal, alloc)
{
}
hopscotch_sc_map(std::initializer_list<value_type> init,
size_type bucket_count,
const Allocator& alloc) :
hopscotch_sc_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
{
}
hopscotch_sc_map(std::initializer_list<value_type> init,
size_type bucket_count,
const Hash& hash,
const Allocator& alloc) :
hopscotch_sc_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
{
}
hopscotch_sc_map& operator=(std::initializer_list<value_type> ilist) {
m_ht.clear();
m_ht.reserve(ilist.size());
m_ht.insert(ilist.begin(), ilist.end());
return *this;
}
allocator_type get_allocator() const { return m_ht.get_allocator(); }
/*
* Iterators
*/
iterator begin() noexcept { return m_ht.begin(); }
const_iterator begin() const noexcept { return m_ht.begin(); }
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
iterator end() noexcept { return m_ht.end(); }
const_iterator end() const noexcept { return m_ht.end(); }
const_iterator cend() const noexcept { return m_ht.cend(); }
/*
* Capacity
*/
bool empty() const noexcept { return m_ht.empty(); }
size_type size() const noexcept { return m_ht.size(); }
size_type max_size() const noexcept { return m_ht.max_size(); }
/*
* Modifiers
*/
void clear() noexcept { m_ht.clear(); }
std::pair<iterator, bool> insert(const value_type& value) {
return m_ht.insert(value);
}
template <typename P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
std::pair<iterator, bool> insert(P&& value) {
return m_ht.insert(std::forward<P>(value));
}
std::pair<iterator, bool> insert(value_type&& value) {
return m_ht.insert(std::move(value));
}
iterator insert(const_iterator hint, const value_type& value) {
return m_ht.insert(hint, value);
}
template <typename P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
iterator insert(const_iterator hint, P&& value) {
return m_ht.insert(hint, std::forward<P>(value));
}
iterator insert(const_iterator hint, value_type&& value) {
return m_ht.insert(hint, std::move(value));
}
template <typename InputIt>
void insert(InputIt first, InputIt last) {
m_ht.insert(first, last);
}
void insert(std::initializer_list<value_type> ilist) {
m_ht.insert(ilist.begin(), ilist.end());
}
template <typename M>
std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj) {
return m_ht.insert_or_assign(k, std::forward<M>(obj));
}
template <typename M>
std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj) {
return m_ht.insert_or_assign(std::move(k), std::forward<M>(obj));
}
template <typename M>
iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj) {
return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));
}
template <typename M>
iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj) {
return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));
}
/**
* Due to the way elements are stored, emplace will need to move or copy the key-value once.
* The method is equivalent to insert(value_type(std::forward<Args>(args)...));
*
* Mainly here for compatibility with the std::unordered_map interface.
*/
template <typename... Args>
std::pair<iterator, bool> emplace(Args&&... args) {
return m_ht.emplace(std::forward<Args>(args)...);
}
/**
* Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
* The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));
*
* Mainly here for compatibility with the std::unordered_map interface.
*/
template <typename... Args>
iterator emplace_hint(const_iterator hint, Args&&... args) {
return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
}
template <typename... Args>
std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args) {
return m_ht.try_emplace(k, std::forward<Args>(args)...);
}
template <typename... Args>
std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args) {
return m_ht.try_emplace(std::move(k), std::forward<Args>(args)...);
}
template <typename... Args>
iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args) {
return m_ht.try_emplace(hint, k, std::forward<Args>(args)...);
}
template <typename... Args>
iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args) {
return m_ht.try_emplace(hint, std::move(k), std::forward<Args>(args)...);
}
iterator erase(iterator pos) { return m_ht.erase(pos); }
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
size_type erase(const key_type& key) { return m_ht.erase(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
*/
size_type erase(const key_type& key, std::size_t precalculated_hash) {
return m_ht.erase(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent
* and Compare::is_transparent exist.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
size_type erase(const K& key) { return m_ht.erase(key); }
/**
* @copydoc erase(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
size_type erase(const K& key, std::size_t precalculated_hash) { return m_ht.erase(key, precalculated_hash); }
void swap(hopscotch_sc_map& other) { other.m_ht.swap(m_ht); }
/*
* Lookup
*/
T& at(const Key& key) { return m_ht.at(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
T& at(const Key& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
const T& at(const Key& key) const { return m_ht.at(key); }
/**
* @copydoc at(const Key& key, std::size_t precalculated_hash)
*/
const T& at(const Key& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent
* and Compare::is_transparent exist.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
T& at(const K& key) { return m_ht.at(key); }
/**
* @copydoc at(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
T& at(const K& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
/**
* @copydoc at(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
const T& at(const K& key) const { return m_ht.at(key); }
/**
* @copydoc at(const K& key, std::size_t precalculated_hash)
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
const T& at(const K& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
T& operator[](const Key& key) { return m_ht[key]; }
T& operator[](Key&& key) { return m_ht[std::move(key)]; }
size_type count(const Key& key) const { return m_ht.count(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
size_type count(const Key& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent
* and Compare::is_transparent exist.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
size_type count(const K& key) const { return m_ht.count(key); }
/**
* @copydoc count(const K& key) const
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
size_type count(const K& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
iterator find(const Key& key) { return m_ht.find(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
const_iterator find(const Key& key) const { return m_ht.find(key); }
/**
* @copydoc find(const Key& key, std::size_t precalculated_hash)
*/
const_iterator find(const Key& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent
* and Compare::is_transparent exist.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
iterator find(const K& key) { return m_ht.find(key); }
/**
* @copydoc find(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
/**
* @copydoc find(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
const_iterator find(const K& key) const { return m_ht.find(key); }
/**
* @copydoc find(const K& key, std::size_t precalculated_hash)
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
const_iterator find(const K& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
return m_ht.equal_range(key, precalculated_hash);
}
std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
*/
std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
return m_ht.equal_range(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent
* and Compare::is_transparent exist.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
return m_ht.equal_range(key, precalculated_hash);
}
/**
* @copydoc equal_range(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const K& key, std::size_t precalculated_hash)
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
return m_ht.equal_range(key, precalculated_hash);
}
/*
* Bucket interface
*/
size_type bucket_count() const { return m_ht.bucket_count(); }
size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
/*
* Hash policy
*/
float load_factor() const { return m_ht.load_factor(); }
float max_load_factor() const { return m_ht.max_load_factor(); }
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
void rehash(size_type count) { m_ht.rehash(count); }
void reserve(size_type count) { m_ht.reserve(count); }
/*
* Observers
*/
hasher hash_function() const { return m_ht.hash_function(); }
key_equal key_eq() const { return m_ht.key_eq(); }
key_compare key_comp() const { return m_ht.key_comp(); }
/*
* Other
*/
/**
* Convert a const_iterator to an iterator.
*/
iterator mutable_iterator(const_iterator pos) {
return m_ht.mutable_iterator(pos);
}
size_type overflow_size() const noexcept { return m_ht.overflow_size(); }
friend bool operator==(const hopscotch_sc_map& lhs, const hopscotch_sc_map& rhs) {
if(lhs.size() != rhs.size()) {
return false;
}
for(const auto& element_lhs : lhs) {
const auto it_element_rhs = rhs.find(element_lhs.first);
if(it_element_rhs == rhs.cend() || element_lhs.second != it_element_rhs->second) {
return false;
}
}
return true;
}
friend bool operator!=(const hopscotch_sc_map& lhs, const hopscotch_sc_map& rhs) {
return !operator==(lhs, rhs);
}
friend void swap(hopscotch_sc_map& lhs, hopscotch_sc_map& rhs) {
lhs.swap(rhs);
}
private:
ht m_ht;
};
} // end namespace tsl
#endif

View File

@ -1,518 +0,0 @@
/**
* MIT License
*
* Copyright (c) 2017 Tessil
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef TSL_HOPSCOTCH_SC_SET_H
#define TSL_HOPSCOTCH_SC_SET_H
#include <algorithm>
#include <cstddef>
#include <functional>
#include <initializer_list>
#include <memory>
#include <set>
#include <type_traits>
#include <utility>
#include "hopscotch_hash.h"
namespace tsl {
/**
* Similar to tsl::hopscotch_set but instead of using a list for overflowing elements it uses
* a binary search tree. It thus needs an additional template parameter Compare. Compare should
* be arithmetically coherent with KeyEqual.
*
* The binary search tree allows the set to have a worst-case scenario of O(log n) for search
* and delete, even if the hash function maps all the elements to the same bucket.
* For insert, the amortized worst case is O(log n), but the worst case is O(n) in case of rehash.
*
* This makes the set resistant to DoS attacks (but doesn't preclude you to have a good hash function,
* as an element in the bucket array is faster to retrieve than in the tree).
*
* @copydoc hopscotch_set
*/
template <typename Key,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>,
unsigned int NeighborhoodSize = 62,
bool StoreHash = false,
class GrowthPolicy = tsl::power_of_two_growth_policy>
class hopscotch_sc_set {
private:
template <typename U>
using has_is_transparent = tsl::detail_hopscotch_hash::has_is_transparent<U>;
class KeySelect {
public:
using key_type = Key;
const key_type& operator()(const Key& key) const {
return key;
}
key_type& operator()(Key& key) {
return key;
}
};
using overflow_container_type = std::set<Key, Compare, Allocator>;
using ht = tsl::detail_hopscotch_hash::hopscotch_hash<Key, KeySelect, void,
Hash, KeyEqual,
Allocator, NeighborhoodSize,
StoreHash, GrowthPolicy,
overflow_container_type>;
public:
using key_type = typename ht::key_type;
using value_type = typename ht::value_type;
using size_type = typename ht::size_type;
using difference_type = typename ht::difference_type;
using hasher = typename ht::hasher;
using key_equal = typename ht::key_equal;
using key_compare = Compare;
using allocator_type = typename ht::allocator_type;
using reference = typename ht::reference;
using const_reference = typename ht::const_reference;
using pointer = typename ht::pointer;
using const_pointer = typename ht::const_pointer;
using iterator = typename ht::iterator;
using const_iterator = typename ht::const_iterator;
/*
* Constructors
*/
hopscotch_sc_set() : hopscotch_sc_set(ht::DEFAULT_INIT_BUCKETS_SIZE) {
}
explicit hopscotch_sc_set(size_type bucket_count,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator(),
const Compare& comp = Compare()) :
m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR, comp)
{
}
hopscotch_sc_set(size_type bucket_count,
const Allocator& alloc) : hopscotch_sc_set(bucket_count, Hash(), KeyEqual(), alloc)
{
}
hopscotch_sc_set(size_type bucket_count,
const Hash& hash,
const Allocator& alloc) : hopscotch_sc_set(bucket_count, hash, KeyEqual(), alloc)
{
}
explicit hopscotch_sc_set(const Allocator& alloc) : hopscotch_sc_set(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
}
template <typename InputIt>
hopscotch_sc_set(InputIt first, InputIt last,
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) : hopscotch_sc_set(bucket_count, hash, equal, alloc)
{
insert(first, last);
}
template <typename InputIt>
hopscotch_sc_set(InputIt first, InputIt last,
size_type bucket_count,
const Allocator& alloc) : hopscotch_sc_set(first, last, bucket_count, Hash(), KeyEqual(), alloc)
{
}
template <typename InputIt>
hopscotch_sc_set(InputIt first, InputIt last,
size_type bucket_count,
const Hash& hash,
const Allocator& alloc) : hopscotch_sc_set(first, last, bucket_count, hash, KeyEqual(), alloc)
{
}
hopscotch_sc_set(std::initializer_list<value_type> init,
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) :
hopscotch_sc_set(init.begin(), init.end(), bucket_count, hash, equal, alloc)
{
}
hopscotch_sc_set(std::initializer_list<value_type> init,
size_type bucket_count,
const Allocator& alloc) :
hopscotch_sc_set(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
{
}
hopscotch_sc_set(std::initializer_list<value_type> init,
size_type bucket_count,
const Hash& hash,
const Allocator& alloc) :
hopscotch_sc_set(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
{
}
hopscotch_sc_set& operator=(std::initializer_list<value_type> ilist) {
m_ht.clear();
m_ht.reserve(ilist.size());
m_ht.insert(ilist.begin(), ilist.end());
return *this;
}
allocator_type get_allocator() const { return m_ht.get_allocator(); }
/*
* Iterators
*/
iterator begin() noexcept { return m_ht.begin(); }
const_iterator begin() const noexcept { return m_ht.begin(); }
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
iterator end() noexcept { return m_ht.end(); }
const_iterator end() const noexcept { return m_ht.end(); }
const_iterator cend() const noexcept { return m_ht.cend(); }
/*
* Capacity
*/
bool empty() const noexcept { return m_ht.empty(); }
size_type size() const noexcept { return m_ht.size(); }
size_type max_size() const noexcept { return m_ht.max_size(); }
/*
* Modifiers
*/
void clear() noexcept { m_ht.clear(); }
std::pair<iterator, bool> insert(const value_type& value) { return m_ht.insert(value); }
std::pair<iterator, bool> insert(value_type&& value) { return m_ht.insert(std::move(value)); }
iterator insert(const_iterator hint, const value_type& value) { return m_ht.insert(hint, value); }
iterator insert(const_iterator hint, value_type&& value) { return m_ht.insert(hint, std::move(value)); }
template <typename InputIt>
void insert(InputIt first, InputIt last) { m_ht.insert(first, last); }
void insert(std::initializer_list<value_type> ilist) { m_ht.insert(ilist.begin(), ilist.end()); }
/**
* Due to the way elements are stored, emplace will need to move or copy the key-value once.
* The method is equivalent to insert(value_type(std::forward<Args>(args)...));
*
* Mainly here for compatibility with the std::unordered_map interface.
*/
template <typename... Args>
std::pair<iterator, bool> emplace(Args&&... args) { return m_ht.emplace(std::forward<Args>(args)...); }
/**
* Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
* The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));
*
* Mainly here for compatibility with the std::unordered_map interface.
*/
template <typename... Args>
iterator emplace_hint(const_iterator hint, Args&&... args) {
return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
}
iterator erase(iterator pos) { return m_ht.erase(pos); }
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
size_type erase(const key_type& key) { return m_ht.erase(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
*/
size_type erase(const key_type& key, std::size_t precalculated_hash) {
return m_ht.erase(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent
* and Compare::is_transparent exist.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
size_type erase(const K& key) { return m_ht.erase(key); }
/**
* @copydoc erase(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
size_type erase(const K& key, std::size_t precalculated_hash) { return m_ht.erase(key, precalculated_hash); }
void swap(hopscotch_sc_set& other) { other.m_ht.swap(m_ht); }
/*
* Lookup
*/
size_type count(const Key& key) const { return m_ht.count(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
size_type count(const Key& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent
* and Compare::is_transparent exist.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
size_type count(const K& key) const { return m_ht.count(key); }
/**
* @copydoc count(const K& key) const
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
size_type count(const K& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
iterator find(const Key& key) { return m_ht.find(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
const_iterator find(const Key& key) const { return m_ht.find(key); }
/**
* @copydoc find(const Key& key, std::size_t precalculated_hash)
*/
const_iterator find(const Key& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent
* and Compare::is_transparent exist.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
iterator find(const K& key) { return m_ht.find(key); }
/**
* @copydoc find(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
/**
* @copydoc find(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
const_iterator find(const K& key) const { return m_ht.find(key); }
/**
* @copydoc find(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
const_iterator find(const K& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
return m_ht.equal_range(key, precalculated_hash);
}
std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
*/
std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
return m_ht.equal_range(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent
* and Compare::is_transparent exist.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
return m_ht.equal_range(key, precalculated_hash);
}
/**
* @copydoc equal_range(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const K& key, std::size_t precalculated_hash)
*/
template <typename K, typename KE = KeyEqual, typename CP = Compare,
typename std::enable_if<has_is_transparent<KE>::value && has_is_transparent<CP>::value>::type* = nullptr>
std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
return m_ht.equal_range(key, precalculated_hash);
}
/*
* Bucket interface
*/
size_type bucket_count() const { return m_ht.bucket_count(); }
size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
/*
* Hash policy
*/
float load_factor() const { return m_ht.load_factor(); }
float max_load_factor() const { return m_ht.max_load_factor(); }
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
void rehash(size_type count) { m_ht.rehash(count); }
void reserve(size_type count) { m_ht.reserve(count); }
/*
* Observers
*/
hasher hash_function() const { return m_ht.hash_function(); }
key_equal key_eq() const { return m_ht.key_eq(); }
key_compare key_comp() const { return m_ht.key_comp(); }
/*
* Other
*/
/**
* Convert a const_iterator to an iterator.
*/
iterator mutable_iterator(const_iterator pos) {
return m_ht.mutable_iterator(pos);
}
size_type overflow_size() const noexcept { return m_ht.overflow_size(); }
friend bool operator==(const hopscotch_sc_set& lhs, const hopscotch_sc_set& rhs) {
if(lhs.size() != rhs.size()) {
return false;
}
for(const auto& element_lhs : lhs) {
const auto it_element_rhs = rhs.find(element_lhs);
if(it_element_rhs == rhs.cend()) {
return false;
}
}
return true;
}
friend bool operator!=(const hopscotch_sc_set& lhs, const hopscotch_sc_set& rhs) {
return !operator==(lhs, rhs);
}
friend void swap(hopscotch_sc_set& lhs, hopscotch_sc_set& rhs) {
lhs.swap(rhs);
}
private:
ht m_ht;
};
} // end namespace tsl
#endif

View File

@ -1,513 +0,0 @@
/**
* MIT License
*
* Copyright (c) 2017 Tessil
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef TSL_HOPSCOTCH_SET_H
#define TSL_HOPSCOTCH_SET_H
#include <algorithm>
#include <cstddef>
#include <functional>
#include <initializer_list>
#include <list>
#include <memory>
#include <type_traits>
#include <utility>
#include "hopscotch_hash.h"
namespace tsl {
/**
* Implementation of a hash set using the hopscotch hashing algorithm.
*
* The Key must be either nothrow move-constructible, copy-constuctible or both.
*
* The size of the neighborhood (NeighborhoodSize) must be > 0 and <= 62 if StoreHash is false.
* When StoreHash is true, 32-bits of the hash will be stored alongside the neighborhood limiting
* the NeighborhoodSize to <= 30. There is no memory usage difference between
* 'NeighborhoodSize 62; StoreHash false' and 'NeighborhoodSize 30; StoreHash true'.
*
* Storing the hash may improve performance on insert during the rehash process if the hash takes time
* to compute. It may also improve read performance if the KeyEqual function takes time (or incurs a cache-miss).
* If used with simple Hash and KeyEqual it may slow things down.
*
* StoreHash can only be set if the GrowthPolicy is set to tsl::power_of_two_growth_policy.
*
* GrowthPolicy defines how the set grows and consequently how a hash value is mapped to a bucket.
* By default the set uses tsl::power_of_two_growth_policy. This policy keeps the number of buckets
* to a power of two and uses a mask to set the hash to a bucket instead of the slow modulo.
* You may define your own growth policy, check tsl::power_of_two_growth_policy for the interface.
*
* If the destructor of Key throws an exception, behaviour of the class is undefined.
*
* Iterators invalidation:
* - clear, operator=, reserve, rehash: always invalidate the iterators.
* - insert, emplace, emplace_hint, operator[]: if there is an effective insert, invalidate the iterators
* if a displacement is needed to resolve a collision (which mean that most of the time,
* insert will invalidate the iterators). Or if there is a rehash.
* - erase: iterator on the erased element is the only one which become invalid.
*/
template <typename Key,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator<Key>,
unsigned int NeighborhoodSize = 62,
bool StoreHash = false,
class GrowthPolicy = tsl::power_of_two_growth_policy>
class hopscotch_set {
private:
template <typename U>
using has_is_transparent = tsl::detail_hopscotch_hash::has_is_transparent<U>;
class KeySelect {
public:
using key_type = Key;
const key_type& operator()(const Key& key) const {
return key;
}
key_type& operator()(Key& key) {
return key;
}
};
using overflow_container_type = std::list<Key, Allocator>;
using ht = detail_hopscotch_hash::hopscotch_hash<Key, KeySelect, void,
Hash, KeyEqual,
Allocator, NeighborhoodSize,
StoreHash, GrowthPolicy,
overflow_container_type>;
public:
using key_type = typename ht::key_type;
using value_type = typename ht::value_type;
using size_type = typename ht::size_type;
using difference_type = typename ht::difference_type;
using hasher = typename ht::hasher;
using key_equal = typename ht::key_equal;
using allocator_type = typename ht::allocator_type;
using reference = typename ht::reference;
using const_reference = typename ht::const_reference;
using pointer = typename ht::pointer;
using const_pointer = typename ht::const_pointer;
using iterator = typename ht::iterator;
using const_iterator = typename ht::const_iterator;
/*
* Constructors
*/
hopscotch_set() : hopscotch_set(ht::DEFAULT_INIT_BUCKETS_SIZE) {
}
explicit hopscotch_set(size_type bucket_count,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) :
m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)
{
}
hopscotch_set(size_type bucket_count,
const Allocator& alloc) : hopscotch_set(bucket_count, Hash(), KeyEqual(), alloc)
{
}
hopscotch_set(size_type bucket_count,
const Hash& hash,
const Allocator& alloc) : hopscotch_set(bucket_count, hash, KeyEqual(), alloc)
{
}
explicit hopscotch_set(const Allocator& alloc) : hopscotch_set(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
}
template <typename InputIt>
hopscotch_set(InputIt first, InputIt last,
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) : hopscotch_set(bucket_count, hash, equal, alloc)
{
insert(first, last);
}
template <typename InputIt>
hopscotch_set(InputIt first, InputIt last,
size_type bucket_count,
const Allocator& alloc) : hopscotch_set(first, last, bucket_count, Hash(), KeyEqual(), alloc)
{
}
template <typename InputIt>
hopscotch_set(InputIt first, InputIt last,
size_type bucket_count,
const Hash& hash,
const Allocator& alloc) : hopscotch_set(first, last, bucket_count, hash, KeyEqual(), alloc)
{
}
hopscotch_set(std::initializer_list<value_type> init,
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
const Hash& hash = Hash(),
const KeyEqual& equal = KeyEqual(),
const Allocator& alloc = Allocator()) :
hopscotch_set(init.begin(), init.end(), bucket_count, hash, equal, alloc)
{
}
hopscotch_set(std::initializer_list<value_type> init,
size_type bucket_count,
const Allocator& alloc) :
hopscotch_set(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
{
}
hopscotch_set(std::initializer_list<value_type> init,
size_type bucket_count,
const Hash& hash,
const Allocator& alloc) :
hopscotch_set(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
{
}
hopscotch_set& operator=(std::initializer_list<value_type> ilist) {
m_ht.clear();
m_ht.reserve(ilist.size());
m_ht.insert(ilist.begin(), ilist.end());
return *this;
}
allocator_type get_allocator() const { return m_ht.get_allocator(); }
/*
* Iterators
*/
iterator begin() noexcept { return m_ht.begin(); }
const_iterator begin() const noexcept { return m_ht.begin(); }
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
iterator end() noexcept { return m_ht.end(); }
const_iterator end() const noexcept { return m_ht.end(); }
const_iterator cend() const noexcept { return m_ht.cend(); }
/*
* Capacity
*/
bool empty() const noexcept { return m_ht.empty(); }
size_type size() const noexcept { return m_ht.size(); }
size_type max_size() const noexcept { return m_ht.max_size(); }
/*
* Modifiers
*/
void clear() noexcept { m_ht.clear(); }
std::pair<iterator, bool> insert(const value_type& value) { return m_ht.insert(value); }
std::pair<iterator, bool> insert(value_type&& value) { return m_ht.insert(std::move(value)); }
iterator insert(const_iterator hint, const value_type& value) { return m_ht.insert(hint, value); }
iterator insert(const_iterator hint, value_type&& value) { return m_ht.insert(hint, std::move(value)); }
template <typename InputIt>
void insert(InputIt first, InputIt last) { m_ht.insert(first, last); }
void insert(std::initializer_list<value_type> ilist) { m_ht.insert(ilist.begin(), ilist.end()); }
/**
* Due to the way elements are stored, emplace will need to move or copy the key-value once.
* The method is equivalent to insert(value_type(std::forward<Args>(args)...));
*
* Mainly here for compatibility with the std::unordered_map interface.
*/
template <typename... Args>
std::pair<iterator, bool> emplace(Args&&... args) { return m_ht.emplace(std::forward<Args>(args)...); }
/**
* Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
* The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));
*
* Mainly here for compatibility with the std::unordered_map interface.
*/
template <typename... Args>
iterator emplace_hint(const_iterator hint, Args&&... args) {
return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
}
iterator erase(iterator pos) { return m_ht.erase(pos); }
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
size_type erase(const key_type& key) { return m_ht.erase(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
*/
size_type erase(const key_type& key, std::size_t precalculated_hash) {
return m_ht.erase(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
size_type erase(const K& key) { return m_ht.erase(key); }
/**
* @copydoc erase(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
size_type erase(const K& key, std::size_t precalculated_hash) {
return m_ht.erase(key, precalculated_hash);
}
void swap(hopscotch_set& other) { other.m_ht.swap(m_ht); }
/*
* Lookup
*/
size_type count(const Key& key) const { return m_ht.count(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
size_type count(const Key& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
size_type count(const K& key) const { return m_ht.count(key); }
/**
* @copydoc count(const K& key) const
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
size_type count(const K& key, std::size_t precalculated_hash) const { return m_ht.count(key, precalculated_hash); }
iterator find(const Key& key) { return m_ht.find(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
const_iterator find(const Key& key) const { return m_ht.find(key); }
/**
* @copydoc find(const Key& key, std::size_t precalculated_hash)
*/
const_iterator find(const Key& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
iterator find(const K& key) { return m_ht.find(key); }
/**
* @copydoc find(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
/**
* @copydoc find(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
const_iterator find(const K& key) const { return m_ht.find(key); }
/**
* @copydoc find(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
const_iterator find(const K& key, std::size_t precalculated_hash) const { return m_ht.find(key, precalculated_hash); }
std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
/**
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
return m_ht.equal_range(key, precalculated_hash);
}
std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
*/
std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
return m_ht.equal_range(key, precalculated_hash);
}
/**
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
* If so, K must be hashable and comparable to Key.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const K& key)
*
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
return m_ht.equal_range(key, precalculated_hash);
}
/**
* @copydoc equal_range(const K& key)
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
/**
* @copydoc equal_range(const K& key, std::size_t precalculated_hash)
*/
template <typename K, typename KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
return m_ht.equal_range(key, precalculated_hash);
}
/*
* Bucket interface
*/
size_type bucket_count() const { return m_ht.bucket_count(); }
size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
/*
* Hash policy
*/
float load_factor() const { return m_ht.load_factor(); }
float max_load_factor() const { return m_ht.max_load_factor(); }
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
void rehash(size_type count) { m_ht.rehash(count); }
void reserve(size_type count) { m_ht.reserve(count); }
/*
* Observers
*/
hasher hash_function() const { return m_ht.hash_function(); }
key_equal key_eq() const { return m_ht.key_eq(); }
/*
* Other
*/
/**
* Convert a const_iterator to an iterator.
*/
iterator mutable_iterator(const_iterator pos) {
return m_ht.mutable_iterator(pos);
}
size_type overflow_size() const noexcept { return m_ht.overflow_size(); }
friend bool operator==(const hopscotch_set& lhs, const hopscotch_set& rhs) {
if(lhs.size() != rhs.size()) {
return false;
}
for(const auto& element_lhs : lhs) {
const auto it_element_rhs = rhs.find(element_lhs);
if(it_element_rhs == rhs.cend()) {
return false;
}
}
return true;
}
friend bool operator!=(const hopscotch_set& lhs, const hopscotch_set& rhs) {
return !operator==(lhs, rhs);
}
friend void swap(hopscotch_set& lhs, hopscotch_set& rhs) {
lhs.swap(rhs);
}
private:
ht m_ht;
};
} // end namespace tsl
#endif

View File

@ -18,9 +18,6 @@
#include <Common/HashTable/HashMap.h>
#include <Common/SipHash.h>
#include "hopscotch-map/src/hopscotch_map.h"
using Key = UInt64;
using Value = UInt64;
@ -288,22 +285,9 @@ namespace Hashes
}
template <typename Key, typename Mapped, typename Hash>
using HopscotchMap = tsl::hopscotch_map<Key, Mapped, Hash>;
template <template <typename...> class Map, typename Hash>
void NO_INLINE test(const Key * data, size_t size, std::function<void(Map<Key, Value, Hash>&)> init = {})
{
if (std::is_same<Map<Key, Value, Hash>, HopscotchMap<Key, Value, Hashes::IdentityHash>>::value
|| std::is_same<Map<Key, Value, Hash>, HopscotchMap<Key, Value, Hashes::SimpleMultiplyHash>>::value
|| std::is_same<Map<Key, Value, Hash>, HopscotchMap<Key, Value, Hashes::MixAllBitsHash>>::value)
{
std::cerr << __PRETTY_FUNCTION__ << ":\nDisqualified\n";
return;
}
Stopwatch watch;
Map<Key, Value, Hash> map;
@ -349,7 +333,6 @@ void NO_INLINE testForEachMapAndHash(const Key * data, size_t size)
testForEachHash<std::unordered_map>(data, size, nothing);
testForEachHash<google::dense_hash_map>(data, size, [](auto & map){ map.set_empty_key(-1); });
testForEachHash<google::sparse_hash_map>(data, size, nothing);
testForEachHash<HopscotchMap>(data, size, nothing);
}

View File

@ -55,11 +55,6 @@
#define DEFAULT_QUERIES_QUEUE_WAIT_TIME_MS 5000 /// Maximum waiting time in the request queue.
#define DBMS_DEFAULT_BACKGROUND_POOL_SIZE 16
/// Name suffix for the column containing the array offsets.
#define ARRAY_SIZES_COLUMN_NAME_SUFFIX ".size"
/// And NULL map.
#define NULL_MAP_COLUMN_NAME_SUFFIX ".null"
#define DBMS_MIN_REVISION_WITH_CLIENT_INFO 54032
#define DBMS_MIN_REVISION_WITH_SERVER_TIMEZONE 54058
#define DBMS_MIN_REVISION_WITH_QUOTA_KEY_IN_CLIENT_INFO 54060

View File

@ -47,7 +47,7 @@ std::ostream & operator<<(std::ostream & stream, const DB::IStorage & what)
return stream;
}
std::ostream & operator<<(std::ostream & stream, const DB::TableStructureReadLock & what)
std::ostream & operator<<(std::ostream & stream, const DB::TableStructureReadLock &)
{
stream << "TableStructureReadLock()";
return stream;

View File

@ -9,7 +9,6 @@
#include <DataStreams/BinaryRowOutputStream.h>
#include <DataStreams/ValuesRowInputStream.h>
#include <DataStreams/ValuesRowOutputStream.h>
#include <DataStreams/TabSeparatedBlockOutputStream.h>
#include <DataStreams/PrettyBlockOutputStream.h>
#include <DataStreams/PrettyCompactBlockOutputStream.h>
#include <DataStreams/PrettySpaceBlockOutputStream.h>
@ -113,7 +112,6 @@ BlockInputStreamPtr FormatFactory::getInput(const String & name, ReadBuffer & bu
#endif
else if (name == "TabSeparatedRaw"
|| name == "TSVRaw"
|| name == "BlockTabSeparated"
|| name == "Pretty"
|| name == "PrettyCompact"
|| name == "PrettyCompactMonoBlock"
@ -154,8 +152,6 @@ static BlockOutputStreamPtr getOutputImpl(const String & name, WriteBuffer & buf
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<TabSeparatedRowOutputStream>(buf, sample, true, true));
else if (name == "TabSeparatedRaw" || name == "TSVRaw")
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<TabSeparatedRawRowOutputStream>(buf, sample));
else if (name == "BlockTabSeparated")
return std::make_shared<TabSeparatedBlockOutputStream>(buf);
else if (name == "CSV")
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<CSVRowOutputStream>(buf, sample));
else if (name == "CSVWithNames")
@ -181,10 +177,10 @@ static BlockOutputStreamPtr getOutputImpl(const String & name, WriteBuffer & buf
return std::make_shared<PrettySpaceBlockOutputStream>(buf, true, settings.output_format_pretty_max_rows, context);
else if (name == "Vertical")
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<VerticalRowOutputStream>(
buf, sample, settings.output_format_pretty_max_rows, context));
buf, sample, settings.output_format_pretty_max_rows));
else if (name == "VerticalRaw")
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<VerticalRawRowOutputStream>(
buf, sample, settings.output_format_pretty_max_rows, context));
buf, sample, settings.output_format_pretty_max_rows));
else if (name == "Values")
return std::make_shared<BlockOutputStreamFromRowOutputStream>(std::make_shared<ValuesRowOutputStream>(buf));
else if (name == "JSON")

View File

@ -43,14 +43,14 @@ public:
/** Methods to set additional information for output in formats, that support it.
*/
virtual void setRowsBeforeLimit(size_t rows_before_limit) {}
virtual void setTotals(const Block & totals) {}
virtual void setExtremes(const Block & extremes) {}
virtual void setRowsBeforeLimit(size_t /*rows_before_limit*/) {}
virtual void setTotals(const Block & /*totals*/) {}
virtual void setExtremes(const Block & /*extremes*/) {}
/** Notify about progress. Method could be called from different threads.
* Passed value are delta, that must be summarized.
*/
virtual void onProgress(const Progress & progress) {}
virtual void onProgress(const Progress & /*progress*/) {}
/** Content-Type to set when sending HTTP response. */
virtual String getContentType() const { return "text/plain; charset=UTF-8"; }

View File

@ -48,7 +48,7 @@ NativeBlockInputStream::NativeBlockInputStream(
void NativeBlockInputStream::readData(const IDataType & type, IColumn & column, ReadBuffer & istr, size_t rows, double avg_value_size_hint)
{
IDataType::InputStreamGetter input_stream_getter = [&] (const IDataType::SubstreamPath & path) { return &istr; };
IDataType::InputStreamGetter input_stream_getter = [&] (const IDataType::SubstreamPath &) { return &istr; };
type.deserializeBinaryBulkWithMultipleStreams(column, input_stream_getter, rows, avg_value_size_hint, false, {});
if (column.size() != rows)

View File

@ -60,7 +60,7 @@ void NativeBlockOutputStream::writeData(const IDataType & type, const ColumnPtr
else
full_column = column;
IDataType::OutputStreamGetter output_stream_getter = [&] (const IDataType::SubstreamPath & path) { return &ostr; };
IDataType::OutputStreamGetter output_stream_getter = [&] (const IDataType::SubstreamPath &) { return &ostr; };
type.serializeBinaryBulkWithMultipleStreams(*full_column, output_stream_getter, offset, limit, false, {});
}

View File

@ -11,7 +11,7 @@ namespace DB
class NullBlockOutputStream : public IBlockOutputStream
{
public:
void write(const Block & block) override {}
void write(const Block &) override {}
};
}

View File

@ -45,22 +45,22 @@ enum class StreamUnionMode
struct ParallelInputsHandler
{
/// Processing the data block.
void onBlock(Block & block, size_t thread_num) {}
void onBlock(Block & /*block*/, size_t /*thread_num*/) {}
/// Processing the data block + additional information.
void onBlock(Block & block, BlockExtraInfo & extra_info, size_t thread_num) {}
void onBlock(Block & /*block*/, BlockExtraInfo & /*extra_info*/, size_t /*thread_num*/) {}
/// Called for each thread, when the thread has nothing else to do.
/// Due to the fact that part of the sources has run out, and now there are fewer sources left than streams.
/// Called if the `onException` method does not throw an exception; is called before the `onFinish` method.
void onFinishThread(size_t thread_num) {}
void onFinishThread(size_t /*thread_num*/) {}
/// Blocks are over. Due to the fact that all sources ran out or because of the cancellation of work.
/// This method is always called exactly once, at the end of the work, if the `onException` method does not throw an exception.
void onFinish() {}
/// Exception handling. It is reasonable to call the ParallelInputsProcessor::cancel method in this method, and also pass the exception to the main thread.
void onException(std::exception_ptr & exception, size_t thread_num) {}
void onException(std::exception_ptr & /*exception*/, size_t /*thread_num*/) {}
};
@ -158,19 +158,15 @@ private:
InputData(const BlockInputStreamPtr & in_, size_t i_) : in(in_), i(i_) {}
};
template <StreamUnionMode mode2 = mode>
void publishPayload(BlockInputStreamPtr & stream, Block & block, size_t thread_num,
typename std::enable_if<mode2 == StreamUnionMode::Basic>::type * = nullptr)
void publishPayload(BlockInputStreamPtr & stream, Block & block, size_t thread_num)
{
handler.onBlock(block, thread_num);
}
template <StreamUnionMode mode2 = mode>
void publishPayload(BlockInputStreamPtr & stream, Block & block, size_t thread_num,
typename std::enable_if<mode2 == StreamUnionMode::ExtraInfo>::type * = nullptr)
{
BlockExtraInfo extra_info = stream->getBlockExtraInfo();
handler.onBlock(block, extra_info, thread_num);
if constexpr (mode == StreamUnionMode::Basic)
handler.onBlock(block, thread_num);
else
{
BlockExtraInfo extra_info = stream->getBlockExtraInfo();
handler.onBlock(block, extra_info, thread_num);
}
}
void thread(MemoryTracker * memory_tracker, size_t thread_num)

View File

@ -76,8 +76,7 @@ void PrettyCompactBlockOutputStream::writeRow(
size_t row_num,
const Block & block,
const WidthsPerColumn & widths,
const Widths & max_widths,
const Widths & name_widths)
const Widths & max_widths)
{
size_t columns = max_widths.size();
@ -112,7 +111,7 @@ void PrettyCompactBlockOutputStream::write(const Block & block)
writeHeader(block, max_widths, name_widths);
for (size_t i = 0; i < rows && total_rows + i < max_rows; ++i)
writeRow(i, block, widths, max_widths, name_widths);
writeRow(i, block, widths, max_widths);
writeBottom(max_widths);

Some files were not shown because too many files have changed in this diff Show More