mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 09:32:06 +00:00
Merge remote-tracking branch 'origin' into unbundled-packager
This commit is contained in:
commit
251f9651e2
@ -202,9 +202,16 @@ if (ARCH_NATIVE)
|
||||
set (COMPILER_FLAGS "${COMPILER_FLAGS} -march=native")
|
||||
endif ()
|
||||
|
||||
# cmake < 3.12 doesn't supoprt 20. We'll set CMAKE_CXX_FLAGS for now
|
||||
if (UNBUNDLED AND (COMPILER_GCC OR COMPILER_CLANG))
|
||||
# to make numeric_limits<__int128> works for unbundled build
|
||||
set (_CXX_STANDARD "-std=gnu++2a")
|
||||
else()
|
||||
set (_CXX_STANDARD "-std=c++2a")
|
||||
endif()
|
||||
# cmake < 3.12 doesn't support 20. We'll set CMAKE_CXX_FLAGS for now
|
||||
# set (CMAKE_CXX_STANDARD 20)
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++2a")
|
||||
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${_CXX_STANDARD}")
|
||||
|
||||
set (CMAKE_CXX_EXTENSIONS 0) # https://cmake.org/cmake/help/latest/prop_tgt/CXX_EXTENSIONS.html#prop_tgt:CXX_EXTENSIONS
|
||||
set (CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/types.h>
|
||||
|
||||
namespace common
|
||||
{
|
||||
template <typename T>
|
||||
@ -35,6 +37,21 @@ namespace common
|
||||
return (y > 0 && x > max_int128 - y) || (y < 0 && x < min_int128 - y);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool addOverflow(bInt256 x, bInt256 y, bInt256 & res)
|
||||
{
|
||||
res = x + y;
|
||||
return (y > 0 && x > std::numeric_limits<bInt256>::max() - y) ||
|
||||
(y < 0 && x < std::numeric_limits<bInt256>::min() - y);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool addOverflow(bUInt256 x, bUInt256 y, bUInt256 & res)
|
||||
{
|
||||
res = x + y;
|
||||
return x > std::numeric_limits<bUInt256>::max() - y;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool subOverflow(T x, T y, T & res)
|
||||
{
|
||||
@ -68,6 +85,21 @@ namespace common
|
||||
return (y < 0 && x > max_int128 + y) || (y > 0 && x < min_int128 + y);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool subOverflow(bInt256 x, bInt256 y, bInt256 & res)
|
||||
{
|
||||
res = x - y;
|
||||
return (y < 0 && x > std::numeric_limits<bInt256>::max() + y) ||
|
||||
(y > 0 && x < std::numeric_limits<bInt256>::min() + y);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool subOverflow(bUInt256 x, bUInt256 y, bUInt256 & res)
|
||||
{
|
||||
res = x - y;
|
||||
return x < y;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool mulOverflow(T x, T y, T & res)
|
||||
{
|
||||
@ -103,4 +135,25 @@ namespace common
|
||||
unsigned __int128 b = (y > 0) ? y : -y;
|
||||
return (a * b) / b != a;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool mulOverflow(bInt256 x, bInt256 y, bInt256 & res)
|
||||
{
|
||||
res = x * y;
|
||||
if (!x || !y)
|
||||
return false;
|
||||
|
||||
bInt256 a = (x > 0) ? x : -x;
|
||||
bInt256 b = (y > 0) ? y : -y;
|
||||
return (a * b) / b != a;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool mulOverflow(bUInt256 x, bUInt256 y, bUInt256 & res)
|
||||
{
|
||||
res = x * y;
|
||||
if (!x || !y)
|
||||
return false;
|
||||
return (x * y) / y != x;
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,15 @@
|
||||
include (${ClickHouse_SOURCE_DIR}/cmake/add_check.cmake)
|
||||
|
||||
add_executable (date_lut_init date_lut_init.cpp)
|
||||
add_executable (date_lut2 date_lut2.cpp)
|
||||
add_executable (date_lut3 date_lut3.cpp)
|
||||
add_executable (date_lut4 date_lut4.cpp)
|
||||
add_executable (date_lut_default_timezone date_lut_default_timezone.cpp)
|
||||
add_executable (local_date_time_comparison local_date_time_comparison.cpp)
|
||||
add_executable (realloc-perf allocator.cpp)
|
||||
|
||||
set(PLATFORM_LIBS ${CMAKE_DL_LIBS})
|
||||
|
||||
target_link_libraries (date_lut_init PRIVATE common ${PLATFORM_LIBS})
|
||||
target_link_libraries (date_lut2 PRIVATE common ${PLATFORM_LIBS})
|
||||
target_link_libraries (date_lut3 PRIVATE common ${PLATFORM_LIBS})
|
||||
target_link_libraries (date_lut4 PRIVATE common ${PLATFORM_LIBS})
|
||||
target_link_libraries (date_lut_default_timezone PRIVATE common ${PLATFORM_LIBS})
|
||||
target_link_libraries (local_date_time_comparison PRIVATE common)
|
||||
target_link_libraries (realloc-perf PRIVATE common)
|
||||
|
@ -1,20 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <common/DateLUT.h>
|
||||
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
/** В DateLUT был глюк - для времён из дня 1970-01-01, возвращался номер часа больше 23. */
|
||||
static const time_t time = 66130;
|
||||
|
||||
const auto & date_lut = DateLUT::instance();
|
||||
|
||||
std::cerr << date_lut.toHour(time) << std::endl;
|
||||
std::cerr << date_lut.toDayNum(time) << std::endl;
|
||||
|
||||
const auto * values = reinterpret_cast<const DateLUTImpl::Values *>(&date_lut);
|
||||
|
||||
std::cerr << values[0].date << ", " << time_t(values[1].date - values[0].date) << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#include <common/DateLUT.h>
|
||||
|
||||
/// Позволяет проверить время инициализации DateLUT.
|
||||
int main(int, char **)
|
||||
{
|
||||
DateLUT::instance();
|
||||
return 0;
|
||||
}
|
@ -6,6 +6,8 @@
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
using Int8 = int8_t;
|
||||
using Int16 = int16_t;
|
||||
using Int32 = int32_t;
|
||||
@ -15,11 +17,21 @@ using Int64 = int64_t;
|
||||
using char8_t = unsigned char;
|
||||
#endif
|
||||
|
||||
/// This is needed for more strict aliasing. https://godbolt.org/z/xpJBSb https://stackoverflow.com/a/57453713
|
||||
using UInt8 = char8_t;
|
||||
using UInt16 = uint16_t;
|
||||
using UInt32 = uint32_t;
|
||||
using UInt64 = uint64_t;
|
||||
|
||||
using Int128 = __int128;
|
||||
|
||||
/// We have to use 127 and 255 bit integers to safe a bit for a sign serialization
|
||||
//using bInt256 = boost::multiprecision::int256_t;
|
||||
using bInt256 = boost::multiprecision::number<boost::multiprecision::cpp_int_backend<
|
||||
255, 255, boost::multiprecision::signed_magnitude, boost::multiprecision::unchecked, void> >;
|
||||
using bUInt256 = boost::multiprecision::uint256_t;
|
||||
|
||||
|
||||
using String = std::string;
|
||||
|
||||
/// The standard library type traits, such as std::is_arithmetic, with one exception
|
||||
@ -31,6 +43,9 @@ struct is_signed
|
||||
static constexpr bool value = std::is_signed_v<T>;
|
||||
};
|
||||
|
||||
template <> struct is_signed<Int128> { static constexpr bool value = true; };
|
||||
template <> struct is_signed<bInt256> { static constexpr bool value = true; };
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_signed_v = is_signed<T>::value;
|
||||
|
||||
@ -40,17 +55,26 @@ struct is_unsigned
|
||||
static constexpr bool value = std::is_unsigned_v<T>;
|
||||
};
|
||||
|
||||
template <> struct is_unsigned<bUInt256> { static constexpr bool value = true; };
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_unsigned_v = is_unsigned<T>::value;
|
||||
|
||||
|
||||
/// TODO: is_integral includes char, char8_t and wchar_t.
|
||||
template <typename T>
|
||||
struct is_integral
|
||||
struct is_integer
|
||||
{
|
||||
static constexpr bool value = std::is_integral_v<T>;
|
||||
};
|
||||
|
||||
template <> struct is_integer<Int128> { static constexpr bool value = true; };
|
||||
template <> struct is_integer<bInt256> { static constexpr bool value = true; };
|
||||
template <> struct is_integer<bUInt256> { static constexpr bool value = true; };
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_integral_v = is_integral<T>::value;
|
||||
inline constexpr bool is_integer_v = is_integer<T>::value;
|
||||
|
||||
|
||||
template <typename T>
|
||||
struct is_arithmetic
|
||||
@ -58,5 +82,42 @@ struct is_arithmetic
|
||||
static constexpr bool value = std::is_arithmetic_v<T>;
|
||||
};
|
||||
|
||||
template <> struct is_arithmetic<__int128> { static constexpr bool value = true; };
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_arithmetic_v = is_arithmetic<T>::value;
|
||||
|
||||
template <typename T>
|
||||
struct make_unsigned
|
||||
{
|
||||
typedef std::make_unsigned_t<T> type;
|
||||
};
|
||||
|
||||
template <> struct make_unsigned<__int128> { using type = unsigned __int128; };
|
||||
template <> struct make_unsigned<bInt256> { using type = bUInt256; };
|
||||
template <> struct make_unsigned<bUInt256> { using type = bUInt256; };
|
||||
|
||||
template <typename T> using make_unsigned_t = typename make_unsigned<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct make_signed
|
||||
{
|
||||
typedef std::make_signed_t<T> type;
|
||||
};
|
||||
|
||||
template <> struct make_signed<bInt256> { typedef bInt256 type; };
|
||||
template <> struct make_signed<bUInt256> { typedef bInt256 type; };
|
||||
|
||||
template <typename T> using make_signed_t = typename make_signed<T>::type;
|
||||
|
||||
template <typename T>
|
||||
struct is_big_int
|
||||
{
|
||||
static constexpr bool value = false;
|
||||
};
|
||||
|
||||
template <> struct is_big_int<bUInt256> { static constexpr bool value = true; };
|
||||
template <> struct is_big_int<bInt256> { static constexpr bool value = true; };
|
||||
|
||||
template <typename T>
|
||||
inline constexpr bool is_big_int_v = is_big_int<T>::value;
|
||||
|
@ -217,7 +217,7 @@ clickhouse-test -j 4 --no-long --testname --shard --zookeeper --skip "${TESTS_TO
|
||||
|
||||
|
||||
# substr is to remove semicolon after test name
|
||||
readarray -t FAILED_TESTS < <(awk '/FAIL|TIMEOUT|ERROR/ { print substr($3, 1, length($3)-1) }' /test_output/test_log.txt)
|
||||
readarray -t FAILED_TESTS < <(awk '/FAIL|TIMEOUT|ERROR/ { print substr($3, 1, length($3)-1) }' /test_output/test_log.txt | tee /test_output/failed-parallel-tests.txt)
|
||||
|
||||
# We will rerun sequentially any tests that have failed during parallel run.
|
||||
# They might have failed because there was some interference from other tests
|
||||
|
@ -703,7 +703,7 @@ But other things being equal, cross-platform or portable code is preferred.
|
||||
|
||||
**3.** Compiler: `gcc`. At this time (August 2020), the code is compiled using version 9.3. (It can also be compiled using `clang 8`.)
|
||||
|
||||
The standard library is used (`libstdc++` or `libc++`).
|
||||
The standard library is used (`libc++`).
|
||||
|
||||
**4.**OS: Linux Ubuntu, not older than Precise.
|
||||
|
||||
|
@ -168,7 +168,7 @@ Main ClickHouse code (that is located in `dbms` directory) is built with `-Wall
|
||||
|
||||
Clang has even more useful warnings - you can look for them with `-Weverything` and pick something to default build.
|
||||
|
||||
For production builds, gcc is used (it still generates slightly more efficient code than clang). For development, clang is usually more convenient to use. You can build on your own machine with debug mode (to save battery of your laptop), but please note that compiler is able to generate more warnings with `-O3` due to better control flow and inter-procedure analysis. When building with clang, `libc++` is used instead of `libstdc++` and when building with debug mode, debug version of `libc++` is used that allows to catch more errors at runtime.
|
||||
For production builds, gcc is used (it still generates slightly more efficient code than clang). For development, clang is usually more convenient to use. You can build on your own machine with debug mode (to save battery of your laptop), but please note that compiler is able to generate more warnings with `-O3` due to better control flow and inter-procedure analysis. When building with clang in debug mode, debug version of `libc++` is used that allows to catch more errors at runtime.
|
||||
|
||||
## Sanitizers {#sanitizers}
|
||||
|
||||
|
@ -15,6 +15,7 @@ toc_title: Adopters
|
||||
| <a href="https://amadeus.com/" class="favicon">Amadeus</a> | Travel | Analytics | — | — | [Press Release, April 2018](https://www.altinity.com/blog/2018/4/5/amadeus-technologies-launches-investment-and-insights-tool-based-on-machine-learning-and-strategy-algorithms) |
|
||||
| <a href="https://www.appsflyer.com" class="favicon">Appsflyer</a> | Mobile analytics | Main product | — | — | [Talk in Russian, July 2019](https://www.youtube.com/watch?v=M3wbRlcpBbY) |
|
||||
| <a href="https://arenadata.tech/" class="favicon">ArenaData</a> | Data Platform | Main product | — | — | [Slides in Russian, December 2019](https://github.com/ClickHouse/clickhouse-presentations/blob/master/meetup38/indexes.pdf) |
|
||||
| <a href="https://avito.ru/" class="favicon">Avito</a> | Classifieds | Monitoring | — | — | [Meetup, April 2020](https://www.youtube.com/watch?v=n1tm4j4W8ZQ) |
|
||||
| <a href="https://badoo.com" class="favicon">Badoo</a> | Dating | Timeseries | — | — | [Slides in Russian, December 2019](https://presentations.clickhouse.tech/meetup38/forecast.pdf) |
|
||||
| <a href="https://www.benocs.com/" class="favicon">Benocs</a> | Network Telemetry and Analytics | Main Product | — | — | [Slides in English, October 2017](https://github.com/ClickHouse/clickhouse-presentations/blob/master/meetup9/lpm.pdf) |
|
||||
| <a href="https://www.bloomberg.com/" class="favicon">Bloomberg</a> | Finance, Media | Monitoring | 102 servers | — | [Slides, May 2018](https://www.slideshare.net/Altinity/http-analytics-for-6m-requests-per-second-using-clickhouse-by-alexander-bocharov) |
|
||||
@ -95,5 +96,6 @@ toc_title: Adopters
|
||||
| <a href="https://metrica.yandex.com" class="favicon">Yandex Metrica</a> | Web analytics | Main product | 360 servers in one cluster, 1862 servers in one department | 66.41 PiB / 5.68 PiB | [Slides, February 2020](https://presentations.clickhouse.tech/meetup40/introduction/#13) |
|
||||
| <a href="https://htc-cs.ru/" class="favicon">ЦВТ</a> | Software Development | Metrics, Logging | — | — | [Blog Post, March 2019, in Russian](https://vc.ru/dev/62715-kak-my-stroili-monitoring-na-prometheus-clickhouse-i-elk) |
|
||||
| <a href="https://mkb.ru/" class="favicon">МКБ</a> | Bank | Web-system monitoring | — | — | [Slides in Russian, September 2019](https://github.com/ClickHouse/clickhouse-presentations/blob/master/meetup28/mkb.pdf) |
|
||||
| <a href="https://cft.ru/" class="favicon">ЦФТ</a> | Banking, Financial products, Payments | — | — | — | [Meetup in Russian, April 2020](https://team.cft.ru/events/162) |
|
||||
|
||||
[Original article](https://clickhouse.tech/docs/en/introduction/adopters/) <!--hide-->
|
||||
|
@ -705,7 +705,7 @@ Pero en igualdad de condiciones, se prefiere el código multiplataforma o portá
|
||||
|
||||
**3.** Compilación: `gcc`. En este momento (agosto 2020), el código se compila utilizando la versión 9.3. (También se puede compilar usando `clang 8`.)
|
||||
|
||||
Se utiliza la biblioteca estándar (`libstdc++` o `libc++`).
|
||||
Se utiliza la biblioteca estándar (`libc++`).
|
||||
|
||||
**4.**OS: Linux Ubuntu, no más viejo que Precise.
|
||||
|
||||
|
@ -175,7 +175,7 @@ Código principal de ClickHouse (que se encuentra en `dbms` directorio) se const
|
||||
|
||||
Clang tiene advertencias aún más útiles: puedes buscarlas con `-Weverything` y elige algo para la compilación predeterminada.
|
||||
|
||||
Para las compilaciones de producción, se usa gcc (todavía genera un código ligeramente más eficiente que clang). Para el desarrollo, el clang suele ser más conveniente de usar. Puede construir en su propia máquina con el modo de depuración (para ahorrar batería de su computadora portátil), pero tenga en cuenta que el compilador puede generar más advertencias con `-O3` debido a un mejor flujo de control y análisis entre procedimientos. Al construir con clang, `libc++` se utiliza en lugar de `libstdc++` y al construir con el modo de depuración, la versión de depuración de `libc++` se utiliza que permite detectar más errores en tiempo de ejecución.
|
||||
Para las compilaciones de producción, se usa gcc (todavía genera un código ligeramente más eficiente que clang). Para el desarrollo, el clang suele ser más conveniente de usar. Puede construir en su propia máquina con el modo de depuración (para ahorrar batería de su computadora portátil), pero tenga en cuenta que el compilador puede generar más advertencias con `-O3` debido a un mejor flujo de control y análisis entre procedimientos. Al construir con clang con el modo de depuración, la versión de depuración de `libc++` se utiliza que permite detectar más errores en tiempo de ejecución.
|
||||
|
||||
## Desinfectantes {#sanitizers}
|
||||
|
||||
|
@ -706,7 +706,7 @@ auto s = std::string{"Hello"};
|
||||
|
||||
**3.** کامپایلر: `gcc`. در این زمان (اوت 2020), کد با استفاده از نسخه وارد شده 9.3. (همچنین می تواند با استفاده از وارد شود `clang 8`.)
|
||||
|
||||
کتابخانه استاندارد استفاده شده است (`libstdc++` یا `libc++`).
|
||||
کتابخانه استاندارد استفاده شده است (`libc++`).
|
||||
|
||||
**4.**سیستم عامل: لینوکس اوبونتو, مسن تر از دقیق نیست.
|
||||
|
||||
|
@ -705,7 +705,7 @@ Mais toutes choses étant égales par ailleurs, le code multi-plateforme ou port
|
||||
|
||||
**3.** Compilateur: `gcc`. En ce moment (août 2020), le code est compilé en utilisant la version 9.3. (Il peut également être compilé en utilisant `clang 8`.)
|
||||
|
||||
La bibliothèque standard est utilisée (`libstdc++` ou `libc++`).
|
||||
La bibliothèque standard est utilisée (`libc++`).
|
||||
|
||||
**4.**OS: Linux Ubuntu, pas plus vieux que précis.
|
||||
|
||||
|
@ -175,7 +175,7 @@ Code ClickHouse principal (qui est situé dans `dbms` annuaire) est construit av
|
||||
|
||||
Clang a des avertissements encore plus utiles - vous pouvez les chercher avec `-Weverything` et choisissez quelque chose à construire par défaut.
|
||||
|
||||
Pour les builds de production, gcc est utilisé (il génère toujours un code légèrement plus efficace que clang). Pour le développement, clang est généralement plus pratique à utiliser. Vous pouvez construire sur votre propre machine avec le mode débogage (pour économiser la batterie de votre ordinateur portable), mais veuillez noter que le compilateur est capable de générer plus d'Avertissements avec `-O3` grâce à une meilleure analyse du flux de contrôle et de l'inter-procédure. Lors de la construction avec clang, `libc++` est utilisé au lieu de `libstdc++` et lors de la construction avec le mode débogage, la version de débogage de `libc++` est utilisé qui permet d'attraper plus d'erreurs à l'exécution.
|
||||
Pour les builds de production, gcc est utilisé (il génère toujours un code légèrement plus efficace que clang). Pour le développement, clang est généralement plus pratique à utiliser. Vous pouvez construire sur votre propre machine avec le mode débogage (pour économiser la batterie de votre ordinateur portable), mais veuillez noter que le compilateur est capable de générer plus d'Avertissements avec `-O3` grâce à une meilleure analyse du flux de contrôle et de l'inter-procédure. Lors de la construction avec clang avec le mode débogage, la version de débogage de `libc++` est utilisé qui permet d'attraper plus d'erreurs à l'exécution.
|
||||
|
||||
## Désinfectant {#sanitizers}
|
||||
|
||||
|
@ -705,7 +705,7 @@ auto s = std::string{"Hello"};
|
||||
|
||||
**3.** コンパイラ: `gcc`. 2020年現在、コードはバージョン9.3を使用してコンパイルされている。 (以下を使ってコンパイルできます `clang 8`.)
|
||||
|
||||
標準ライブラリが使用されます (`libstdc++` または `libc++`).
|
||||
標準ライブラリが使用されます (`libc++`).
|
||||
|
||||
**4.**OS:LinuxのUbuntuの、正確よりも古いではありません。
|
||||
|
||||
|
@ -21,7 +21,7 @@ mkdocs-htmlproofer-plugin==0.0.3
|
||||
mkdocs-macros-plugin==0.4.9
|
||||
nltk==3.5
|
||||
nose==1.3.7
|
||||
protobuf==3.12.4
|
||||
protobuf==3.13.0
|
||||
numpy==1.19.1
|
||||
Pygments==2.5.2
|
||||
pymdown-extensions==8.0
|
||||
|
@ -705,7 +705,7 @@ Ama diğer şeyler eşit olmak, çapraz platform veya taşınabilir kod tercih e
|
||||
|
||||
**3.** Derleyici: `gcc`. Şu anda (Ağustos 2020), kod sürüm 9.3 kullanılarak derlenmiştir. (Ayrıca kullanılarak derlenebilir `clang 8`.)
|
||||
|
||||
Standart kütüphane kullanılır (`libstdc++` veya `libc++`).
|
||||
Standart kütüphane kullanılır (`libc++`).
|
||||
|
||||
**4.**OS: Linux UB .untu, daha eski değil.
|
||||
|
||||
|
@ -176,7 +176,7 @@ Ana ClickHouse kodu (bu `dbms` dizin) ile inşa edilmiştir `-Wall -Wextra -Werr
|
||||
|
||||
Clang daha yararlı uyarılar vardır-Sen ile onları arayabilirsiniz `-Weverything` ve varsayılan oluşturmak için bir şey seçin.
|
||||
|
||||
Üretim yapıları için gcc kullanılır (hala clang'dan biraz daha verimli kod üretir). Geliştirme için, clang genellikle kullanımı daha uygundur. Hata ayıklama modu ile kendi makinenizde inşa edebilirsiniz (dizüstü bilgisayarınızın pilinden tasarruf etmek için), ancak derleyicinin daha fazla uyarı üretebileceğini lütfen unutmayın `-O3` daha iyi kontrol akışı ve prosedürler arası analiz nedeniyle. Clang ile inşa ederken, `libc++` yerine kullanılır `libstdc++` ve hata ayıklama modu ile oluştururken, hata ayıklama sürümü `libc++` çalışma zamanında daha fazla hata yakalamak için izin verir kullanılır.
|
||||
Üretim yapıları için gcc kullanılır (hala clang'dan biraz daha verimli kod üretir). Geliştirme için, clang genellikle kullanımı daha uygundur. Hata ayıklama modu ile kendi makinenizde inşa edebilirsiniz (dizüstü bilgisayarınızın pilinden tasarruf etmek için), ancak derleyicinin daha fazla uyarı üretebileceğini lütfen unutmayın `-O3` daha iyi kontrol akışı ve prosedürler arası analiz nedeniyle. Clang ile inşa ederken ayıklama modu ile oluştururken, hata ayıklama sürümü `libc++` çalışma zamanında daha fazla hata yakalamak için izin verir kullanılır.
|
||||
|
||||
## Dezenfektanlar {#sanitizers}
|
||||
|
||||
|
@ -698,7 +698,7 @@ auto s = std::string{"Hello"};
|
||||
|
||||
**3.** 编译器: `gcc`。 此时(2020年08月),代码使用9.3版编译。(它也可以使用`clang 8` 编译)
|
||||
|
||||
使用标准库 (`libstdc++` 或 `libc++`)。
|
||||
使用标准库 (`libc++`)。
|
||||
|
||||
**4.** 操作系统:Linux Ubuntu,不比 Precise 早。
|
||||
|
||||
|
@ -511,13 +511,14 @@ void UsersConfigAccessStorage::parseFromConfig(const Poco::Util::AbstractConfigu
|
||||
memory_storage.setAll(all_entities);
|
||||
}
|
||||
|
||||
void UsersConfigAccessStorage::load(const String & users_config_path,
|
||||
const String & include_from_path,
|
||||
const String & preprocessed_dir,
|
||||
const zkutil::GetZooKeeper & get_zookeeper_function)
|
||||
void UsersConfigAccessStorage::load(
|
||||
const String & users_config_path,
|
||||
const String & include_from_path,
|
||||
const String & preprocessed_dir,
|
||||
const zkutil::GetZooKeeper & get_zookeeper_function)
|
||||
{
|
||||
std::lock_guard lock{load_mutex};
|
||||
path = std::filesystem::canonical(users_config_path);
|
||||
path = std::filesystem::path{users_config_path}.lexically_normal();
|
||||
config_reloader.reset();
|
||||
config_reloader = std::make_unique<ConfigReloader>(
|
||||
users_config_path,
|
||||
|
@ -17,7 +17,10 @@ namespace
|
||||
template <typename T>
|
||||
struct Avg
|
||||
{
|
||||
using FieldType = std::conditional_t<IsDecimalNumber<T>, Decimal128, NearestFieldType<T>>;
|
||||
using FieldType = std::conditional_t<IsDecimalNumber<T>,
|
||||
std::conditional_t<std::is_same_v<T, Decimal256>, Decimal256, Decimal128>,
|
||||
NearestFieldType<T>>;
|
||||
// using FieldType = std::conditional_t<IsDecimalNumber<T>, Decimal128, NearestFieldType<T>>;
|
||||
using Function = AggregateFunctionAvg<T, AggregateFunctionAvgData<FieldType, UInt64>>;
|
||||
};
|
||||
|
||||
|
@ -22,19 +22,28 @@ struct AggregateFunctionAvgData
|
||||
using NumeratorType = T;
|
||||
using DenominatorType = Denominator;
|
||||
|
||||
T numerator = 0;
|
||||
Denominator denominator = 0;
|
||||
T numerator{0};
|
||||
Denominator denominator{0};
|
||||
|
||||
template <typename ResultT>
|
||||
ResultT NO_SANITIZE_UNDEFINED result() const
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<ResultT>)
|
||||
if constexpr (std::numeric_limits<ResultT>::is_iec559)
|
||||
return static_cast<ResultT>(numerator) / denominator; /// allow division by zero
|
||||
{
|
||||
if constexpr (is_big_int_v<Denominator>)
|
||||
return static_cast<ResultT>(numerator) / static_cast<ResultT>(denominator);
|
||||
else
|
||||
return static_cast<ResultT>(numerator) / denominator; /// allow division by zero
|
||||
}
|
||||
|
||||
if (denominator == 0)
|
||||
if (denominator == static_cast<Denominator>(0))
|
||||
return static_cast<ResultT>(0);
|
||||
return static_cast<ResultT>(numerator / denominator);
|
||||
|
||||
if constexpr (std::is_same_v<T, Decimal256>)
|
||||
return static_cast<ResultT>(numerator / static_cast<T>(denominator));
|
||||
else
|
||||
return static_cast<ResultT>(numerator / denominator);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -17,7 +17,10 @@ namespace
|
||||
template <typename T>
|
||||
struct AvgWeighted
|
||||
{
|
||||
using FieldType = std::conditional_t<IsDecimalNumber<T>, Decimal128, NearestFieldType<T>>;
|
||||
using FieldType = std::conditional_t<IsDecimalNumber<T>,
|
||||
std::conditional_t<std::is_same_v<T, Decimal256>, Decimal256, Decimal128>,
|
||||
NearestFieldType<T>>;
|
||||
// using FieldType = std::conditional_t<IsDecimalNumber<T>, Decimal128, NearestFieldType<T>>;
|
||||
using Function = AggregateFunctionAvgWeighted<T, AggregateFunctionAvgData<FieldType, FieldType>>;
|
||||
};
|
||||
|
||||
|
@ -295,7 +295,12 @@ public:
|
||||
if (size)
|
||||
{
|
||||
typename ColumnVector<T>::Container & data_to = assert_cast<ColumnVector<T> &>(arr_to.getData()).getData();
|
||||
data_to.insert(this->data(place).value.begin(), this->data(place).value.end());
|
||||
if constexpr (is_big_int_v<T>)
|
||||
// is data_to empty? we should probaly use std::vector::insert then
|
||||
for (auto it = this->data(place).value.begin(); it != this->data(place).value.end(); it++)
|
||||
data_to.push_back(*it);
|
||||
else
|
||||
data_to.insert(this->data(place).value.begin(), this->data(place).value.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,12 +37,12 @@ struct MovingAvg
|
||||
template <typename T, typename LimitNumberOfElements> using MovingSumTemplate = typename MovingSum<T, LimitNumberOfElements>::Function;
|
||||
template <typename T, typename LimitNumberOfElements> using MovingAvgTemplate = typename MovingAvg<T, LimitNumberOfElements>::Function;
|
||||
|
||||
template <template <typename, typename> class Function, typename HasLimit, typename ... TArgs>
|
||||
template <template <typename, typename> class Function, typename HasLimit, typename DecimalArg, typename ... TArgs>
|
||||
inline AggregateFunctionPtr createAggregateFunctionMovingImpl(const std::string & name, const DataTypePtr & argument_type, TArgs ... args)
|
||||
{
|
||||
AggregateFunctionPtr res;
|
||||
|
||||
if (isDecimal(argument_type))
|
||||
if constexpr (DecimalArg::value)
|
||||
res.reset(createWithDecimalType<Function, HasLimit>(*argument_type, argument_type, std::forward<TArgs>(args)...));
|
||||
else
|
||||
res.reset(createWithNumericType<Function, HasLimit>(*argument_type, argument_type, std::forward<TArgs>(args)...));
|
||||
@ -84,10 +84,21 @@ AggregateFunctionPtr createAggregateFunctionMoving(const std::string & name, con
|
||||
throw Exception("Incorrect number of parameters for aggregate function " + name + ", should be 0 or 1",
|
||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
||||
|
||||
const DataTypePtr & argument_type = argument_types[0];
|
||||
if (!limit_size)
|
||||
return createAggregateFunctionMovingImpl<Function, std::false_type>(name, argument_types[0]);
|
||||
{
|
||||
if (isDecimal(argument_type))
|
||||
return createAggregateFunctionMovingImpl<Function, std::false_type, std::true_type>(name, argument_type);
|
||||
else
|
||||
return createAggregateFunctionMovingImpl<Function, std::false_type, std::false_type>(name, argument_type);
|
||||
}
|
||||
else
|
||||
return createAggregateFunctionMovingImpl<Function, std::true_type>(name, argument_types[0], max_elems);
|
||||
{
|
||||
if (isDecimal(argument_type))
|
||||
return createAggregateFunctionMovingImpl<Function, std::true_type, std::true_type>(name, argument_type, max_elems);
|
||||
else
|
||||
return createAggregateFunctionMovingImpl<Function, std::true_type, std::false_type>(name, argument_type, max_elems);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ public:
|
||||
void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena * arena) const override
|
||||
{
|
||||
auto value = static_cast<const ColumnSource &>(*columns[0]).getData()[row_num];
|
||||
this->data(place).add(value, arena);
|
||||
this->data(place).add(static_cast<ResultT>(value), arena);
|
||||
}
|
||||
|
||||
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena * arena) const override
|
||||
|
@ -59,6 +59,16 @@ static constexpr bool supportDecimal()
|
||||
std::is_same_v<Function<Float32, false>, FuncQuantilesExactWeighted<Float32, false>>;
|
||||
}
|
||||
|
||||
template <template <typename, bool> class Function>
|
||||
static constexpr bool supportBigInt()
|
||||
{
|
||||
return std::is_same_v<Function<Float32, false>, FuncQuantile<Float32, false>> ||
|
||||
std::is_same_v<Function<Float32, false>, FuncQuantiles<Float32, false>> ||
|
||||
std::is_same_v<Function<Float32, false>, FuncQuantileExact<Float32, false>> ||
|
||||
std::is_same_v<Function<Float32, false>, FuncQuantilesExact<Float32, false>> ||
|
||||
std::is_same_v<Function<Float32, false>, FuncQuantileExactWeighted<Float32, false>> ||
|
||||
std::is_same_v<Function<Float32, false>, FuncQuantilesExactWeighted<Float32, false>>;
|
||||
}
|
||||
|
||||
template <template <typename, bool> class Function>
|
||||
AggregateFunctionPtr createAggregateFunctionQuantile(const std::string & name, const DataTypes & argument_types, const Array & params)
|
||||
@ -71,7 +81,7 @@ AggregateFunctionPtr createAggregateFunctionQuantile(const std::string & name, c
|
||||
|
||||
#define DISPATCH(TYPE) \
|
||||
if (which.idx == TypeIndex::TYPE) return std::make_shared<Function<TYPE, true>>(argument_types, params);
|
||||
FOR_NUMERIC_TYPES(DISPATCH)
|
||||
FOR_BASIC_NUMERIC_TYPES(DISPATCH)
|
||||
#undef DISPATCH
|
||||
if (which.idx == TypeIndex::Date) return std::make_shared<Function<DataTypeDate::FieldType, false>>(argument_types, params);
|
||||
if (which.idx == TypeIndex::DateTime) return std::make_shared<Function<DataTypeDateTime::FieldType, false>>(argument_types, params);
|
||||
@ -81,6 +91,14 @@ AggregateFunctionPtr createAggregateFunctionQuantile(const std::string & name, c
|
||||
if (which.idx == TypeIndex::Decimal32) return std::make_shared<Function<Decimal32, false>>(argument_types, params);
|
||||
if (which.idx == TypeIndex::Decimal64) return std::make_shared<Function<Decimal64, false>>(argument_types, params);
|
||||
if (which.idx == TypeIndex::Decimal128) return std::make_shared<Function<Decimal128, false>>(argument_types, params);
|
||||
//if (which.idx == TypeIndex::Decimal256) return std::make_shared<Function<Decimal256, false>>(argument_types, params);
|
||||
}
|
||||
|
||||
if constexpr (supportBigInt<Function>())
|
||||
{
|
||||
if (which.idx == TypeIndex::Int128) return std::make_shared<Function<Int128, true>>(argument_types, params);
|
||||
if (which.idx == TypeIndex::bInt256) return std::make_shared<Function<bInt256, true>>(argument_types, params);
|
||||
if (which.idx == TypeIndex::bUInt256) return std::make_shared<Function<bUInt256, true>>(argument_types, params);
|
||||
}
|
||||
|
||||
throw Exception("Illegal type " + argument_type->getName() + " of argument for aggregate function " + name,
|
||||
|
@ -433,11 +433,20 @@ public:
|
||||
{
|
||||
if constexpr (StatFunc::num_args == 2)
|
||||
this->data(place).add(
|
||||
static_cast<const ColVecT1 &>(*columns[0]).getData()[row_num],
|
||||
static_cast<const ColVecT2 &>(*columns[1]).getData()[row_num]);
|
||||
static_cast<ResultType>(static_cast<const ColVecT1 &>(*columns[0]).getData()[row_num]),
|
||||
static_cast<ResultType>(static_cast<const ColVecT2 &>(*columns[1]).getData()[row_num]));
|
||||
else
|
||||
this->data(place).add(
|
||||
static_cast<const ColVecT1 &>(*columns[0]).getData()[row_num]);
|
||||
{
|
||||
if constexpr (std::is_same_v<T1, Decimal256>)
|
||||
{
|
||||
this->data(place).add(static_cast<ResultType>(
|
||||
static_cast<const ColVecT1 &>(*columns[0]).getData()[row_num].value
|
||||
));
|
||||
}
|
||||
else
|
||||
this->data(place).add(
|
||||
static_cast<ResultType>(static_cast<const ColVecT1 &>(*columns[0]).getData()[row_num]));
|
||||
}
|
||||
}
|
||||
|
||||
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
|
||||
|
@ -19,7 +19,10 @@ template <typename T>
|
||||
struct SumSimple
|
||||
{
|
||||
/// @note It uses slow Decimal128 (cause we need such a variant). sumWithOverflow is faster for Decimal32/64
|
||||
using ResultType = std::conditional_t<IsDecimalNumber<T>, Decimal128, NearestFieldType<T>>;
|
||||
using ResultType = std::conditional_t<IsDecimalNumber<T>,
|
||||
std::conditional_t<std::is_same_v<T, Decimal256>, Decimal256, Decimal128>,
|
||||
NearestFieldType<T>>;
|
||||
// using ResultType = std::conditional_t<IsDecimalNumber<T>, Decimal128, NearestFieldType<T>>;
|
||||
using AggregateDataType = AggregateFunctionSumData<ResultType>;
|
||||
using Function = AggregateFunctionSum<T, ResultType, AggregateDataType, AggregateFunctionTypeSum>;
|
||||
};
|
||||
|
@ -119,7 +119,7 @@ struct AggregateFunctionSumKahanData
|
||||
template <typename Value>
|
||||
void ALWAYS_INLINE addImpl(Value value, T & out_sum, T & out_compensation)
|
||||
{
|
||||
auto compensated_value = value - out_compensation;
|
||||
auto compensated_value = static_cast<T>(value) - out_compensation;
|
||||
auto new_sum = out_sum + compensated_value;
|
||||
out_compensation = (new_sum - out_sum) - compensated_value;
|
||||
out_sum = new_sum;
|
||||
@ -273,7 +273,10 @@ public:
|
||||
void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena *) const override
|
||||
{
|
||||
const auto & column = static_cast<const ColVecType &>(*columns[0]);
|
||||
this->data(place).add(column.getData()[row_num]);
|
||||
if constexpr (is_big_int_v<T>)
|
||||
this->data(place).add(static_cast<TResult>(column.getData()[row_num]));
|
||||
else
|
||||
this->data(place).add(column.getData()[row_num]);
|
||||
}
|
||||
|
||||
/// Vectorized version when there is no GROUP BY keys.
|
||||
|
@ -348,7 +348,11 @@ private:
|
||||
using Self = AggregateFunctionSumMapFiltered<T, overflow, tuple_argument>;
|
||||
using Base = AggregateFunctionMapBase<T, Self, FieldVisitorSum, overflow, tuple_argument>;
|
||||
|
||||
std::unordered_set<T> keys_to_keep;
|
||||
/// ARCADIA_BUILD disallow unordered_set for big ints for some reason
|
||||
static constexpr const bool allow_hash = !OverBigInt<T>;
|
||||
using ContainerT = std::conditional_t<allow_hash, std::unordered_set<T>, std::set<T>>;
|
||||
|
||||
ContainerT keys_to_keep;
|
||||
|
||||
public:
|
||||
AggregateFunctionSumMapFiltered(const DataTypePtr & keys_type_,
|
||||
@ -367,7 +371,9 @@ public:
|
||||
"Aggregate function {} requires an Array as a parameter",
|
||||
getName());
|
||||
|
||||
keys_to_keep.reserve(keys_to_keep_.size());
|
||||
if constexpr (allow_hash)
|
||||
keys_to_keep.reserve(keys_to_keep_.size());
|
||||
|
||||
for (const Field & f : keys_to_keep_)
|
||||
{
|
||||
keys_to_keep.emplace(f.safeGet<NearestFieldType<T>>());
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <Interpreters/AggregationCommon.h>
|
||||
|
||||
#include <Common/HashTable/Hash.h>
|
||||
#include <Common/HashTable/HashSet.h>
|
||||
#include <Common/HyperLogLogWithSmallSetOptimization.h>
|
||||
#include <Common/CombinedCardinalityEstimator.h>
|
||||
@ -130,30 +131,20 @@ namespace detail
|
||||
*/
|
||||
template <typename T> struct AggregateFunctionUniqTraits
|
||||
{
|
||||
static UInt64 hash(T x) { return x; }
|
||||
};
|
||||
|
||||
template <> struct AggregateFunctionUniqTraits<UInt128>
|
||||
{
|
||||
static UInt64 hash(UInt128 x)
|
||||
static UInt64 hash(T x)
|
||||
{
|
||||
return sipHash64(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct AggregateFunctionUniqTraits<Float32>
|
||||
{
|
||||
static UInt64 hash(Float32 x)
|
||||
{
|
||||
return ext::bit_cast<UInt64>(x);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct AggregateFunctionUniqTraits<Float64>
|
||||
{
|
||||
static UInt64 hash(Float64 x)
|
||||
{
|
||||
return ext::bit_cast<UInt64>(x);
|
||||
if constexpr (std::is_same_v<T, UInt128>)
|
||||
{
|
||||
return sipHash64(x);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, Float32> || std::is_same_v<T, Float64>)
|
||||
{
|
||||
return ext::bit_cast<UInt64>(x);
|
||||
}
|
||||
else if constexpr (sizeof(T) <= sizeof(UInt64))
|
||||
return x;
|
||||
else
|
||||
return DefaultHash64<T>(x);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -31,7 +31,10 @@ namespace detail
|
||||
{
|
||||
static Ret hash(T x)
|
||||
{
|
||||
return static_cast<Ret>(intHash64(x));
|
||||
if constexpr (sizeof(T) > sizeof(UInt64))
|
||||
return static_cast<Ret>(DefaultHash64<T>(x));
|
||||
else
|
||||
return static_cast<Ret>(intHash64(x));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -43,10 +43,8 @@ struct __attribute__((__packed__)) AggregateFunctionUniqUpToData
|
||||
* then set count to `threshold + 1`, and values from another state are not copied.
|
||||
*/
|
||||
UInt8 count = 0;
|
||||
|
||||
T data[0];
|
||||
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
return count;
|
||||
@ -138,6 +136,28 @@ struct AggregateFunctionUniqUpToData<UInt128> : AggregateFunctionUniqUpToData<UI
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct AggregateFunctionUniqUpToData<bUInt256> : AggregateFunctionUniqUpToData<UInt64>
|
||||
{
|
||||
/// ALWAYS_INLINE is required to have better code layout for uniqUpTo function
|
||||
void ALWAYS_INLINE add(const IColumn & column, size_t row_num, UInt8 threshold)
|
||||
{
|
||||
bUInt256 value = assert_cast<const ColumnVector<bUInt256> &>(column).getData()[row_num];
|
||||
insert(sipHash64(value), threshold);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct AggregateFunctionUniqUpToData<bInt256> : AggregateFunctionUniqUpToData<UInt64>
|
||||
{
|
||||
/// ALWAYS_INLINE is required to have better code layout for uniqUpTo function
|
||||
void ALWAYS_INLINE add(const IColumn & column, size_t row_num, UInt8 threshold)
|
||||
{
|
||||
bInt256 value = assert_cast<const ColumnVector<bInt256> &>(column).getData()[row_num];
|
||||
insert(sipHash64(value), threshold);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class AggregateFunctionUniqUpTo final : public IAggregateFunctionDataHelper<AggregateFunctionUniqUpToData<T>, AggregateFunctionUniqUpTo<T>>
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include <DataTypes/IDataType.h>
|
||||
#include <AggregateFunctions/IAggregateFunction.h>
|
||||
|
||||
#define FOR_NUMERIC_TYPES(M) \
|
||||
#define FOR_BASIC_NUMERIC_TYPES(M) \
|
||||
M(UInt8) \
|
||||
M(UInt16) \
|
||||
M(UInt32) \
|
||||
@ -15,6 +15,21 @@
|
||||
M(Float32) \
|
||||
M(Float64)
|
||||
|
||||
#define FOR_NUMERIC_TYPES(M) \
|
||||
M(UInt8) \
|
||||
M(UInt16) \
|
||||
M(UInt32) \
|
||||
M(UInt64) \
|
||||
M(bUInt256) \
|
||||
M(Int8) \
|
||||
M(Int16) \
|
||||
M(Int32) \
|
||||
M(Int64) \
|
||||
M(Int128) \
|
||||
M(bInt256) \
|
||||
M(Float32) \
|
||||
M(Float64)
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
@ -118,6 +133,7 @@ static IAggregateFunction * createWithDecimalType(const IDataType & argument_typ
|
||||
if (which.idx == TypeIndex::Decimal32) return new AggregateFunctionTemplate<Decimal32>(std::forward<TArgs>(args)...);
|
||||
if (which.idx == TypeIndex::Decimal64) return new AggregateFunctionTemplate<Decimal64>(std::forward<TArgs>(args)...);
|
||||
if (which.idx == TypeIndex::Decimal128) return new AggregateFunctionTemplate<Decimal128>(std::forward<TArgs>(args)...);
|
||||
if (which.idx == TypeIndex::Decimal256) return new AggregateFunctionTemplate<Decimal256>(std::forward<TArgs>(args)...);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -128,6 +144,7 @@ static IAggregateFunction * createWithDecimalType(const IDataType & argument_typ
|
||||
if (which.idx == TypeIndex::Decimal32) return new AggregateFunctionTemplate<Decimal32, Data>(std::forward<TArgs>(args)...);
|
||||
if (which.idx == TypeIndex::Decimal64) return new AggregateFunctionTemplate<Decimal64, Data>(std::forward<TArgs>(args)...);
|
||||
if (which.idx == TypeIndex::Decimal128) return new AggregateFunctionTemplate<Decimal128, Data>(std::forward<TArgs>(args)...);
|
||||
if (which.idx == TypeIndex::Decimal256) return new AggregateFunctionTemplate<Decimal256, Data>(std::forward<TArgs>(args)...);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -127,14 +127,14 @@ struct QuantileExactExclusive : public QuantileExact<Value>
|
||||
auto n = static_cast<size_t>(h);
|
||||
|
||||
if (n >= array.size())
|
||||
return array[array.size() - 1];
|
||||
return static_cast<Float64>(array[array.size() - 1]);
|
||||
else if (n < 1)
|
||||
return array[0];
|
||||
return static_cast<Float64>(array[0]);
|
||||
|
||||
std::nth_element(array.begin(), array.begin() + n - 1, array.end());
|
||||
auto nth_element = std::min_element(array.begin() + n, array.end());
|
||||
|
||||
return array[n - 1] + (h - n) * (*nth_element - array[n - 1]);
|
||||
return static_cast<Float64>(array[n - 1]) + (h - n) * static_cast<Float64>(*nth_element - array[n - 1]);
|
||||
}
|
||||
|
||||
return std::numeric_limits<Float64>::quiet_NaN();
|
||||
@ -155,15 +155,15 @@ struct QuantileExactExclusive : public QuantileExact<Value>
|
||||
auto n = static_cast<size_t>(h);
|
||||
|
||||
if (n >= array.size())
|
||||
result[indices[i]] = array[array.size() - 1];
|
||||
result[indices[i]] = static_cast<Float64>(array[array.size() - 1]);
|
||||
else if (n < 1)
|
||||
result[indices[i]] = array[0];
|
||||
result[indices[i]] = static_cast<Float64>(array[0]);
|
||||
else
|
||||
{
|
||||
std::nth_element(array.begin() + prev_n, array.begin() + n - 1, array.end());
|
||||
auto nth_element = std::min_element(array.begin() + n, array.end());
|
||||
|
||||
result[indices[i]] = array[n - 1] + (h - n) * (*nth_element - array[n - 1]);
|
||||
result[indices[i]] = static_cast<Float64>(array[n - 1]) + (h - n) * static_cast<Float64>(*nth_element - array[n - 1]);
|
||||
prev_n = n - 1;
|
||||
}
|
||||
}
|
||||
@ -191,14 +191,14 @@ struct QuantileExactInclusive : public QuantileExact<Value>
|
||||
auto n = static_cast<size_t>(h);
|
||||
|
||||
if (n >= array.size())
|
||||
return array[array.size() - 1];
|
||||
return static_cast<Float64>(array[array.size() - 1]);
|
||||
else if (n < 1)
|
||||
return array[0];
|
||||
return static_cast<Float64>(array[0]);
|
||||
|
||||
std::nth_element(array.begin(), array.begin() + n - 1, array.end());
|
||||
auto nth_element = std::min_element(array.begin() + n, array.end());
|
||||
|
||||
return array[n - 1] + (h - n) * (*nth_element - array[n - 1]);
|
||||
return static_cast<Float64>(array[n - 1]) + (h - n) * static_cast<Float64>(*nth_element - array[n - 1]);
|
||||
}
|
||||
|
||||
return std::numeric_limits<Float64>::quiet_NaN();
|
||||
@ -217,15 +217,15 @@ struct QuantileExactInclusive : public QuantileExact<Value>
|
||||
auto n = static_cast<size_t>(h);
|
||||
|
||||
if (n >= array.size())
|
||||
result[indices[i]] = array[array.size() - 1];
|
||||
result[indices[i]] = static_cast<Float64>(array[array.size() - 1]);
|
||||
else if (n < 1)
|
||||
result[indices[i]] = array[0];
|
||||
result[indices[i]] = static_cast<Float64>(array[0]);
|
||||
else
|
||||
{
|
||||
std::nth_element(array.begin() + prev_n, array.begin() + n - 1, array.end());
|
||||
auto nth_element = std::min_element(array.begin() + n, array.end());
|
||||
|
||||
result[indices[i]] = array[n - 1] + (h - n) * (*nth_element - array[n - 1]);
|
||||
result[indices[i]] = static_cast<Float64>(array[n - 1]) + (h - n) * static_cast<Float64>(*nth_element - array[n - 1]);
|
||||
prev_n = n - 1;
|
||||
}
|
||||
}
|
||||
|
@ -129,12 +129,12 @@ public:
|
||||
size_t left_index = static_cast<size_t>(index);
|
||||
size_t right_index = left_index + 1;
|
||||
if (right_index == samples.size())
|
||||
return samples[left_index];
|
||||
return static_cast<double>(samples[left_index]);
|
||||
|
||||
double left_coef = right_index - index;
|
||||
double right_coef = index - left_index;
|
||||
|
||||
return samples[left_index] * left_coef + samples[right_index] * right_coef;
|
||||
return static_cast<double>(samples[left_index]) * left_coef + static_cast<double>(samples[right_index]) * right_coef;
|
||||
}
|
||||
|
||||
void merge(const ReservoirSampler<T, OnEmpty> & b)
|
||||
|
@ -121,12 +121,12 @@ public:
|
||||
size_t left_index = static_cast<size_t>(index);
|
||||
size_t right_index = left_index + 1;
|
||||
if (right_index == samples.size())
|
||||
return samples[left_index].first;
|
||||
return static_cast<double>(samples[left_index].first);
|
||||
|
||||
const double left_coef = right_index - index;
|
||||
const double right_coef = index - left_index;
|
||||
|
||||
return samples[left_index].first * left_coef + samples[right_index].first * right_coef;
|
||||
return static_cast<double>(samples[left_index].first) * left_coef + static_cast<double>(samples[right_index].first) * right_coef;
|
||||
}
|
||||
|
||||
void merge(const ReservoirSamplerDeterministic & b)
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <Common/assert_cast.h>
|
||||
#include <Common/WeakHash.h>
|
||||
#include <Common/HashTable/Hash.h>
|
||||
#include <Core/BigInt.h>
|
||||
|
||||
#include <common/unaligned.h>
|
||||
|
||||
@ -51,30 +52,47 @@ void ColumnDecimal<T>::compareColumn(const IColumn & rhs, size_t rhs_row_num,
|
||||
template <typename T>
|
||||
StringRef ColumnDecimal<T>::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
|
||||
{
|
||||
auto * pos = arena.allocContinue(sizeof(T), begin);
|
||||
memcpy(pos, &data[n], sizeof(T));
|
||||
return StringRef(pos, sizeof(T));
|
||||
if constexpr (is_POD)
|
||||
{
|
||||
auto * pos = arena.allocContinue(sizeof(T), begin);
|
||||
memcpy(pos, &data[n], sizeof(T));
|
||||
return StringRef(pos, sizeof(T));
|
||||
}
|
||||
else
|
||||
{
|
||||
char * pos = arena.allocContinue(BigInt<T>::size, begin);
|
||||
return BigInt<bInt256>::serialize(data[n], pos);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const char * ColumnDecimal<T>::deserializeAndInsertFromArena(const char * pos)
|
||||
{
|
||||
data.push_back(unalignedLoad<T>(pos));
|
||||
return pos + sizeof(T);
|
||||
if constexpr (is_POD)
|
||||
{
|
||||
data.push_back(unalignedLoad<T>(pos));
|
||||
return pos + sizeof(T);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.push_back(BigInt<bInt256>::deserialize(pos));
|
||||
return pos + BigInt<bInt256>::size;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
UInt64 ColumnDecimal<T>::get64(size_t n) const
|
||||
UInt64 ColumnDecimal<T>::get64([[maybe_unused]] size_t n) const
|
||||
{
|
||||
if constexpr (sizeof(T) > sizeof(UInt64))
|
||||
throw Exception(String("Method get64 is not supported for ") + getFamilyName(), ErrorCodes::NOT_IMPLEMENTED);
|
||||
return static_cast<typename T::NativeType>(data[n]);
|
||||
else
|
||||
return static_cast<NativeT>(data[n]);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ColumnDecimal<T>::updateHashWithValue(size_t n, SipHash & hash) const
|
||||
{
|
||||
hash.update(data[n]);
|
||||
hash.update(data[n].value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -220,12 +238,24 @@ MutableColumnPtr ColumnDecimal<T>::cloneResized(size_t size) const
|
||||
new_col.data.resize(size);
|
||||
|
||||
size_t count = std::min(this->size(), size);
|
||||
memcpy(new_col.data.data(), data.data(), count * sizeof(data[0]));
|
||||
|
||||
if (size > count)
|
||||
if constexpr (is_POD)
|
||||
{
|
||||
void * tail = &new_col.data[count];
|
||||
memset(tail, 0, (size - count) * sizeof(T));
|
||||
memcpy(new_col.data.data(), data.data(), count * sizeof(data[0]));
|
||||
|
||||
if (size > count)
|
||||
{
|
||||
void * tail = &new_col.data[count];
|
||||
memset(tail, 0, (size - count) * sizeof(T));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
new_col.data[i] = data[i];
|
||||
|
||||
if (size > count)
|
||||
for (size_t i = count; i < size; i++)
|
||||
new_col.data[i] = T{};
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,9 +265,16 @@ MutableColumnPtr ColumnDecimal<T>::cloneResized(size_t size) const
|
||||
template <typename T>
|
||||
void ColumnDecimal<T>::insertData(const char * src, size_t /*length*/)
|
||||
{
|
||||
T tmp;
|
||||
memcpy(&tmp, src, sizeof(T));
|
||||
data.emplace_back(tmp);
|
||||
if constexpr (is_POD)
|
||||
{
|
||||
T tmp;
|
||||
memcpy(&tmp, src, sizeof(T));
|
||||
data.emplace_back(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.push_back(BigInt<bInt256>::deserialize(src));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -252,7 +289,13 @@ void ColumnDecimal<T>::insertRangeFrom(const IColumn & src, size_t start, size_t
|
||||
|
||||
size_t old_size = data.size();
|
||||
data.resize(old_size + length);
|
||||
memcpy(data.data() + old_size, &src_vec.data[start], length * sizeof(data[0]));
|
||||
if constexpr (is_POD)
|
||||
memcpy(data.data() + old_size, &src_vec.data[start], length * sizeof(data[0]));
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < length; i++)
|
||||
data[old_size + i] = src_vec.data[start + i];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -328,8 +371,8 @@ void ColumnDecimal<T>::getExtremes(Field & min, Field & max) const
|
||||
{
|
||||
if (data.empty())
|
||||
{
|
||||
min = NearestFieldType<T>(0, scale);
|
||||
max = NearestFieldType<T>(0, scale);
|
||||
min = NearestFieldType<T>(T(0), scale);
|
||||
max = NearestFieldType<T>(T(0), scale);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -351,4 +394,5 @@ void ColumnDecimal<T>::getExtremes(Field & min, Field & max) const
|
||||
template class ColumnDecimal<Decimal32>;
|
||||
template class ColumnDecimal<Decimal64>;
|
||||
template class ColumnDecimal<Decimal128>;
|
||||
template class ColumnDecimal<Decimal256>;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ namespace DB
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/// PaddedPODArray extended by Decimal scale
|
||||
@ -53,6 +54,42 @@ private:
|
||||
UInt32 scale;
|
||||
};
|
||||
|
||||
/// std::vector extended by Decimal scale
|
||||
template <typename T>
|
||||
class DecimalVector : public std::vector<T>
|
||||
{
|
||||
public:
|
||||
using Base = std::vector<T>;
|
||||
using Base::operator[];
|
||||
|
||||
DecimalVector(size_t size, UInt32 scale_)
|
||||
: Base(size),
|
||||
scale(scale_)
|
||||
{}
|
||||
|
||||
DecimalVector(const DecimalVector & other)
|
||||
: Base(other.begin(), other.end()),
|
||||
scale(other.scale)
|
||||
{}
|
||||
|
||||
DecimalVector(DecimalVector && other)
|
||||
{
|
||||
this->swap(other);
|
||||
std::swap(scale, other.scale);
|
||||
}
|
||||
|
||||
DecimalVector & operator=(DecimalVector && other)
|
||||
{
|
||||
this->swap(other);
|
||||
std::swap(scale, other.scale);
|
||||
return *this;
|
||||
}
|
||||
|
||||
UInt32 getScale() const { return scale; }
|
||||
|
||||
private:
|
||||
UInt32 scale;
|
||||
};
|
||||
|
||||
/// A ColumnVector for Decimals
|
||||
template <typename T>
|
||||
@ -66,7 +103,11 @@ private:
|
||||
|
||||
public:
|
||||
using ValueType = T;
|
||||
using Container = DecimalPaddedPODArray<T>;
|
||||
using NativeT = typename T::NativeType;
|
||||
static constexpr bool is_POD = !is_big_int_v<NativeT>;
|
||||
using Container = std::conditional_t<is_POD,
|
||||
DecimalPaddedPODArray<T>,
|
||||
DecimalVector<T>>;
|
||||
|
||||
private:
|
||||
ColumnDecimal(const size_t n, UInt32 scale_)
|
||||
@ -85,23 +126,61 @@ public:
|
||||
|
||||
bool isNumeric() const override { return false; }
|
||||
bool canBeInsideNullable() const override { return true; }
|
||||
bool isFixedAndContiguous() const override { return true; }
|
||||
bool isFixedAndContiguous() const override { return is_POD; }
|
||||
size_t sizeOfValueIfFixed() const override { return sizeof(T); }
|
||||
|
||||
size_t size() const override { return data.size(); }
|
||||
size_t byteSize() const override { return data.size() * sizeof(data[0]); }
|
||||
size_t allocatedBytes() const override { return data.allocated_bytes(); }
|
||||
void protect() override { data.protect(); }
|
||||
size_t allocatedBytes() const override
|
||||
{
|
||||
if constexpr (is_POD)
|
||||
return data.allocated_bytes();
|
||||
else
|
||||
return data.capacity() * sizeof(data[0]);
|
||||
}
|
||||
void protect() override
|
||||
{
|
||||
if constexpr (is_POD)
|
||||
data.protect();
|
||||
}
|
||||
void reserve(size_t n) override { data.reserve(n); }
|
||||
|
||||
void insertFrom(const IColumn & src, size_t n) override { data.push_back(static_cast<const Self &>(src).getData()[n]); }
|
||||
void insertData(const char * src, size_t /*length*/) override;
|
||||
void insertDefault() override { data.push_back(T()); }
|
||||
virtual void insertManyDefaults(size_t length) override { data.resize_fill(data.size() + length); }
|
||||
virtual void insertManyDefaults(size_t length) override
|
||||
{
|
||||
if constexpr (is_POD)
|
||||
data.resize_fill(data.size() + length);
|
||||
else
|
||||
data.resize(data.size() + length);
|
||||
}
|
||||
void insert(const Field & x) override { data.push_back(DB::get<NearestFieldType<T>>(x)); }
|
||||
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override;
|
||||
|
||||
void popBack(size_t n) override { data.resize_assume_reserved(data.size() - n); }
|
||||
void popBack(size_t n) override
|
||||
{
|
||||
if constexpr (is_POD)
|
||||
data.resize_assume_reserved(data.size() - n);
|
||||
else
|
||||
data.resize(data.size() - n);
|
||||
}
|
||||
|
||||
StringRef getRawData() const override
|
||||
{
|
||||
if constexpr (is_POD)
|
||||
return StringRef(reinterpret_cast<const char*>(data.data()), byteSize());
|
||||
else
|
||||
throw Exception("getRawData() is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
StringRef getDataAt(size_t n) const override
|
||||
{
|
||||
if constexpr (is_POD)
|
||||
return StringRef(reinterpret_cast<const char *>(&data[n]), sizeof(data[n]));
|
||||
else
|
||||
throw Exception("getDataAt() is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
StringRef serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const override;
|
||||
const char * deserializeAndInsertFromArena(const char * pos) override;
|
||||
@ -118,14 +197,11 @@ public:
|
||||
MutableColumnPtr cloneResized(size_t size) const override;
|
||||
|
||||
Field operator[](size_t n) const override { return DecimalField(data[n], scale); }
|
||||
|
||||
StringRef getRawData() const override { return StringRef(reinterpret_cast<const char*>(data.data()), byteSize()); }
|
||||
StringRef getDataAt(size_t n) const override { return StringRef(reinterpret_cast<const char *>(&data[n]), sizeof(data[n])); }
|
||||
void get(size_t n, Field & res) const override { res = (*this)[n]; }
|
||||
bool getBool(size_t n) const override { return bool(data[n]); }
|
||||
Int64 getInt(size_t n) const override { return Int64(data[n] * scale); }
|
||||
bool getBool(size_t n) const override { return bool(data[n].value); }
|
||||
Int64 getInt(size_t n) const override { return Int64(data[n].value * scale); }
|
||||
UInt64 get64(size_t n) const override;
|
||||
bool isDefaultAt(size_t n) const override { return data[n] == 0; }
|
||||
bool isDefaultAt(size_t n) const override { return data[n].value == 0; }
|
||||
|
||||
ColumnPtr filter(const IColumn::Filter & filt, ssize_t result_size_hint) const override;
|
||||
ColumnPtr permute(const IColumn::Permutation & perm, size_t limit) const override;
|
||||
|
@ -189,7 +189,7 @@ void ColumnFixedString::updatePermutation(bool reverse, size_t limit, int, Permu
|
||||
auto new_first = first;
|
||||
for (auto j = first + 1; j < last; ++j)
|
||||
{
|
||||
if (memcmpSmallAllowOverflow15(chars.data() + j * n, chars.data() + new_first * n, n) != 0)
|
||||
if (memcmpSmallAllowOverflow15(chars.data() + res[j] * n, chars.data() + res[new_first] * n, n) != 0)
|
||||
{
|
||||
if (j - new_first > 1)
|
||||
new_ranges.emplace_back(new_first, j);
|
||||
@ -210,7 +210,7 @@ void ColumnFixedString::updatePermutation(bool reverse, size_t limit, int, Permu
|
||||
auto new_first = first;
|
||||
for (auto j = first + 1; j < limit; ++j)
|
||||
{
|
||||
if (memcmpSmallAllowOverflow15(chars.data() + j * n, chars.data() + new_first * n, n) != 0)
|
||||
if (memcmpSmallAllowOverflow15(chars.data() + res[j] * n, chars.data() + res[new_first] * n, n) != 0)
|
||||
{
|
||||
if (j - new_first > 1)
|
||||
new_ranges.emplace_back(new_first, j);
|
||||
@ -221,7 +221,7 @@ void ColumnFixedString::updatePermutation(bool reverse, size_t limit, int, Permu
|
||||
auto new_last = limit;
|
||||
for (auto j = limit; j < last; ++j)
|
||||
{
|
||||
if (memcmpSmallAllowOverflow15(chars.data() + j * n, chars.data() + new_first * n, n) == 0)
|
||||
if (memcmpSmallAllowOverflow15(chars.data() + res[j] * n, chars.data() + res[new_first] * n, n) == 0)
|
||||
{
|
||||
std::swap(res[new_last], res[j]);
|
||||
++new_last;
|
||||
|
@ -42,20 +42,36 @@ namespace ErrorCodes
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
StringRef ColumnVector<T>::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
|
||||
{
|
||||
auto * pos = arena.allocContinue(sizeof(T), begin);
|
||||
unalignedStore<T>(pos, data[n]);
|
||||
return StringRef(pos, sizeof(T));
|
||||
if constexpr (is_big_int_v<T>)
|
||||
{
|
||||
static constexpr size_t bytesize = BigInt<T>::size;
|
||||
char * pos = arena.allocContinue(bytesize, begin);
|
||||
return BigInt<T>::serialize(data[n], pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto * pos = arena.allocContinue(sizeof(T), begin);
|
||||
unalignedStore<T>(pos, data[n]);
|
||||
return StringRef(pos, sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const char * ColumnVector<T>::deserializeAndInsertFromArena(const char * pos)
|
||||
{
|
||||
data.push_back(unalignedLoad<T>(pos));
|
||||
return pos + sizeof(T);
|
||||
if constexpr (is_big_int_v<T>)
|
||||
{
|
||||
data.emplace_back(BigInt<T>::deserialize(pos));
|
||||
return pos + BigInt<T>::size;
|
||||
}
|
||||
else
|
||||
{
|
||||
data.emplace_back(unalignedLoad<T>(pos));
|
||||
return pos + sizeof(T);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -305,10 +321,18 @@ MutableColumnPtr ColumnVector<T>::cloneResized(size_t size) const
|
||||
new_col.data.resize(size);
|
||||
|
||||
size_t count = std::min(this->size(), size);
|
||||
memcpy(new_col.data.data(), data.data(), count * sizeof(data[0]));
|
||||
if constexpr (is_POD)
|
||||
{
|
||||
memcpy(new_col.data.data(), data.data(), count * sizeof(data[0]));
|
||||
|
||||
if (size > count)
|
||||
memset(static_cast<void *>(&new_col.data[count]), static_cast<int>(ValueType()), (size - count) * sizeof(ValueType));
|
||||
if (size > count)
|
||||
memset(static_cast<void *>(&new_col.data[count]), static_cast<int>(ValueType()), (size - count) * sizeof(ValueType));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < count; i++)
|
||||
new_col.data[i] = data[i];
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -346,7 +370,15 @@ void ColumnVector<T>::insertRangeFrom(const IColumn & src, size_t start, size_t
|
||||
|
||||
size_t old_size = data.size();
|
||||
data.resize(old_size + length);
|
||||
memcpy(data.data() + old_size, &src_vec.data[start], length * sizeof(data[0]));
|
||||
if constexpr (is_POD)
|
||||
{
|
||||
memcpy(data.data() + old_size, &src_vec.data[start], length * sizeof(data[0]));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < length; i++)
|
||||
data[old_size + i] = src_vec.data[start + i];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -362,52 +394,70 @@ ColumnPtr ColumnVector<T>::filter(const IColumn::Filter & filt, ssize_t result_s
|
||||
if (result_size_hint)
|
||||
res_data.reserve(result_size_hint > 0 ? result_size_hint : size);
|
||||
|
||||
const UInt8 * filt_pos = filt.data();
|
||||
const UInt8 * filt_end = filt_pos + size;
|
||||
const T * data_pos = data.data();
|
||||
if constexpr (is_POD)
|
||||
{
|
||||
const UInt8 * filt_pos = filt.data();
|
||||
const UInt8 * filt_end = filt_pos + size;
|
||||
const T * data_pos = data.data();
|
||||
|
||||
#ifdef __SSE2__
|
||||
/** A slightly more optimized version.
|
||||
/** A slightly more optimized version.
|
||||
* Based on the assumption that often pieces of consecutive values
|
||||
* completely pass or do not pass the filter.
|
||||
* Therefore, we will optimistically check the parts of `SIMD_BYTES` values.
|
||||
*/
|
||||
|
||||
static constexpr size_t SIMD_BYTES = 16;
|
||||
const __m128i zero16 = _mm_setzero_si128();
|
||||
const UInt8 * filt_end_sse = filt_pos + size / SIMD_BYTES * SIMD_BYTES;
|
||||
static constexpr size_t SIMD_BYTES = 16;
|
||||
const __m128i zero16 = _mm_setzero_si128();
|
||||
const UInt8 * filt_end_sse = filt_pos + size / SIMD_BYTES * SIMD_BYTES;
|
||||
|
||||
while (filt_pos < filt_end_sse)
|
||||
{
|
||||
int mask = _mm_movemask_epi8(_mm_cmpgt_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i *>(filt_pos)), zero16));
|
||||
while (filt_pos < filt_end_sse)
|
||||
{
|
||||
int mask = _mm_movemask_epi8(_mm_cmpgt_epi8(_mm_loadu_si128(reinterpret_cast<const __m128i *>(filt_pos)), zero16));
|
||||
|
||||
if (0 == mask)
|
||||
{
|
||||
/// Nothing is inserted.
|
||||
}
|
||||
else if (0xFFFF == mask)
|
||||
{
|
||||
res_data.insert(data_pos, data_pos + SIMD_BYTES);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < SIMD_BYTES; ++i)
|
||||
if (filt_pos[i])
|
||||
res_data.push_back(data_pos[i]);
|
||||
}
|
||||
if (0 == mask)
|
||||
{
|
||||
/// Nothing is inserted.
|
||||
}
|
||||
else if (0xFFFF == mask)
|
||||
{
|
||||
res_data.insert(data_pos, data_pos + SIMD_BYTES);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < SIMD_BYTES; ++i)
|
||||
if (filt_pos[i])
|
||||
res_data.push_back(data_pos[i]);
|
||||
}
|
||||
|
||||
filt_pos += SIMD_BYTES;
|
||||
data_pos += SIMD_BYTES;
|
||||
}
|
||||
filt_pos += SIMD_BYTES;
|
||||
data_pos += SIMD_BYTES;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (filt_pos < filt_end)
|
||||
{
|
||||
if (*filt_pos)
|
||||
res_data.push_back(*data_pos);
|
||||
while (filt_pos < filt_end)
|
||||
{
|
||||
if (*filt_pos)
|
||||
res_data.push_back(*data_pos);
|
||||
|
||||
++filt_pos;
|
||||
++data_pos;
|
||||
++filt_pos;
|
||||
++data_pos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto * filt_pos = filt.begin();
|
||||
const auto * filt_end = filt.end();
|
||||
auto data_pos = data.begin();
|
||||
|
||||
while (filt_pos < filt_end)
|
||||
{
|
||||
if (*filt_pos)
|
||||
res_data.push_back(*data_pos);
|
||||
|
||||
++filt_pos;
|
||||
++data_pos;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -477,10 +527,10 @@ ColumnPtr ColumnVector<T>::replicate(const IColumn::Offsets & offsets) const
|
||||
|
||||
auto res = this->create(offsets.back());
|
||||
|
||||
auto * it = res->getData().begin();
|
||||
auto it = res->getData().begin(); // NOLINT
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
{
|
||||
const auto * span_end = res->getData().begin() + offsets[i];
|
||||
const auto span_end = res->getData().begin() + offsets[i]; // NOLINT
|
||||
for (; it != span_end; ++it)
|
||||
*it = data[i];
|
||||
}
|
||||
@ -497,6 +547,8 @@ void ColumnVector<T>::gather(ColumnGathererStream & gatherer)
|
||||
template <typename T>
|
||||
void ColumnVector<T>::getExtremes(Field & min, Field & max) const
|
||||
{
|
||||
using FastRefT = std::conditional_t<is_big_int_v<T>, const T &, const T>;
|
||||
|
||||
size_t size = data.size();
|
||||
|
||||
if (size == 0)
|
||||
@ -517,7 +569,7 @@ void ColumnVector<T>::getExtremes(Field & min, Field & max) const
|
||||
T cur_min = NaNOrZero<T>();
|
||||
T cur_max = NaNOrZero<T>();
|
||||
|
||||
for (const T x : data)
|
||||
for (FastRefT x : data)
|
||||
{
|
||||
if (isNaN(x))
|
||||
continue;
|
||||
@ -546,11 +598,13 @@ template class ColumnVector<UInt16>;
|
||||
template class ColumnVector<UInt32>;
|
||||
template class ColumnVector<UInt64>;
|
||||
template class ColumnVector<UInt128>;
|
||||
template class ColumnVector<bUInt256>;
|
||||
template class ColumnVector<Int8>;
|
||||
template class ColumnVector<Int16>;
|
||||
template class ColumnVector<Int32>;
|
||||
template class ColumnVector<Int64>;
|
||||
template class ColumnVector<Int128>;
|
||||
template class ColumnVector<bInt256>;
|
||||
template class ColumnVector<Float32>;
|
||||
template class ColumnVector<Float64>;
|
||||
}
|
||||
|
@ -6,11 +6,17 @@
|
||||
#include <Columns/ColumnVectorHelper.h>
|
||||
#include <common/unaligned.h>
|
||||
#include <Core/Field.h>
|
||||
#include <Core/BigInt.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/** Stuff for comparing numbers.
|
||||
* Integer values are compared as usual.
|
||||
* Floating-point numbers are compared this way that NaNs always end up at the end
|
||||
@ -105,7 +111,10 @@ private:
|
||||
|
||||
public:
|
||||
using ValueType = T;
|
||||
using Container = PaddedPODArray<ValueType>;
|
||||
static constexpr bool is_POD = !is_big_int_v<T>;
|
||||
using Container = std::conditional_t<is_POD,
|
||||
PaddedPODArray<ValueType>,
|
||||
std::vector<ValueType>>;
|
||||
|
||||
private:
|
||||
ColumnVector() {}
|
||||
@ -124,19 +133,17 @@ public:
|
||||
return data.size();
|
||||
}
|
||||
|
||||
StringRef getDataAt(size_t n) const override
|
||||
{
|
||||
return StringRef(reinterpret_cast<const char *>(&data[n]), sizeof(data[n]));
|
||||
}
|
||||
|
||||
void insertFrom(const IColumn & src, size_t n) override
|
||||
{
|
||||
data.push_back(static_cast<const Self &>(src).getData()[n]);
|
||||
}
|
||||
|
||||
void insertData(const char * pos, size_t /*length*/) override
|
||||
void insertData(const char * pos, size_t) override
|
||||
{
|
||||
data.push_back(unalignedLoad<T>(pos));
|
||||
if constexpr (is_POD)
|
||||
data.emplace_back(unalignedLoad<T>(pos));
|
||||
else
|
||||
data.emplace_back(BigInt<T>::deserialize(pos));
|
||||
}
|
||||
|
||||
void insertDefault() override
|
||||
@ -144,14 +151,20 @@ public:
|
||||
data.push_back(T());
|
||||
}
|
||||
|
||||
virtual void insertManyDefaults(size_t length) override
|
||||
void insertManyDefaults(size_t length) override
|
||||
{
|
||||
data.resize_fill(data.size() + length, T());
|
||||
if constexpr (is_POD)
|
||||
data.resize_fill(data.size() + length, T());
|
||||
else
|
||||
data.resize(data.size() + length, T());
|
||||
}
|
||||
|
||||
void popBack(size_t n) override
|
||||
{
|
||||
data.resize_assume_reserved(data.size() - n);
|
||||
if constexpr (is_POD)
|
||||
data.resize_assume_reserved(data.size() - n);
|
||||
else
|
||||
data.resize(data.size() - n);
|
||||
}
|
||||
|
||||
StringRef serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const override;
|
||||
@ -171,12 +184,16 @@ public:
|
||||
|
||||
size_t allocatedBytes() const override
|
||||
{
|
||||
return data.allocated_bytes();
|
||||
if constexpr (is_POD)
|
||||
return data.allocated_bytes();
|
||||
else
|
||||
return data.capacity() * sizeof(data[0]);
|
||||
}
|
||||
|
||||
void protect() override
|
||||
{
|
||||
data.protect();
|
||||
if constexpr (is_POD)
|
||||
data.protect();
|
||||
}
|
||||
|
||||
void insertValue(const T value)
|
||||
@ -274,13 +291,25 @@ public:
|
||||
|
||||
void gather(ColumnGathererStream & gatherer_stream) override;
|
||||
|
||||
|
||||
bool canBeInsideNullable() const override { return true; }
|
||||
|
||||
bool isFixedAndContiguous() const override { return true; }
|
||||
bool isFixedAndContiguous() const override { return is_POD; }
|
||||
size_t sizeOfValueIfFixed() const override { return sizeof(T); }
|
||||
StringRef getRawData() const override { return StringRef(reinterpret_cast<const char*>(data.data()), byteSize()); }
|
||||
|
||||
StringRef getRawData() const override
|
||||
{
|
||||
if constexpr (is_POD)
|
||||
return StringRef(reinterpret_cast<const char*>(data.data()), byteSize());
|
||||
else
|
||||
throw Exception("getRawData() is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
StringRef getDataAt(size_t n) const override
|
||||
{
|
||||
if constexpr (is_POD)
|
||||
return StringRef(reinterpret_cast<const char *>(&data[n]), sizeof(data[n]));
|
||||
else
|
||||
throw Exception("getDataAt() is not implemented for big integers", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
bool structureEquals(const IColumn & rhs) const override
|
||||
{
|
||||
|
@ -14,11 +14,14 @@ using ColumnUInt16 = ColumnVector<UInt16>;
|
||||
using ColumnUInt32 = ColumnVector<UInt32>;
|
||||
using ColumnUInt64 = ColumnVector<UInt64>;
|
||||
using ColumnUInt128 = ColumnVector<UInt128>;
|
||||
using ColumnUInt256 = ColumnVector<bUInt256>;
|
||||
|
||||
using ColumnInt8 = ColumnVector<Int8>;
|
||||
using ColumnInt16 = ColumnVector<Int16>;
|
||||
using ColumnInt32 = ColumnVector<Int32>;
|
||||
using ColumnInt64 = ColumnVector<Int64>;
|
||||
using ColumnInt128 = ColumnVector<Int128>;
|
||||
using ColumnInt256 = ColumnVector<bInt256>;
|
||||
|
||||
using ColumnFloat32 = ColumnVector<Float32>;
|
||||
using ColumnFloat64 = ColumnVector<Float64>;
|
||||
|
@ -402,7 +402,6 @@ public:
|
||||
virtual size_t sizeOfValueIfFixed() const { throw Exception("Values of column " + getName() + " are not fixed size.", ErrorCodes::CANNOT_GET_SIZE_OF_FIELD); }
|
||||
|
||||
/// Column is ColumnVector of numbers or ColumnConst of it. Note that Nullable columns are not numeric.
|
||||
/// Implies isFixedAndContiguous.
|
||||
virtual bool isNumeric() const { return false; }
|
||||
|
||||
/// If the only value column can contain is NULL.
|
||||
|
@ -262,6 +262,23 @@ TEST(WeakHash32, ColumnVectorU128)
|
||||
checkColumn(hash.getData(), eq_data, [&](size_t row) { return col->getElement(row).toHexString(); });
|
||||
}
|
||||
|
||||
TEST(WeakHash32, ColumnVectorI128)
|
||||
{
|
||||
auto col = ColumnInt128::create();
|
||||
auto & data = col->getData();
|
||||
|
||||
for (int idx [[maybe_unused]] : {1, 2})
|
||||
{
|
||||
for (int64_t i = -32768; i < 32768; ++i)
|
||||
data.push_back(i << 32); //-V610
|
||||
}
|
||||
|
||||
WeakHash32 hash(col->size());
|
||||
col->updateWeakHash32(hash);
|
||||
|
||||
checkColumn(hash.getData(), col->getData(), [&](size_t row) { return std::to_string(Int64(col->getElement(row))); });
|
||||
}
|
||||
|
||||
TEST(WeakHash32, ColumnDecimal32)
|
||||
{
|
||||
auto col = ColumnDecimal<Decimal32>::create(0, 0);
|
||||
@ -300,23 +317,17 @@ TEST(WeakHash32, ColumnDecimal128)
|
||||
{
|
||||
auto col = ColumnDecimal<Decimal128>::create(0, 0);
|
||||
auto & data = col->getData();
|
||||
auto eq = ColumnUInt32::create();
|
||||
auto & eq_data = eq->getData();
|
||||
|
||||
for (int idx [[maybe_unused]] : {1, 2})
|
||||
{
|
||||
for (uint64_t i = 0; i < 65536; ++i)
|
||||
{
|
||||
UInt128 val(i << 32u, i << 32u);
|
||||
data.push_back(val);
|
||||
eq_data.push_back(i);
|
||||
}
|
||||
for (int64_t i = -32768; i < 32768; ++i)
|
||||
data.push_back(i << 32); //-V610
|
||||
}
|
||||
|
||||
WeakHash32 hash(col->size());
|
||||
col->updateWeakHash32(hash);
|
||||
|
||||
checkColumn(hash.getData(), eq_data, [&](size_t row) { return getHexUIntLowercase(col->getElement(row)); });
|
||||
checkColumn(hash.getData(), col->getData(), [&](size_t row) { return std::to_string(Int64(col->getElement(row))); });
|
||||
}
|
||||
|
||||
TEST(WeakHash32, ColumnString1)
|
||||
|
@ -47,6 +47,10 @@ String FieldVisitorDump::operator() (const Float64 & x) const { return formatQuo
|
||||
String FieldVisitorDump::operator() (const DecimalField<Decimal32> & x) const { return formatQuotedWithPrefix(x, "Decimal32_"); }
|
||||
String FieldVisitorDump::operator() (const DecimalField<Decimal64> & x) const { return formatQuotedWithPrefix(x, "Decimal64_"); }
|
||||
String FieldVisitorDump::operator() (const DecimalField<Decimal128> & x) const { return formatQuotedWithPrefix(x, "Decimal128_"); }
|
||||
String FieldVisitorDump::operator() (const DecimalField<Decimal256> & x) const { return formatQuotedWithPrefix(x, "Decimal256_"); }
|
||||
String FieldVisitorDump::operator() (const bUInt256 & x) const { return formatQuotedWithPrefix(x, "UInt256_"); }
|
||||
String FieldVisitorDump::operator() (const bInt256 & x) const { return formatQuotedWithPrefix(x, "Int256_"); }
|
||||
String FieldVisitorDump::operator() (const Int128 & x) const { return formatQuotedWithPrefix(x, "Int128_"); }
|
||||
String FieldVisitorDump::operator() (const UInt128 & x) const { return formatQuotedWithPrefix(UUID(x), "UUID_"); }
|
||||
|
||||
|
||||
@ -130,11 +134,15 @@ String FieldVisitorToString::operator() (const String & x) const { return format
|
||||
String FieldVisitorToString::operator() (const DecimalField<Decimal32> & x) const { return formatQuoted(x); }
|
||||
String FieldVisitorToString::operator() (const DecimalField<Decimal64> & x) const { return formatQuoted(x); }
|
||||
String FieldVisitorToString::operator() (const DecimalField<Decimal128> & x) const { return formatQuoted(x); }
|
||||
String FieldVisitorToString::operator() (const DecimalField<Decimal256> & x) const { return formatQuoted(x); }
|
||||
String FieldVisitorToString::operator() (const Int128 & x) const { return formatQuoted(x); }
|
||||
String FieldVisitorToString::operator() (const UInt128 & x) const { return formatQuoted(UUID(x)); }
|
||||
String FieldVisitorToString::operator() (const AggregateFunctionStateData & x) const
|
||||
{
|
||||
return formatQuoted(x.data);
|
||||
}
|
||||
String FieldVisitorToString::operator() (const bUInt256 & x) const { return formatQuoted(x); }
|
||||
String FieldVisitorToString::operator() (const bInt256 & x) const { return formatQuoted(x); }
|
||||
|
||||
String FieldVisitorToString::operator() (const Array & x) const
|
||||
{
|
||||
@ -198,6 +206,13 @@ void FieldVisitorHash::operator() (const Int64 & x) const
|
||||
hash.update(x);
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const Int128 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Int128;
|
||||
hash.update(type);
|
||||
hash.update(x);
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const Float64 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Float64;
|
||||
@ -237,21 +252,28 @@ void FieldVisitorHash::operator() (const DecimalField<Decimal32> & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Decimal32;
|
||||
hash.update(type);
|
||||
hash.update(x);
|
||||
hash.update(x.getValue().value);
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const DecimalField<Decimal64> & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Decimal64;
|
||||
hash.update(type);
|
||||
hash.update(x);
|
||||
hash.update(x.getValue().value);
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const DecimalField<Decimal128> & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Decimal128;
|
||||
hash.update(type);
|
||||
hash.update(x);
|
||||
hash.update(x.getValue().value);
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const DecimalField<Decimal256> & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::Decimal256;
|
||||
hash.update(type);
|
||||
hash.update(x.getValue().value);
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const AggregateFunctionStateData & x) const
|
||||
@ -264,5 +286,18 @@ void FieldVisitorHash::operator() (const AggregateFunctionStateData & x) const
|
||||
hash.update(x.data.data(), x.data.size());
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const bUInt256 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::bUInt256;
|
||||
hash.update(type);
|
||||
hash.update(x);
|
||||
}
|
||||
|
||||
void FieldVisitorHash::operator() (const bInt256 & x) const
|
||||
{
|
||||
UInt8 type = Field::Types::bInt256;
|
||||
hash.update(type);
|
||||
hash.update(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <Core/DecimalFunctions.h>
|
||||
#include <Core/Field.h>
|
||||
#include <common/demangle.h>
|
||||
|
||||
@ -14,6 +15,7 @@ namespace ErrorCodes
|
||||
{
|
||||
extern const int CANNOT_CONVERT_TYPE;
|
||||
extern const int LOGICAL_ERROR;
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
@ -69,6 +71,7 @@ public:
|
||||
String operator() (const UInt64 & x) const;
|
||||
String operator() (const UInt128 & x) const;
|
||||
String operator() (const Int64 & x) const;
|
||||
String operator() (const Int128 & x) const;
|
||||
String operator() (const Float64 & x) const;
|
||||
String operator() (const String & x) const;
|
||||
String operator() (const Array & x) const;
|
||||
@ -76,7 +79,11 @@ public:
|
||||
String operator() (const DecimalField<Decimal32> & x) const;
|
||||
String operator() (const DecimalField<Decimal64> & x) const;
|
||||
String operator() (const DecimalField<Decimal128> & x) const;
|
||||
String operator() (const DecimalField<Decimal256> & x) const;
|
||||
String operator() (const AggregateFunctionStateData & x) const;
|
||||
|
||||
String operator() (const bUInt256 & x) const;
|
||||
String operator() (const bInt256 & x) const;
|
||||
};
|
||||
|
||||
|
||||
@ -88,6 +95,7 @@ public:
|
||||
String operator() (const UInt64 & x) const;
|
||||
String operator() (const UInt128 & x) const;
|
||||
String operator() (const Int64 & x) const;
|
||||
String operator() (const Int128 & x) const;
|
||||
String operator() (const Float64 & x) const;
|
||||
String operator() (const String & x) const;
|
||||
String operator() (const Array & x) const;
|
||||
@ -95,7 +103,11 @@ public:
|
||||
String operator() (const DecimalField<Decimal32> & x) const;
|
||||
String operator() (const DecimalField<Decimal64> & x) const;
|
||||
String operator() (const DecimalField<Decimal128> & x) const;
|
||||
String operator() (const DecimalField<Decimal256> & x) const;
|
||||
String operator() (const AggregateFunctionStateData & x) const;
|
||||
|
||||
String operator() (const bUInt256 & x) const;
|
||||
String operator() (const bInt256 & x) const;
|
||||
};
|
||||
|
||||
|
||||
@ -126,7 +138,15 @@ public:
|
||||
|
||||
T operator() (const UInt64 & x) const { return T(x); }
|
||||
T operator() (const Int64 & x) const { return T(x); }
|
||||
T operator() (const Float64 & x) const { return T(x); }
|
||||
T operator() (const Int128 & x) const { return T(x); }
|
||||
|
||||
T operator() (const Float64 & x) const
|
||||
{
|
||||
if constexpr (std::is_same_v<Decimal256, T>)
|
||||
return bInt256(x);
|
||||
else
|
||||
return T(x);
|
||||
}
|
||||
|
||||
T operator() (const UInt128 &) const
|
||||
{
|
||||
@ -137,15 +157,43 @@ public:
|
||||
T operator() (const DecimalField<U> & x) const
|
||||
{
|
||||
if constexpr (std::is_floating_point_v<T>)
|
||||
return static_cast<T>(x.getValue()) / x.getScaleMultiplier();
|
||||
return x.getValue(). template convertTo<T>() / x.getScaleMultiplier(). template convertTo<T>();
|
||||
else if constexpr (std::is_same_v<T, UInt128>)
|
||||
{
|
||||
/// TODO: remove with old UInt128 type
|
||||
if constexpr (sizeof(U) < 16)
|
||||
{
|
||||
return UInt128(0, (x.getValue() / x.getScaleMultiplier()).value);
|
||||
}
|
||||
else if constexpr (sizeof(U) == 16)
|
||||
{
|
||||
auto tmp = (x.getValue() / x.getScaleMultiplier()).value;
|
||||
return UInt128(tmp >> 64, UInt64(tmp));
|
||||
}
|
||||
else
|
||||
throw Exception("No conversion to old UInt128 from " + demangle(typeid(U).name()), ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
else
|
||||
return static_cast<T>(x.getValue() / x.getScaleMultiplier());
|
||||
return (x.getValue() / x.getScaleMultiplier()). template convertTo<T>();
|
||||
}
|
||||
|
||||
T operator() (const AggregateFunctionStateData &) const
|
||||
{
|
||||
throw Exception("Cannot convert AggregateFunctionStateData to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE);
|
||||
}
|
||||
|
||||
template <typename U, typename = std::enable_if_t<is_big_int_v<U>> >
|
||||
T operator() (const U & x) const
|
||||
{
|
||||
if constexpr (IsDecimalNumber<T>)
|
||||
return static_cast<T>(static_cast<typename T::NativeType>(x));
|
||||
else if constexpr (std::is_same_v<T, UInt8>)
|
||||
return static_cast<T>(static_cast<UInt16>(x));
|
||||
else if constexpr (std::is_same_v<T, UInt128>)
|
||||
throw Exception("No conversion to old UInt128 from " + demangle(typeid(U).name()), ErrorCodes::NOT_IMPLEMENTED);
|
||||
else
|
||||
return static_cast<T>(x);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -161,6 +209,7 @@ public:
|
||||
void operator() (const UInt64 & x) const;
|
||||
void operator() (const UInt128 & x) const;
|
||||
void operator() (const Int64 & x) const;
|
||||
void operator() (const Int128 & x) const;
|
||||
void operator() (const Float64 & x) const;
|
||||
void operator() (const String & x) const;
|
||||
void operator() (const Array & x) const;
|
||||
@ -168,7 +217,11 @@ public:
|
||||
void operator() (const DecimalField<Decimal32> & x) const;
|
||||
void operator() (const DecimalField<Decimal64> & x) const;
|
||||
void operator() (const DecimalField<Decimal128> & x) const;
|
||||
void operator() (const DecimalField<Decimal256> & x) const;
|
||||
void operator() (const AggregateFunctionStateData & x) const;
|
||||
|
||||
void operator() (const bUInt256 & x) const;
|
||||
void operator() (const bInt256 & x) const;
|
||||
};
|
||||
|
||||
|
||||
@ -176,6 +229,7 @@ template <typename T> constexpr bool isDecimalField() { return false; }
|
||||
template <> constexpr bool isDecimalField<DecimalField<Decimal32>>() { return true; }
|
||||
template <> constexpr bool isDecimalField<DecimalField<Decimal64>>() { return true; }
|
||||
template <> constexpr bool isDecimalField<DecimalField<Decimal128>>() { return true; }
|
||||
template <> constexpr bool isDecimalField<DecimalField<Decimal256>>() { return true; }
|
||||
|
||||
|
||||
/** Implements `+=` operation.
|
||||
@ -205,11 +259,24 @@ public:
|
||||
bool operator() (UInt128 &) const { throw Exception("Cannot sum UUIDs", ErrorCodes::LOGICAL_ERROR); }
|
||||
bool operator() (AggregateFunctionStateData &) const { throw Exception("Cannot sum AggregateFunctionStates", ErrorCodes::LOGICAL_ERROR); }
|
||||
|
||||
bool operator() (Int128 & x) const
|
||||
{
|
||||
x += get<Int128>(rhs);
|
||||
return x != Int128(0);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator() (DecimalField<T> & x) const
|
||||
{
|
||||
x += get<DecimalField<T>>(rhs);
|
||||
return x.getValue() != 0;
|
||||
return x.getValue() != T(0);
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<is_big_int_v<T>> >
|
||||
bool operator() (T & x) const
|
||||
{
|
||||
x += rhs.reinterpret<T>();
|
||||
return x != T(0);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -72,7 +72,7 @@ inline DB::UInt64 intHashCRC32(DB::UInt64 x, DB::UInt64 updated_value)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename std::enable_if<(sizeof(T) > sizeof(DB::UInt64)), DB::UInt64>::type
|
||||
inline typename std::enable_if<(sizeof(T) > sizeof(DB::UInt64)) && !is_big_int_v<T>, DB::UInt64>::type
|
||||
intHashCRC32(const T & x, DB::UInt64 updated_value)
|
||||
{
|
||||
auto * begin = reinterpret_cast<const char *>(&x);
|
||||
@ -85,6 +85,18 @@ intHashCRC32(const T & x, DB::UInt64 updated_value)
|
||||
return updated_value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline typename std::enable_if<is_big_int_v<T>, DB::UInt64>::type
|
||||
intHashCRC32(const T & x, DB::UInt64 updated_value)
|
||||
{
|
||||
std::vector<UInt64> parts;
|
||||
export_bits(x, std::back_inserter(parts), sizeof(UInt64), false);
|
||||
for (const auto & part : parts)
|
||||
updated_value = intHashCRC32(part, updated_value);
|
||||
|
||||
return updated_value;
|
||||
}
|
||||
|
||||
inline UInt32 updateWeakHash32(const DB::UInt8 * pos, size_t size, DB::UInt32 updated_value)
|
||||
{
|
||||
if (size < 8)
|
||||
@ -164,7 +176,7 @@ inline UInt32 updateWeakHash32(const DB::UInt8 * pos, size_t size, DB::UInt32 up
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline size_t DefaultHash64(T key)
|
||||
inline size_t DefaultHash64(std::enable_if_t<(sizeof(T) <= sizeof(UInt64)), T> key)
|
||||
{
|
||||
union
|
||||
{
|
||||
@ -176,11 +188,32 @@ inline size_t DefaultHash64(T key)
|
||||
return intHash64(u.out);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline size_t DefaultHash64(std::enable_if_t<(sizeof(T) > sizeof(UInt64)), T> key)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, DB::Int128>)
|
||||
{
|
||||
return intHash64(static_cast<UInt64>(key) ^ static_cast<UInt64>(key >> 64));
|
||||
}
|
||||
if constexpr (std::is_same_v<T, DB::UInt128>)
|
||||
{
|
||||
return intHash64(key.low ^ key.high);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, bInt256> || std::is_same_v<T, bUInt256>)
|
||||
{
|
||||
return intHash64(static_cast<UInt64>(key) ^
|
||||
static_cast<UInt64>(key >> 64) ^
|
||||
static_cast<UInt64>(key >> 128) ^
|
||||
static_cast<UInt64>(key >> 256));
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
template <typename T, typename Enable = void>
|
||||
struct DefaultHash;
|
||||
|
||||
template <typename T>
|
||||
struct DefaultHash<T, std::enable_if_t<is_arithmetic_v<T>>>
|
||||
struct DefaultHash<T, std::enable_if_t<!DB::IsDecimalNumber<T>>>
|
||||
{
|
||||
size_t operator() (T key) const
|
||||
{
|
||||
@ -189,7 +222,7 @@ struct DefaultHash<T, std::enable_if_t<is_arithmetic_v<T>>>
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct DefaultHash<T, std::enable_if_t<DB::IsDecimalNumber<T> && sizeof(T) <= 8>>
|
||||
struct DefaultHash<T, std::enable_if_t<DB::IsDecimalNumber<T>>>
|
||||
{
|
||||
size_t operator() (T key) const
|
||||
{
|
||||
@ -197,19 +230,10 @@ struct DefaultHash<T, std::enable_if_t<DB::IsDecimalNumber<T> && sizeof(T) <= 8>
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct DefaultHash<T, std::enable_if_t<DB::IsDecimalNumber<T> && sizeof(T) == 16>>
|
||||
{
|
||||
size_t operator() (T key) const
|
||||
{
|
||||
return DefaultHash64<Int64>(key >> 64) ^ DefaultHash64<Int64>(key);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct HashCRC32;
|
||||
|
||||
template <typename T>
|
||||
inline size_t hashCRC32(T key)
|
||||
inline size_t hashCRC32(std::enable_if_t<(sizeof(T) <= sizeof(UInt64)), T> key)
|
||||
{
|
||||
union
|
||||
{
|
||||
@ -221,6 +245,27 @@ inline size_t hashCRC32(T key)
|
||||
return intHashCRC32(u.out);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline size_t hashCRC32(std::enable_if_t<(sizeof(T) > sizeof(UInt64)), T> key)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, DB::Int128>)
|
||||
{
|
||||
return intHashCRC32(static_cast<UInt64>(key) ^ static_cast<UInt64>(key >> 64));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, DB::UInt128>)
|
||||
{
|
||||
return intHashCRC32(key.low ^ key.high);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, bInt256> || std::is_same_v<T, bUInt256>)
|
||||
{
|
||||
return intHashCRC32(static_cast<UInt64>(key) ^
|
||||
static_cast<UInt64>(key >> 64) ^
|
||||
static_cast<UInt64>(key >> 128) ^
|
||||
static_cast<UInt64>(key >> 256));
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
#define DEFINE_HASH(T) \
|
||||
template <> struct HashCRC32<T>\
|
||||
{\
|
||||
@ -235,10 +280,13 @@ DEFINE_HASH(DB::UInt16)
|
||||
DEFINE_HASH(DB::UInt32)
|
||||
DEFINE_HASH(DB::UInt64)
|
||||
DEFINE_HASH(DB::UInt128)
|
||||
DEFINE_HASH(DB::bUInt256)
|
||||
DEFINE_HASH(DB::Int8)
|
||||
DEFINE_HASH(DB::Int16)
|
||||
DEFINE_HASH(DB::Int32)
|
||||
DEFINE_HASH(DB::Int64)
|
||||
DEFINE_HASH(DB::Int128)
|
||||
DEFINE_HASH(DB::bInt256)
|
||||
DEFINE_HASH(DB::Float32)
|
||||
DEFINE_HASH(DB::Float64)
|
||||
|
||||
@ -302,6 +350,23 @@ struct IntHash32
|
||||
{
|
||||
size_t operator() (const T & key) const
|
||||
{
|
||||
return intHash32<salt>(key);
|
||||
if constexpr (std::is_same_v<T, DB::Int128>)
|
||||
{
|
||||
return intHash32<salt>(static_cast<UInt64>(key) ^ static_cast<UInt64>(key >> 64));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, DB::UInt128>)
|
||||
{
|
||||
return intHash32<salt>(key.low ^ key.high);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, bInt256> || std::is_same_v<T, bUInt256>)
|
||||
{
|
||||
return intHash32<salt>(static_cast<UInt64>(key) ^
|
||||
static_cast<UInt64>(key >> 64) ^
|
||||
static_cast<UInt64>(key >> 128) ^
|
||||
static_cast<UInt64>(key >> 256));
|
||||
}
|
||||
else if constexpr (sizeof(T) <= sizeof(UInt64))
|
||||
return intHash32<salt>(key);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
};
|
||||
|
@ -27,6 +27,7 @@ class HyperLogLogWithSmallSetOptimization : private boost::noncopyable
|
||||
private:
|
||||
using Small = SmallSet<Key, small_set_size>;
|
||||
using Large = HyperLogLogCounter<K, Hash, UInt32, DenominatorType>;
|
||||
using LargeValueType = typename Large::value_type;
|
||||
|
||||
Small small;
|
||||
Large * large = nullptr;
|
||||
@ -42,7 +43,7 @@ private:
|
||||
Large * tmp_large = new Large;
|
||||
|
||||
for (const auto & x : small)
|
||||
tmp_large->insert(x.getValue());
|
||||
tmp_large->insert(static_cast<LargeValueType>(x.getValue()));
|
||||
|
||||
large = tmp_large;
|
||||
}
|
||||
@ -68,12 +69,12 @@ public:
|
||||
else
|
||||
{
|
||||
toLarge();
|
||||
large->insert(value);
|
||||
large->insert(static_cast<LargeValueType>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
large->insert(value);
|
||||
large->insert(static_cast<LargeValueType>(value));
|
||||
}
|
||||
|
||||
UInt64 size() const
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
#include <common/types.h>
|
||||
|
||||
|
||||
/// To be sure, that this function is zero-cost for non-floating point types.
|
||||
template <typename T>
|
||||
@ -37,21 +39,13 @@ std::enable_if_t<std::is_floating_point_v<T>, T> NaNOrZero()
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::numeric_limits<T>::is_integer, T> NaNOrZero()
|
||||
std::enable_if_t<is_integer_v<T>, T> NaNOrZero()
|
||||
{
|
||||
return 0;
|
||||
return T{0};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_class_v<T>, T> NaNOrZero()
|
||||
std::enable_if_t<std::is_class_v<T> && !is_integer_v<T>, T> NaNOrZero()
|
||||
{
|
||||
return T{};
|
||||
}
|
||||
|
||||
#if 1 /// __int128
|
||||
template <typename T>
|
||||
std::enable_if_t<std::is_same_v<T, __int128> && !std::numeric_limits<T>::is_integer, __int128> NaNOrZero()
|
||||
{
|
||||
return __int128(0);
|
||||
}
|
||||
#endif
|
||||
|
@ -167,7 +167,7 @@ struct RadixSortIntTraits
|
||||
using Result = Element;
|
||||
using Key = Element;
|
||||
using CountType = uint32_t;
|
||||
using KeyBits = std::make_unsigned_t<Key>;
|
||||
using KeyBits = make_unsigned_t<Key>;
|
||||
|
||||
static constexpr size_t PART_SIZE_BITS = 8;
|
||||
|
||||
@ -186,7 +186,7 @@ struct RadixSortIntTraits
|
||||
|
||||
template <typename T>
|
||||
using RadixSortNumTraits = std::conditional_t<
|
||||
is_integral_v<T>,
|
||||
is_integer_v<T>,
|
||||
std::conditional_t<is_unsigned_v<T>, RadixSortUIntTraits<T>, RadixSortIntTraits<T>>,
|
||||
RadixSortFloatTraits<T>>;
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <Core/Defines.h>
|
||||
#include <Core/BigInt.h>
|
||||
|
||||
#define ROTL(x, b) static_cast<UInt64>(((x) << (b)) | ((x) >> (64 - (b))))
|
||||
|
||||
@ -134,13 +135,24 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// NOTE: std::has_unique_object_representations is only available since clang 6. As of Mar 2017 we still use clang 5 sometimes.
|
||||
template <typename T>
|
||||
std::enable_if_t<std::/*has_unique_object_representations_v*/is_standard_layout_v<T>, void> update(const T & x)
|
||||
std::enable_if_t<std::has_unique_object_representations_v<T>, void> update(const T & x)
|
||||
{
|
||||
update(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<(std::is_floating_point_v<T> || std::is_same_v<T, CityHash_v1_0_2::uint128>), void> update(const T & x)
|
||||
{
|
||||
update(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<is_big_int_v<T>, void> update(const T & x)
|
||||
{
|
||||
update(DB::BigInt<T>::serialize(x));
|
||||
}
|
||||
|
||||
void update(const std::string & x)
|
||||
{
|
||||
update(x.data(), x.length());
|
||||
@ -193,13 +205,27 @@ inline UInt64 sipHash64(const char * data, const size_t size)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<std::/*has_unique_object_representations_v*/is_standard_layout_v<T>, UInt64> sipHash64(const T & x)
|
||||
std::enable_if_t<std::has_unique_object_representations_v<T>, UInt64> sipHash64(const T & x)
|
||||
{
|
||||
SipHash hash;
|
||||
hash.update(x);
|
||||
return hash.get64();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<(std::is_floating_point_v<T> || is_big_int_v<T>), UInt64> sipHash64(const T & x)
|
||||
{
|
||||
SipHash hash;
|
||||
hash.update(x);
|
||||
return hash.get64();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::enable_if_t<DB::IsDecimalNumber<T>, UInt64> sipHash64(const T & x)
|
||||
{
|
||||
return sipHash64(x.value);
|
||||
}
|
||||
|
||||
inline UInt64 sipHash64(const std::string & s)
|
||||
{
|
||||
return sipHash64(s.data(), s.size());
|
||||
|
@ -30,7 +30,19 @@ struct UInt128
|
||||
|
||||
UInt128() = default;
|
||||
explicit UInt128(const UInt64 low_, const UInt64 high_) : low(low_), high(high_) {}
|
||||
|
||||
/// We need Int128 to UInt128 conversion or AccurateComparison will call greaterOp<Int128, UInt64> instead of greaterOp<Int128, UInt128>
|
||||
explicit UInt128(const Int128 rhs) : low(rhs), high(rhs >> 64) {}
|
||||
explicit UInt128(const Int64 rhs) : low(rhs), high() {}
|
||||
explicit UInt128(const Int32 rhs) : low(rhs), high() {}
|
||||
explicit UInt128(const Int16 rhs) : low(rhs), high() {}
|
||||
explicit UInt128(const Int8 rhs) : low(rhs), high() {}
|
||||
explicit UInt128(const UInt8 rhs) : low(rhs), high() {}
|
||||
explicit UInt128(const UInt16 rhs) : low(rhs), high() {}
|
||||
explicit UInt128(const UInt32 rhs) : low(rhs), high() {}
|
||||
explicit UInt128(const UInt64 rhs) : low(rhs), high() {}
|
||||
explicit UInt128(const Float32 rhs) : low(rhs), high() {}
|
||||
explicit UInt128(const Float64 rhs) : low(rhs), high() {}
|
||||
|
||||
auto tuple() const { return std::tie(high, low); }
|
||||
|
||||
@ -48,6 +60,13 @@ struct UInt128
|
||||
bool inline operator> (const UInt128 rhs) const { return tuple() > rhs.tuple(); }
|
||||
bool inline operator>= (const UInt128 rhs) const { return tuple() >= rhs.tuple(); }
|
||||
|
||||
bool inline operator == (const Int128 rhs) const { return *this == UInt128(rhs, rhs >> 64) && rhs >= 0; }
|
||||
bool inline operator != (const Int128 rhs) const { return *this != UInt128(rhs, rhs >> 64) || rhs < 0; }
|
||||
bool inline operator >= (const Int128 rhs) const { return *this >= UInt128(rhs, rhs >> 64) || rhs < 0; }
|
||||
bool inline operator > (const Int128 rhs) const { return *this > UInt128(rhs, rhs >> 64) || rhs < 0; }
|
||||
bool inline operator <= (const Int128 rhs) const { return *this <= UInt128(rhs, rhs >> 64) && rhs >= 0; }
|
||||
bool inline operator < (const Int128 rhs) const { return *this < UInt128(rhs, rhs >> 64) && rhs >= 0; }
|
||||
|
||||
template <typename T> bool inline operator== (const T rhs) const { return *this == UInt128(rhs); }
|
||||
template <typename T> bool inline operator!= (const T rhs) const { return *this != UInt128(rhs); }
|
||||
template <typename T> bool inline operator>= (const T rhs) const { return *this >= UInt128(rhs); }
|
||||
@ -55,7 +74,13 @@ struct UInt128
|
||||
template <typename T> bool inline operator<= (const T rhs) const { return *this <= UInt128(rhs); }
|
||||
template <typename T> bool inline operator< (const T rhs) const { return *this < UInt128(rhs); }
|
||||
|
||||
template <typename T> explicit operator T() const { return static_cast<T>(low); }
|
||||
template <typename T> explicit operator T() const
|
||||
{
|
||||
if constexpr (std::is_class_v<T>)
|
||||
return T();
|
||||
else
|
||||
return static_cast<T>(low);
|
||||
}
|
||||
|
||||
#if !__clang__
|
||||
#pragma GCC diagnostic pop
|
||||
@ -64,12 +89,12 @@ struct UInt128
|
||||
UInt128 & operator= (const UInt64 rhs) { low = rhs; high = 0; return *this; }
|
||||
};
|
||||
|
||||
template <typename T> bool inline operator== (T a, const UInt128 b) { return UInt128(a) == b; }
|
||||
template <typename T> bool inline operator!= (T a, const UInt128 b) { return UInt128(a) != b; }
|
||||
template <typename T> bool inline operator>= (T a, const UInt128 b) { return UInt128(a) >= b; }
|
||||
template <typename T> bool inline operator> (T a, const UInt128 b) { return UInt128(a) > b; }
|
||||
template <typename T> bool inline operator<= (T a, const UInt128 b) { return UInt128(a) <= b; }
|
||||
template <typename T> bool inline operator< (T a, const UInt128 b) { return UInt128(a) < b; }
|
||||
template <typename T> bool inline operator == (T a, const UInt128 b) { return b == a; }
|
||||
template <typename T> bool inline operator != (T a, const UInt128 b) { return b != a; }
|
||||
template <typename T> bool inline operator >= (T a, const UInt128 b) { return b <= a; }
|
||||
template <typename T> bool inline operator > (T a, const UInt128 b) { return b < a; }
|
||||
template <typename T> bool inline operator <= (T a, const UInt128 b) { return b >= a; }
|
||||
template <typename T> bool inline operator < (T a, const UInt128 b) { return b > a; }
|
||||
|
||||
template <> inline constexpr bool IsNumber<UInt128> = true;
|
||||
template <> struct TypeName<UInt128> { static constexpr const char * get() { return "UInt128"; } };
|
||||
@ -194,7 +219,7 @@ template <> struct is_unsigned<DB::UInt128>
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template <> struct is_integral<DB::UInt128>
|
||||
template <> struct is_integer<DB::UInt128>
|
||||
{
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
@ -1,49 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ZooKeeperHolder.h"
|
||||
|
||||
namespace zkutil
|
||||
{
|
||||
|
||||
class Increment
|
||||
{
|
||||
public:
|
||||
Increment(ZooKeeperHolderPtr zk_holder_, const std::string & path_)
|
||||
: zookeeper_holder(zk_holder_), path(path_)
|
||||
{
|
||||
zookeeper_holder->getZooKeeper()->createAncestors(path);
|
||||
}
|
||||
|
||||
size_t get()
|
||||
{
|
||||
LOG_TRACE(log, "Get increment");
|
||||
|
||||
size_t result = 0;
|
||||
std::string result_str;
|
||||
Coordination::Stat stat;
|
||||
|
||||
bool success = false;
|
||||
auto zookeeper = zookeeper_holder->getZooKeeper();
|
||||
do
|
||||
{
|
||||
if (zookeeper->tryGet(path, result_str, &stat))
|
||||
{
|
||||
result = std::stol(result_str) + 1;
|
||||
success = zookeeper->trySet(path, std::to_string(result), stat.version) == Coordination::Error::ZOK;
|
||||
}
|
||||
else
|
||||
{
|
||||
success = zookeeper->tryCreate(path, std::to_string(result), zkutil::CreateMode::Persistent) == Coordination::Error::ZOK;
|
||||
}
|
||||
}
|
||||
while (!success);
|
||||
|
||||
return result;
|
||||
}
|
||||
private:
|
||||
zkutil::ZooKeeperHolderPtr zookeeper_holder;
|
||||
std::string path;
|
||||
Poco::Logger * log = &Poco::Logger::get("zkutil::Increment");
|
||||
};
|
||||
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
#include "KeeperException.h"
|
||||
#include "Lock.h"
|
||||
|
||||
|
||||
using namespace zkutil;
|
||||
|
||||
bool Lock::tryLock()
|
||||
{
|
||||
auto zookeeper = zookeeper_holder->getZooKeeper();
|
||||
if (locked)
|
||||
{
|
||||
/// проверим, что нода создана и я ее владелец
|
||||
if (tryCheck() != Status::LOCKED_BY_ME)
|
||||
locked.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string dummy;
|
||||
Coordination::Error code = zookeeper->tryCreate(lock_path, lock_message, zkutil::CreateMode::Ephemeral, dummy);
|
||||
|
||||
if (code == Coordination::Error::ZNODEEXISTS)
|
||||
{
|
||||
locked.reset();
|
||||
}
|
||||
else if (code == Coordination::Error::ZOK)
|
||||
{
|
||||
locked = std::make_unique<ZooKeeperHandler>(zookeeper);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Coordination::Exception(code);
|
||||
}
|
||||
}
|
||||
return bool(locked);
|
||||
}
|
||||
|
||||
void Lock::unlock()
|
||||
{
|
||||
if (locked)
|
||||
{
|
||||
auto zookeeper = zookeeper_holder->getZooKeeper();
|
||||
if (tryCheck() == Status::LOCKED_BY_ME)
|
||||
zookeeper->remove(lock_path, -1);
|
||||
locked.reset();
|
||||
}
|
||||
}
|
||||
|
||||
Lock::Status Lock::tryCheck() const
|
||||
{
|
||||
auto zookeeper = zookeeper_holder->getZooKeeper();
|
||||
|
||||
Status lock_status;
|
||||
Coordination::Stat stat;
|
||||
std::string dummy;
|
||||
bool result = zookeeper->tryGet(lock_path, dummy, &stat);
|
||||
if (!result)
|
||||
lock_status = UNLOCKED;
|
||||
else
|
||||
{
|
||||
if (stat.ephemeralOwner == zookeeper->getClientID())
|
||||
lock_status = LOCKED_BY_ME;
|
||||
else
|
||||
lock_status = LOCKED_BY_OTHER;
|
||||
}
|
||||
|
||||
if (locked && lock_status != LOCKED_BY_ME)
|
||||
LOG_WARNING(log, "Lock is lost. It is normal if session was expired. Path: {}/{}", lock_path, lock_message);
|
||||
|
||||
return lock_status;
|
||||
}
|
||||
|
||||
void Lock::unlockAssumeLockNodeRemovedManually()
|
||||
{
|
||||
locked.reset();
|
||||
}
|
||||
|
@ -1,78 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ZooKeeperHolder.h"
|
||||
#include <common/logger_useful.h>
|
||||
#include <Common/Exception.h>
|
||||
|
||||
namespace zkutil
|
||||
{
|
||||
class Lock
|
||||
{
|
||||
public:
|
||||
/// lock_prefix - относительный путь до блокировки в ZK. Начинается со слеша
|
||||
/// lock_name - имя ноды блокировки в ZK
|
||||
Lock(
|
||||
zkutil::ZooKeeperHolderPtr zookeeper_holder_,
|
||||
const std::string & lock_prefix_,
|
||||
const std::string & lock_name_,
|
||||
const std::string & lock_message_ = "",
|
||||
bool create_parent_path_ = false)
|
||||
:
|
||||
zookeeper_holder(zookeeper_holder_),
|
||||
lock_path(lock_prefix_ + "/" + lock_name_),
|
||||
lock_message(lock_message_),
|
||||
log(&Poco::Logger::get("zkutil::Lock"))
|
||||
{
|
||||
auto zookeeper = zookeeper_holder->getZooKeeper();
|
||||
if (create_parent_path_)
|
||||
zookeeper->createAncestors(lock_prefix_);
|
||||
|
||||
zookeeper->createIfNotExists(lock_prefix_, "");
|
||||
}
|
||||
|
||||
Lock(const Lock &) = delete;
|
||||
Lock(Lock && lock) = default;
|
||||
Lock & operator=(const Lock &) = delete;
|
||||
|
||||
~Lock()
|
||||
{
|
||||
try
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
DB::tryLogCurrentException(__PRETTY_FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
enum Status
|
||||
{
|
||||
UNLOCKED,
|
||||
LOCKED_BY_ME,
|
||||
LOCKED_BY_OTHER,
|
||||
};
|
||||
|
||||
/// проверяет создана ли эфемерная нода и кто ее владелец.
|
||||
Status tryCheck() const;
|
||||
|
||||
void unlock();
|
||||
void unlockAssumeLockNodeRemovedManually();
|
||||
|
||||
bool tryLock();
|
||||
|
||||
/// путь к ноде блокировки в zookeeper
|
||||
const std::string & getPath() { return lock_path; }
|
||||
|
||||
private:
|
||||
zkutil::ZooKeeperHolderPtr zookeeper_holder;
|
||||
/// пока храним указатель на хендлер, никто не может переиницализировать сессию с zookeeper
|
||||
using ZooKeeperHandler = zkutil::ZooKeeperHolder::UnstorableZookeeperHandler;
|
||||
std::unique_ptr<ZooKeeperHandler> locked;
|
||||
|
||||
std::string lock_path;
|
||||
std::string lock_message;
|
||||
Poco::Logger * log;
|
||||
|
||||
};
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
#include "ZooKeeperHolder.h"
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
using namespace zkutil;
|
||||
|
||||
ZooKeeperHolder::UnstorableZookeeperHandler ZooKeeperHolder::getZooKeeper()
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
return UnstorableZookeeperHandler(ptr);
|
||||
}
|
||||
|
||||
void ZooKeeperHolder::initFromInstance(const ZooKeeper::Ptr & zookeeper_ptr)
|
||||
{
|
||||
ptr = zookeeper_ptr;
|
||||
}
|
||||
|
||||
bool ZooKeeperHolder::replaceZooKeeperSessionToNewOne()
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
|
||||
if (ptr.unique())
|
||||
{
|
||||
ptr = ptr->startNewSession();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(log, "replaceZooKeeperSessionToNewOne(): Fail to replace zookeeper session to new one because handlers for old zookeeper session still exists.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ZooKeeperHolder::isSessionExpired() const
|
||||
{
|
||||
return ptr ? ptr->expired() : false;
|
||||
}
|
||||
|
||||
|
||||
std::string ZooKeeperHolder::nullptr_exception_message =
|
||||
"UnstorableZookeeperHandler::zk_ptr is nullptr. "
|
||||
"ZooKeeperHolder should be initialized before sending any request to ZooKeeper";
|
||||
|
||||
ZooKeeperHolder::UnstorableZookeeperHandler::UnstorableZookeeperHandler(ZooKeeper::Ptr zk_ptr_)
|
||||
: zk_ptr(zk_ptr_)
|
||||
{
|
||||
}
|
||||
|
||||
ZooKeeper * ZooKeeperHolder::UnstorableZookeeperHandler::operator->()
|
||||
{
|
||||
if (zk_ptr == nullptr)
|
||||
throw DB::Exception(nullptr_exception_message, DB::ErrorCodes::LOGICAL_ERROR);
|
||||
|
||||
return zk_ptr.get();
|
||||
}
|
||||
|
||||
const ZooKeeper * ZooKeeperHolder::UnstorableZookeeperHandler::operator->() const
|
||||
{
|
||||
if (zk_ptr == nullptr)
|
||||
throw DB::Exception(nullptr_exception_message, DB::ErrorCodes::LOGICAL_ERROR);
|
||||
return zk_ptr.get();
|
||||
}
|
||||
|
||||
ZooKeeper & ZooKeeperHolder::UnstorableZookeeperHandler::operator*()
|
||||
{
|
||||
if (zk_ptr == nullptr)
|
||||
throw DB::Exception(nullptr_exception_message, DB::ErrorCodes::LOGICAL_ERROR);
|
||||
return *zk_ptr;
|
||||
}
|
||||
|
||||
const ZooKeeper & ZooKeeperHolder::UnstorableZookeeperHandler::operator*() const
|
||||
{
|
||||
if (zk_ptr == nullptr)
|
||||
throw DB::Exception(nullptr_exception_message, DB::ErrorCodes::LOGICAL_ERROR);
|
||||
return *zk_ptr;
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "ZooKeeper.h"
|
||||
#include <mutex>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
namespace zkutil
|
||||
{
|
||||
class Lock;
|
||||
|
||||
class ZooKeeperHolder : public boost::noncopyable
|
||||
{
|
||||
friend class zkutil::Lock;
|
||||
|
||||
protected:
|
||||
class UnstorableZookeeperHandler;
|
||||
|
||||
public:
|
||||
ZooKeeperHolder() = default;
|
||||
|
||||
/// вызывать из одного потока - не thread safe
|
||||
template <typename... Args>
|
||||
void init(Args &&... args);
|
||||
/// был ли класс инициализирован
|
||||
bool isInitialized() const { return ptr != nullptr; }
|
||||
|
||||
/// Workaround for zkutil::Lock
|
||||
void initFromInstance(const ZooKeeper::Ptr & zookeeper_ptr);
|
||||
|
||||
UnstorableZookeeperHandler getZooKeeper();
|
||||
bool replaceZooKeeperSessionToNewOne();
|
||||
|
||||
bool isSessionExpired() const;
|
||||
|
||||
protected:
|
||||
/** Хендлер для подсчета количества используемых ссылок на ZooKeeper
|
||||
*
|
||||
* Запрещается переинициализировать ZooKeeper пока, хранится хотя бы один хендлер на него.
|
||||
* Большинство классов должны хранить хендлер на стеке и не хранить как член класса.
|
||||
* Т.е. хранить holder и запрашивать хендлер перед каждым использованием.
|
||||
* Поэтому класс специально объявлен, как protected.
|
||||
*
|
||||
* Исключение - классы, работающие с эфимерными нодами. Пример: zkutil::Lock
|
||||
*
|
||||
* Как использовать:
|
||||
* auto zookeeper = zookeeper_holder->getZooKeeper();
|
||||
* zookeeper->get(path);
|
||||
*/
|
||||
class UnstorableZookeeperHandler
|
||||
{
|
||||
public:
|
||||
UnstorableZookeeperHandler(ZooKeeper::Ptr zk_ptr_);
|
||||
|
||||
explicit operator bool() const { return bool(zk_ptr); }
|
||||
bool operator==(std::nullptr_t) const { return zk_ptr == nullptr; }
|
||||
bool operator!=(std::nullptr_t) const { return !(*this == nullptr); }
|
||||
|
||||
/// в случае nullptr методы разыменования кидают исключение,
|
||||
/// с более подробным текстом, чем просто nullptr
|
||||
ZooKeeper * operator->();
|
||||
const ZooKeeper * operator->() const;
|
||||
ZooKeeper & operator*();
|
||||
const ZooKeeper & operator*() const;
|
||||
|
||||
private:
|
||||
ZooKeeper::Ptr zk_ptr;
|
||||
};
|
||||
|
||||
private:
|
||||
mutable std::mutex mutex;
|
||||
ZooKeeper::Ptr ptr;
|
||||
|
||||
Poco::Logger * log = &Poco::Logger::get("ZooKeeperHolder");
|
||||
|
||||
static std::string nullptr_exception_message;
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
void ZooKeeperHolder::init(Args &&... args)
|
||||
{
|
||||
ptr = std::make_shared<ZooKeeper>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
using ZooKeeperHolderPtr = std::shared_ptr<ZooKeeperHolder>;
|
||||
|
||||
}
|
@ -4,18 +4,12 @@ target_link_libraries(zkutil_test_commands PRIVATE clickhouse_common_zookeeper)
|
||||
add_executable(zkutil_test_commands_new_lib zkutil_test_commands_new_lib.cpp)
|
||||
target_link_libraries(zkutil_test_commands_new_lib PRIVATE clickhouse_common_zookeeper string_utils)
|
||||
|
||||
add_executable(zkutil_test_lock zkutil_test_lock.cpp)
|
||||
target_link_libraries(zkutil_test_lock PRIVATE clickhouse_common_zookeeper)
|
||||
|
||||
add_executable(zkutil_expiration_test zkutil_expiration_test.cpp)
|
||||
target_link_libraries(zkutil_expiration_test PRIVATE clickhouse_common_zookeeper)
|
||||
|
||||
add_executable(zkutil_test_async zkutil_test_async.cpp)
|
||||
target_link_libraries(zkutil_test_async PRIVATE clickhouse_common_zookeeper)
|
||||
|
||||
add_executable(zkutil_zookeeper_holder zkutil_zookeeper_holder.cpp)
|
||||
target_link_libraries(zkutil_zookeeper_holder PRIVATE clickhouse_common_zookeeper)
|
||||
|
||||
add_executable (zk_many_watches_reconnect zk_many_watches_reconnect.cpp)
|
||||
target_link_libraries (zk_many_watches_reconnect PRIVATE clickhouse_common_zookeeper clickhouse_common_config)
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <Common/ZooKeeper/Lock.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
auto zookeeper_holder = std::make_shared<zkutil::ZooKeeperHolder>();
|
||||
zookeeper_holder->init("localhost:2181");
|
||||
|
||||
zkutil::Lock l(zookeeper_holder, "/test", "test_lock");
|
||||
std::cout << "check " << l.tryCheck() << std::endl;
|
||||
std::cout << "lock tryLock() " << l.tryLock() << std::endl;
|
||||
std::cout << "check " << l.tryCheck() << std::endl;
|
||||
}
|
||||
catch (const Poco::Exception & e)
|
||||
{
|
||||
std::cout << e.message() << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
#include <Common/ZooKeeper/ZooKeeperHolder.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <Poco/Util/Application.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
// Test::initLogger();
|
||||
|
||||
zkutil::ZooKeeperHolder zk_holder;
|
||||
zk_holder.init("localhost:2181");
|
||||
|
||||
{
|
||||
auto zk_handler = zk_holder.getZooKeeper();
|
||||
if (zk_handler)
|
||||
{
|
||||
bool started_new_session = zk_holder.replaceZooKeeperSessionToNewOne();
|
||||
std::cerr << "Started new session: " << started_new_session << "\n";
|
||||
std::cerr << "get / " << zk_handler->get("/") << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
bool started_new_session = zk_holder.replaceZooKeeperSessionToNewOne();
|
||||
std::cerr << "Started new session: " << started_new_session << "\n";
|
||||
auto zk_handler = zk_holder.getZooKeeper();
|
||||
if (zk_handler != nullptr)
|
||||
std::cerr << "get / " << zk_handler->get("/") << "\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -3,6 +3,7 @@
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
|
||||
#include <common/types.h>
|
||||
|
||||
// Also defined in Core/Defines.h
|
||||
#if !defined(NO_SANITIZE_UNDEFINED)
|
||||
@ -89,49 +90,136 @@ constexpr inline int64_t exp10_i64(int x)
|
||||
return values[x];
|
||||
}
|
||||
|
||||
constexpr inline __int128 exp10_i128(int x)
|
||||
constexpr inline Int128 exp10_i128(int x)
|
||||
{
|
||||
constexpr __int128 values[] =
|
||||
constexpr Int128 values[] =
|
||||
{
|
||||
static_cast<__int128>(1LL),
|
||||
static_cast<__int128>(10LL),
|
||||
static_cast<__int128>(100LL),
|
||||
static_cast<__int128>(1000LL),
|
||||
static_cast<__int128>(10000LL),
|
||||
static_cast<__int128>(100000LL),
|
||||
static_cast<__int128>(1000000LL),
|
||||
static_cast<__int128>(10000000LL),
|
||||
static_cast<__int128>(100000000LL),
|
||||
static_cast<__int128>(1000000000LL),
|
||||
static_cast<__int128>(10000000000LL),
|
||||
static_cast<__int128>(100000000000LL),
|
||||
static_cast<__int128>(1000000000000LL),
|
||||
static_cast<__int128>(10000000000000LL),
|
||||
static_cast<__int128>(100000000000000LL),
|
||||
static_cast<__int128>(1000000000000000LL),
|
||||
static_cast<__int128>(10000000000000000LL),
|
||||
static_cast<__int128>(100000000000000000LL),
|
||||
static_cast<__int128>(1000000000000000000LL),
|
||||
static_cast<__int128>(1000000000000000000LL) * 10LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 100LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 1000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 10000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 100000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 1000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 10000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 100000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 1000000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 10000000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 100000000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 1000000000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 10000000000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 100000000000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 1000000000000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 10000000000000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 10LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 100LL,
|
||||
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 1000LL
|
||||
static_cast<Int128>(1LL),
|
||||
static_cast<Int128>(10LL),
|
||||
static_cast<Int128>(100LL),
|
||||
static_cast<Int128>(1000LL),
|
||||
static_cast<Int128>(10000LL),
|
||||
static_cast<Int128>(100000LL),
|
||||
static_cast<Int128>(1000000LL),
|
||||
static_cast<Int128>(10000000LL),
|
||||
static_cast<Int128>(100000000LL),
|
||||
static_cast<Int128>(1000000000LL),
|
||||
static_cast<Int128>(10000000000LL),
|
||||
static_cast<Int128>(100000000000LL),
|
||||
static_cast<Int128>(1000000000000LL),
|
||||
static_cast<Int128>(10000000000000LL),
|
||||
static_cast<Int128>(100000000000000LL),
|
||||
static_cast<Int128>(1000000000000000LL),
|
||||
static_cast<Int128>(10000000000000000LL),
|
||||
static_cast<Int128>(100000000000000000LL),
|
||||
static_cast<Int128>(1000000000000000000LL),
|
||||
static_cast<Int128>(1000000000000000000LL) * 10LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 100LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 1000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 10000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 100000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 1000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 10000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 100000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 1000000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 10000000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 100000000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 1000000000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 10000000000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 100000000000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 1000000000000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 10000000000000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 100000000000000000LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 100000000000000000LL * 10LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 100000000000000000LL * 100LL,
|
||||
static_cast<Int128>(1000000000000000000LL) * 100000000000000000LL * 1000LL
|
||||
};
|
||||
return values[x];
|
||||
}
|
||||
|
||||
|
||||
inline bInt256 exp10_i256(int x)
|
||||
{
|
||||
using Int256 = bInt256;
|
||||
static constexpr Int256 i10e18{1000000000000000000ll};
|
||||
static const Int256 values[] = {
|
||||
static_cast<Int256>(1ll),
|
||||
static_cast<Int256>(10ll),
|
||||
static_cast<Int256>(100ll),
|
||||
static_cast<Int256>(1000ll),
|
||||
static_cast<Int256>(10000ll),
|
||||
static_cast<Int256>(100000ll),
|
||||
static_cast<Int256>(1000000ll),
|
||||
static_cast<Int256>(10000000ll),
|
||||
static_cast<Int256>(100000000ll),
|
||||
static_cast<Int256>(1000000000ll),
|
||||
static_cast<Int256>(10000000000ll),
|
||||
static_cast<Int256>(100000000000ll),
|
||||
static_cast<Int256>(1000000000000ll),
|
||||
static_cast<Int256>(10000000000000ll),
|
||||
static_cast<Int256>(100000000000000ll),
|
||||
static_cast<Int256>(1000000000000000ll),
|
||||
static_cast<Int256>(10000000000000000ll),
|
||||
static_cast<Int256>(100000000000000000ll),
|
||||
i10e18,
|
||||
i10e18 * 10ll,
|
||||
i10e18 * 100ll,
|
||||
i10e18 * 1000ll,
|
||||
i10e18 * 10000ll,
|
||||
i10e18 * 100000ll,
|
||||
i10e18 * 1000000ll,
|
||||
i10e18 * 10000000ll,
|
||||
i10e18 * 100000000ll,
|
||||
i10e18 * 1000000000ll,
|
||||
i10e18 * 10000000000ll,
|
||||
i10e18 * 100000000000ll,
|
||||
i10e18 * 1000000000000ll,
|
||||
i10e18 * 10000000000000ll,
|
||||
i10e18 * 100000000000000ll,
|
||||
i10e18 * 1000000000000000ll,
|
||||
i10e18 * 10000000000000000ll,
|
||||
i10e18 * 100000000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 10ll,
|
||||
i10e18 * 100000000000000000ll * 100ll,
|
||||
i10e18 * 100000000000000000ll * 1000ll,
|
||||
i10e18 * 100000000000000000ll * 10000ll,
|
||||
i10e18 * 100000000000000000ll * 100000ll,
|
||||
i10e18 * 100000000000000000ll * 1000000ll,
|
||||
i10e18 * 100000000000000000ll * 10000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000ll,
|
||||
i10e18 * 100000000000000000ll * 1000000000ll,
|
||||
i10e18 * 100000000000000000ll * 10000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000ll,
|
||||
i10e18 * 100000000000000000ll * 1000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 10000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 1000000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 10000000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 10ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 1000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 10000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 1000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 10000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 1000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 10000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 1000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 10000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 1000000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 10000000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000000000ll * 10ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000000000ll * 100ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000000000ll * 1000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000000000ll * 10000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000000000ll * 100000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000000000ll * 1000000ll,
|
||||
i10e18 * 100000000000000000ll * 100000000000000000ll * 100000000000000000ll * 10000000ll,
|
||||
};
|
||||
return values[x];
|
||||
}
|
||||
@ -145,6 +233,8 @@ constexpr inline T intExp10OfSize(int x)
|
||||
{
|
||||
if constexpr (sizeof(T) <= 8)
|
||||
return intExp10(x);
|
||||
else
|
||||
else if constexpr (sizeof(T) <= 16)
|
||||
return common::exp10_i128(x);
|
||||
else
|
||||
return common::exp10_i256(x);
|
||||
}
|
||||
|
@ -98,10 +98,8 @@ SRCS(
|
||||
UTF8Helpers.cpp
|
||||
WeakHash.cpp
|
||||
ZooKeeper/IKeeper.cpp
|
||||
ZooKeeper/Lock.cpp
|
||||
ZooKeeper/TestKeeper.cpp
|
||||
ZooKeeper/ZooKeeper.cpp
|
||||
ZooKeeper/ZooKeeperHolder.cpp
|
||||
ZooKeeper/ZooKeeperImpl.cpp
|
||||
ZooKeeper/ZooKeeperNodeCache.cpp
|
||||
|
||||
|
@ -698,7 +698,7 @@ auto SequentialGenerator = [](auto stride = 1)
|
||||
template <typename T>
|
||||
using uniform_distribution =
|
||||
typename std::conditional_t<std::is_floating_point_v<T>, std::uniform_real_distribution<T>,
|
||||
typename std::conditional_t<is_integral_v<T>, std::uniform_int_distribution<T>, void>>;
|
||||
typename std::conditional_t<is_integer_v<T>, std::uniform_int_distribution<T>, void>>;
|
||||
|
||||
|
||||
template <typename T = Int32>
|
||||
|
@ -35,10 +35,7 @@ using DB::UInt64;
|
||||
// Case 1. Is pair of floats or pair of ints or pair of uints
|
||||
template <typename A, typename B>
|
||||
constexpr bool is_safe_conversion = (std::is_floating_point_v<A> && std::is_floating_point_v<B>)
|
||||
|| (is_integral_v<A> && is_integral_v<B> && !(is_signed_v<A> ^ is_signed_v<B>))
|
||||
|| (std::is_same_v<A, DB::Int128> && std::is_same_v<B, DB::Int128>)
|
||||
|| (is_integral_v<A> && std::is_same_v<B, DB::Int128>)
|
||||
|| (std::is_same_v<A, DB::Int128> && is_integral_v<B>);
|
||||
|| (is_integer_v<A> && is_integer_v<B> && !(is_signed_v<A> ^ is_signed_v<B>));
|
||||
template <typename A, typename B>
|
||||
using bool_if_safe_conversion = std::enable_if_t<is_safe_conversion<A, B>, bool>;
|
||||
template <typename A, typename B>
|
||||
@ -48,13 +45,15 @@ using bool_if_not_safe_conversion = std::enable_if_t<!is_safe_conversion<A, B>,
|
||||
/// Case 2. Are params IntXX and UIntYY ?
|
||||
template <typename TInt, typename TUInt>
|
||||
constexpr bool is_any_int_vs_uint
|
||||
= is_integral_v<TInt> && is_integral_v<TUInt> && is_signed_v<TInt> && is_unsigned_v<TUInt>;
|
||||
|
||||
= is_integer_v<TInt> && is_integer_v<TUInt> && is_signed_v<TInt> && is_unsigned_v<TUInt>;
|
||||
|
||||
// Case 2a. Are params IntXX and UIntYY and sizeof(IntXX) >= sizeof(UIntYY) (in such case will use accurate compare)
|
||||
template <typename TInt, typename TUInt>
|
||||
constexpr bool is_le_int_vs_uint = is_any_int_vs_uint<TInt, TUInt> && (sizeof(TInt) <= sizeof(TUInt));
|
||||
|
||||
static_assert(is_le_int_vs_uint<Int128, DB::UInt128>);
|
||||
static_assert(is_le_int_vs_uint<Int128, bUInt256>);
|
||||
|
||||
template <typename TInt, typename TUInt>
|
||||
using bool_if_le_int_vs_uint_t = std::enable_if_t<is_le_int_vs_uint<TInt, TUInt>, bool>;
|
||||
|
||||
@ -93,32 +92,46 @@ using bool_if_gt_int_vs_uint = std::enable_if_t<is_gt_int_vs_uint<TInt, TUInt>,
|
||||
template <typename TInt, typename TUInt>
|
||||
inline bool_if_gt_int_vs_uint<TInt, TUInt> greaterOpTmpl(TInt a, TUInt b)
|
||||
{
|
||||
return static_cast<TInt>(a) > static_cast<TInt>(b);
|
||||
if constexpr (is_big_int_v<TInt> && std::is_same_v<TUInt, UInt8>)
|
||||
return static_cast<TInt>(a) > static_cast<TInt>(static_cast<UInt16>(b));
|
||||
else
|
||||
return static_cast<TInt>(a) > static_cast<TInt>(b);
|
||||
}
|
||||
|
||||
template <typename TInt, typename TUInt>
|
||||
inline bool_if_gt_int_vs_uint<TInt, TUInt> greaterOpTmpl(TUInt a, TInt b)
|
||||
{
|
||||
return static_cast<TInt>(a) > static_cast<TInt>(b);
|
||||
if constexpr (is_big_int_v<TInt> && std::is_same_v<TUInt, UInt8>)
|
||||
return static_cast<TInt>(static_cast<UInt16>(a)) > static_cast<TInt>(b);
|
||||
else if constexpr (is_big_int_v<TInt> && std::is_same_v<TUInt, DB::UInt128>)
|
||||
return static_cast<bUInt256>(a) > b;
|
||||
else
|
||||
return static_cast<TInt>(a) > b;
|
||||
}
|
||||
|
||||
template <typename TInt, typename TUInt>
|
||||
inline bool_if_gt_int_vs_uint<TInt, TUInt> equalsOpTmpl(TInt a, TUInt b)
|
||||
{
|
||||
return static_cast<TInt>(a) == static_cast<TInt>(b);
|
||||
if constexpr (is_big_int_v<TInt> && std::is_same_v<TUInt, UInt8>)
|
||||
return static_cast<TInt>(a) == static_cast<TInt>(static_cast<UInt16>(b));
|
||||
else
|
||||
return static_cast<TInt>(a) == static_cast<TInt>(b);
|
||||
}
|
||||
|
||||
template <typename TInt, typename TUInt>
|
||||
inline bool_if_gt_int_vs_uint<TInt, TUInt> equalsOpTmpl(TUInt a, TInt b)
|
||||
{
|
||||
return static_cast<TInt>(a) == static_cast<TInt>(b);
|
||||
if constexpr (is_big_int_v<TInt> && std::is_same_v<TUInt, UInt8>)
|
||||
return static_cast<TInt>(static_cast<UInt16>(a)) == static_cast<TInt>(b);
|
||||
else
|
||||
return static_cast<TInt>(a) == static_cast<TInt>(b);
|
||||
}
|
||||
|
||||
|
||||
// Case 3a. Comparison via conversion to double.
|
||||
template <typename TAInt, typename TAFloat>
|
||||
using bool_if_double_can_be_used
|
||||
= std::enable_if_t<is_integral_v<TAInt> && (sizeof(TAInt) <= 4) && std::is_floating_point_v<TAFloat>, bool>;
|
||||
= std::enable_if_t<is_integer_v<TAInt> && (sizeof(TAInt) <= 4) && std::is_floating_point_v<TAFloat>, bool>;
|
||||
|
||||
template <typename TAInt, typename TAFloat>
|
||||
inline bool_if_double_can_be_used<TAInt, TAFloat> greaterOpTmpl(TAInt a, TAFloat b)
|
||||
@ -144,6 +157,37 @@ inline bool_if_double_can_be_used<TAInt, TAFloat> equalsOpTmpl(TAFloat a, TAInt
|
||||
return static_cast<double>(a) == static_cast<double>(b);
|
||||
}
|
||||
|
||||
// Big integers vs Float (not equal in any case for now, until big floats are introduced?)
|
||||
template <typename TABigInt, typename TAFloat>
|
||||
constexpr bool if_big_int_vs_float = (is_big_int_v<TABigInt> && std::is_floating_point_v<TAFloat>);
|
||||
|
||||
template <typename TABigInt, typename TAFloat>
|
||||
using bool_if_big_int_vs_float = std::enable_if_t<if_big_int_vs_float<TABigInt, TAFloat>, bool>;
|
||||
|
||||
template <typename TABigInt, typename TAFloat>
|
||||
inline bool_if_big_int_vs_float<TABigInt, TAFloat> greaterOpTmpl(TAFloat, TABigInt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TABigInt, typename TAFloat>
|
||||
inline bool_if_big_int_vs_float<TABigInt, TAFloat> greaterOpTmpl(TABigInt, TAFloat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TABigInt, typename TAFloat>
|
||||
inline bool_if_big_int_vs_float<TABigInt, TAFloat> equalsOpTmpl(TAFloat, TABigInt)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TABigInt, typename TAFloat>
|
||||
inline bool_if_big_int_vs_float<TABigInt, TAFloat> equalsOpTmpl(TABigInt, TAFloat)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Final realiztions */
|
||||
|
||||
|
||||
@ -156,7 +200,18 @@ inline bool_if_not_safe_conversion<A, B> greaterOp(A a, B b)
|
||||
template <typename A, typename B>
|
||||
inline bool_if_safe_conversion<A, B> greaterOp(A a, B b)
|
||||
{
|
||||
return a > b;
|
||||
if constexpr (is_big_int_v<A> && std::is_same_v<B, UInt8>)
|
||||
return a > static_cast<UInt16>(b);
|
||||
else if constexpr (is_big_int_v<B> && std::is_same_v<A, UInt8>)
|
||||
return static_cast<UInt16>(a) > b;
|
||||
else if constexpr (std::is_same_v<A, DB::UInt128> && is_big_int_v<B>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return static_cast<B>(a) > b;
|
||||
else if constexpr (std::is_same_v<B, DB::UInt128> && is_big_int_v<A>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return a > static_cast<A>(b);
|
||||
else
|
||||
return a > b;
|
||||
}
|
||||
|
||||
// Case 3b. 64-bit integers vs floats comparison.
|
||||
@ -263,7 +318,16 @@ template <typename A, typename B>
|
||||
inline bool_if_safe_conversion<A, B> equalsOp(A a, B b)
|
||||
{
|
||||
using LargestType = std::conditional_t<sizeof(A) >= sizeof(B), A, B>;
|
||||
return static_cast<LargestType>(a) == static_cast<LargestType>(b);
|
||||
|
||||
if constexpr (is_big_int_v<LargestType> && std::is_same_v<A, UInt8>)
|
||||
return static_cast<LargestType>(static_cast<UInt16>(a)) == static_cast<LargestType>(b);
|
||||
else if constexpr (is_big_int_v<LargestType> && std::is_same_v<B, UInt8>)
|
||||
return static_cast<LargestType>(a) == static_cast<LargestType>(static_cast<UInt16>(b));
|
||||
else if constexpr (std::is_same_v<LargestType, DB::UInt128> && is_big_int_v<B>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return static_cast<B>(a) == static_cast<B>(b);
|
||||
else
|
||||
return static_cast<LargestType>(a) == static_cast<LargestType>(b);
|
||||
}
|
||||
|
||||
template <>
|
||||
@ -340,8 +404,8 @@ inline bool equalsOp<DB::Float32, DB::UInt128>(DB::Float32 f, DB::UInt128 u)
|
||||
|
||||
inline bool NO_SANITIZE_UNDEFINED greaterOp(DB::Int128 i, DB::Float64 f)
|
||||
{
|
||||
static constexpr __int128 min_int128 = __int128(0x8000000000000000ll) << 64;
|
||||
static constexpr __int128 max_int128 = (__int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll;
|
||||
static constexpr Int128 min_int128 = Int128(0x8000000000000000ll) << 64;
|
||||
static constexpr Int128 max_int128 = (Int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll;
|
||||
|
||||
if (-MAX_INT64_WITH_EXACT_FLOAT64_REPR <= i && i <= MAX_INT64_WITH_EXACT_FLOAT64_REPR)
|
||||
return static_cast<DB::Float64>(i) > f;
|
||||
@ -352,8 +416,8 @@ inline bool NO_SANITIZE_UNDEFINED greaterOp(DB::Int128 i, DB::Float64 f)
|
||||
|
||||
inline bool NO_SANITIZE_UNDEFINED greaterOp(DB::Float64 f, DB::Int128 i)
|
||||
{
|
||||
static constexpr __int128 min_int128 = __int128(0x8000000000000000ll) << 64;
|
||||
static constexpr __int128 max_int128 = (__int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll;
|
||||
static constexpr Int128 min_int128 = Int128(0x8000000000000000ll) << 64;
|
||||
static constexpr Int128 max_int128 = (Int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll;
|
||||
|
||||
if (-MAX_INT64_WITH_EXACT_FLOAT64_REPR <= i && i <= MAX_INT64_WITH_EXACT_FLOAT64_REPR)
|
||||
return f > static_cast<DB::Float64>(i);
|
||||
@ -379,7 +443,18 @@ inline bool_if_not_safe_conversion<A, B> notEqualsOp(A a, B b)
|
||||
template <typename A, typename B>
|
||||
inline bool_if_safe_conversion<A, B> notEqualsOp(A a, B b)
|
||||
{
|
||||
return a != b;
|
||||
if constexpr (std::is_same_v<A, UInt8> && is_big_int_v<B>)
|
||||
return static_cast<UInt16>(a) != b;
|
||||
else if constexpr (std::is_same_v<B, UInt8> && is_big_int_v<A>)
|
||||
return a != static_cast<UInt16>(b);
|
||||
else if constexpr (std::is_same_v<A, DB::UInt128> && is_big_int_v<B>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return static_cast<B>(a) != b;
|
||||
else if constexpr (std::is_same_v<B, DB::UInt128> && is_big_int_v<A>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return a != static_cast<A>(b);
|
||||
else
|
||||
return a != b;
|
||||
}
|
||||
|
||||
|
||||
@ -392,7 +467,18 @@ inline bool_if_not_safe_conversion<A, B> lessOp(A a, B b)
|
||||
template <typename A, typename B>
|
||||
inline bool_if_safe_conversion<A, B> lessOp(A a, B b)
|
||||
{
|
||||
return a < b;
|
||||
if constexpr (std::is_same_v<A, UInt8> && is_big_int_v<B>)
|
||||
return static_cast<UInt16>(a) < b;
|
||||
else if constexpr (std::is_same_v<B, UInt8> && is_big_int_v<A>)
|
||||
return a < static_cast<UInt16>(b);
|
||||
else if constexpr (std::is_same_v<A, DB::UInt128> && is_big_int_v<B>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return static_cast<B>(a) < b;
|
||||
else if constexpr (std::is_same_v<B, DB::UInt128> && is_big_int_v<A>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return a < static_cast<A>(b);
|
||||
else
|
||||
return a < b;
|
||||
}
|
||||
|
||||
|
||||
@ -407,7 +493,18 @@ inline bool_if_not_safe_conversion<A, B> lessOrEqualsOp(A a, B b)
|
||||
template <typename A, typename B>
|
||||
inline bool_if_safe_conversion<A, B> lessOrEqualsOp(A a, B b)
|
||||
{
|
||||
return a <= b;
|
||||
if constexpr (std::is_same_v<A, UInt8> && is_big_int_v<B>)
|
||||
return static_cast<UInt16>(a) <= b;
|
||||
else if constexpr (std::is_same_v<B, UInt8> && is_big_int_v<A>)
|
||||
return a <= static_cast<UInt16>(b);
|
||||
else if constexpr (std::is_same_v<A, DB::UInt128> && is_big_int_v<B>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return static_cast<B>(a) <= b;
|
||||
else if constexpr (std::is_same_v<B, DB::UInt128> && is_big_int_v<A>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return a <= static_cast<A>(b);
|
||||
else
|
||||
return a <= b;
|
||||
}
|
||||
|
||||
|
||||
@ -422,7 +519,18 @@ inline bool_if_not_safe_conversion<A, B> greaterOrEqualsOp(A a, B b)
|
||||
template <typename A, typename B>
|
||||
inline bool_if_safe_conversion<A, B> greaterOrEqualsOp(A a, B b)
|
||||
{
|
||||
return a >= b;
|
||||
if constexpr (std::is_same_v<A, UInt8> && is_big_int_v<B>)
|
||||
return static_cast<UInt16>(a) >= b;
|
||||
else if constexpr (std::is_same_v<B, UInt8> && is_big_int_v<A>)
|
||||
return a >= static_cast<UInt16>(b);
|
||||
else if constexpr (std::is_same_v<A, DB::UInt128> && is_big_int_v<B>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return static_cast<B>(a) >= b;
|
||||
else if constexpr (std::is_same_v<B, DB::UInt128> && is_big_int_v<A>)
|
||||
// hack for UInt128 and bUInt128
|
||||
return a >= static_cast<A>(b);
|
||||
else
|
||||
return a >= b;
|
||||
}
|
||||
|
||||
/// Converts numeric to an equal numeric of other type.
|
||||
|
83
src/Core/BigInt.h
Normal file
83
src/Core/BigInt.h
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/StringRef.h>
|
||||
#include <Core/Types.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
struct BigIntPayload
|
||||
{
|
||||
static_assert(!is_big_int_v<T>);
|
||||
static constexpr size_t size = 0;
|
||||
};
|
||||
|
||||
template <> struct BigIntPayload<bUInt256> { static constexpr size_t size = 32; };
|
||||
|
||||
template <> struct BigIntPayload<bInt256>
|
||||
{
|
||||
using UnsingedType = bUInt256;
|
||||
static constexpr size_t size = 32;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct BigInt : BigIntPayload<T>
|
||||
{
|
||||
using BigIntPayload<T>::size;
|
||||
|
||||
static constexpr size_t lastBit()
|
||||
{
|
||||
return size * 8 - 1;
|
||||
}
|
||||
|
||||
static StringRef serialize(const T & x, char * pos)
|
||||
{
|
||||
if constexpr (is_signed_v<T>)
|
||||
{
|
||||
using UnsignedT = typename BigIntPayload<T>::UnsingedType;
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
UnsignedT unsigned_x = UnsignedT{0} - static_cast<UnsignedT>(-x);
|
||||
export_bits(unsigned_x, pos, 8, false);
|
||||
}
|
||||
else
|
||||
export_bits(x, pos, 8, false);
|
||||
}
|
||||
else
|
||||
export_bits(x, pos, 8, false);
|
||||
return StringRef(pos, size);
|
||||
}
|
||||
|
||||
static String serialize(const T & x)
|
||||
{
|
||||
String str(size, '\0');
|
||||
serialize(x, str.data());
|
||||
return str;
|
||||
}
|
||||
|
||||
static T deserialize(const char * pos)
|
||||
{
|
||||
if constexpr (is_signed_v<T>)
|
||||
{
|
||||
using UnsignedT = typename BigIntPayload<T>::UnsingedType;
|
||||
|
||||
UnsignedT unsigned_x;
|
||||
import_bits(unsigned_x, pos, pos + size, false);
|
||||
|
||||
bool is_negative = bit_test(unsigned_x, lastBit());
|
||||
if (is_negative)
|
||||
unsigned_x = UnsignedT{0} - unsigned_x;
|
||||
return static_cast<T>(unsigned_x);
|
||||
}
|
||||
else
|
||||
{
|
||||
T x;
|
||||
import_bits(x, pos, pos + size, false);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@ -37,6 +37,7 @@ inline bool allowDecimalComparison(const DataTypePtr & left_type, const DataType
|
||||
template <size_t > struct ConstructDecInt { using Type = Int32; };
|
||||
template <> struct ConstructDecInt<8> { using Type = Int64; };
|
||||
template <> struct ConstructDecInt<16> { using Type = Int128; };
|
||||
template <> struct ConstructDecInt<48> { using Type = bInt256; };
|
||||
|
||||
template <typename T, typename U>
|
||||
struct DecCompareInt
|
||||
@ -84,15 +85,15 @@ public:
|
||||
|
||||
static bool compare(A a, B b, UInt32 scale_a, UInt32 scale_b)
|
||||
{
|
||||
static const UInt32 max_scale = DecimalUtils::maxPrecision<Decimal128>();
|
||||
static const UInt32 max_scale = DecimalUtils::maxPrecision<Decimal256>();
|
||||
if (scale_a > max_scale || scale_b > max_scale)
|
||||
throw Exception("Bad scale of decimal field", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
|
||||
Shift shift;
|
||||
if (scale_a < scale_b)
|
||||
shift.a = B::getScaleMultiplier(scale_b - scale_a);
|
||||
shift.a = static_cast<CompareInt>(DecimalUtils::scaleMultiplier<B>(scale_b - scale_a));
|
||||
if (scale_a > scale_b)
|
||||
shift.b = A::getScaleMultiplier(scale_a - scale_b);
|
||||
shift.b = static_cast<CompareInt>(DecimalUtils::scaleMultiplier<A>(scale_a - scale_b));
|
||||
|
||||
return applyWithScale(a, b, shift);
|
||||
}
|
||||
@ -129,13 +130,13 @@ private:
|
||||
if (decimal0 && decimal1)
|
||||
{
|
||||
auto result_type = decimalResultType(*decimal0, *decimal1, false, false);
|
||||
shift.a = result_type.scaleFactorFor(*decimal0, false);
|
||||
shift.b = result_type.scaleFactorFor(*decimal1, false);
|
||||
shift.a = static_cast<CompareInt>(result_type.scaleFactorFor(*decimal0, false).value);
|
||||
shift.b = static_cast<CompareInt>(result_type.scaleFactorFor(*decimal1, false).value);
|
||||
}
|
||||
else if (decimal0)
|
||||
shift.b = decimal0->getScaleMultiplier();
|
||||
shift.b = static_cast<CompareInt>(decimal0->getScaleMultiplier().value);
|
||||
else if (decimal1)
|
||||
shift.a = decimal1->getScaleMultiplier();
|
||||
shift.a = static_cast<CompareInt>(decimal1->getScaleMultiplier().value);
|
||||
|
||||
return shift;
|
||||
}
|
||||
@ -147,7 +148,7 @@ private:
|
||||
Shift shift;
|
||||
const DataTypeDecimal<T> * decimal0 = checkDecimal<T>(*left_type);
|
||||
if (decimal0)
|
||||
shift.b = decimal0->getScaleMultiplier();
|
||||
shift.b = static_cast<CompareInt>(decimal0->getScaleMultiplier().value);
|
||||
return shift;
|
||||
}
|
||||
|
||||
@ -158,7 +159,7 @@ private:
|
||||
Shift shift;
|
||||
const DataTypeDecimal<U> * decimal1 = checkDecimal<U>(*right_type);
|
||||
if (decimal1)
|
||||
shift.a = decimal1->getScaleMultiplier();
|
||||
shift.a = static_cast<CompareInt>(decimal1->getScaleMultiplier().value);
|
||||
return shift;
|
||||
}
|
||||
|
||||
@ -224,8 +225,21 @@ private:
|
||||
template <bool scale_left, bool scale_right>
|
||||
static NO_INLINE UInt8 apply(A a, B b, CompareInt scale [[maybe_unused]])
|
||||
{
|
||||
CompareInt x = a;
|
||||
CompareInt y = b;
|
||||
CompareInt x;
|
||||
if constexpr (is_big_int_v<CompareInt> && IsDecimalNumber<A>)
|
||||
x = a.value;
|
||||
else if constexpr (is_big_int_v<CompareInt> && std::is_same_v<A, UInt8>)
|
||||
x = static_cast<UInt16>(a);
|
||||
else
|
||||
x = static_cast<CompareInt>(a);
|
||||
|
||||
CompareInt y;
|
||||
if constexpr (is_big_int_v<CompareInt> && IsDecimalNumber<B>)
|
||||
y = b.value;
|
||||
else if constexpr (is_big_int_v<CompareInt> && std::is_same_v<B, UInt8>)
|
||||
y = static_cast<UInt16>(b);
|
||||
else
|
||||
y = static_cast<CompareInt>(b);
|
||||
|
||||
if constexpr (_check_overflow)
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <Core/Types.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <Common/intExp.h>
|
||||
#include <common/arithmeticOverflow.h>
|
||||
|
||||
#include <limits>
|
||||
@ -24,11 +25,21 @@ template <typename T> static constexpr size_t maxPrecision() { return 0; }
|
||||
template <> constexpr size_t maxPrecision<Decimal32>() { return 9; }
|
||||
template <> constexpr size_t maxPrecision<Decimal64>() { return 18; }
|
||||
template <> constexpr size_t maxPrecision<Decimal128>() { return 38; }
|
||||
template <> constexpr size_t maxPrecision<Decimal256>() { return 76; }
|
||||
|
||||
template <typename T>
|
||||
inline auto scaleMultiplier(UInt32 scale)
|
||||
{
|
||||
if constexpr (std::is_same_v<T, Int32> || std::is_same_v<T, Decimal32>)
|
||||
return common::exp10_i32(scale);
|
||||
else if constexpr (std::is_same_v<T, Int64> || std::is_same_v<T, Decimal64>)
|
||||
return common::exp10_i64(scale);
|
||||
else if constexpr (std::is_same_v<T, Int128> || std::is_same_v<T, Decimal128>)
|
||||
return common::exp10_i128(scale);
|
||||
else if constexpr (std::is_same_v<T, bInt256> || std::is_same_v<T, Decimal256>)
|
||||
return common::exp10_i256(scale);
|
||||
}
|
||||
|
||||
template <typename T> T scaleMultiplier(UInt32 scale);
|
||||
template <> inline Int32 scaleMultiplier<Int32>(UInt32 scale) { return common::exp10_i32(scale); }
|
||||
template <> inline Int64 scaleMultiplier<Int64>(UInt32 scale) { return common::exp10_i64(scale); }
|
||||
template <> inline Int128 scaleMultiplier<Int128>(UInt32 scale) { return common::exp10_i128(scale); }
|
||||
|
||||
/** Components of DecimalX value:
|
||||
* whole - represents whole part of decimal, can be negative or positive.
|
||||
@ -164,6 +175,41 @@ inline typename DecimalType::NativeType getFractionalPart(const DecimalType & de
|
||||
return getFractionalPartWithScaleMultiplier(decimal, scaleMultiplier<typename DecimalType::NativeType>(scale));
|
||||
}
|
||||
|
||||
/// Decimal to integer/float conversion
|
||||
template <typename To, typename DecimalType>
|
||||
To convertTo(const DecimalType & decimal, size_t scale)
|
||||
{
|
||||
using NativeT = typename DecimalType::NativeType;
|
||||
|
||||
if constexpr (std::is_floating_point_v<To>)
|
||||
{
|
||||
return static_cast<To>(decimal.value) / static_cast<To>(scaleMultiplier<NativeT>(scale));
|
||||
}
|
||||
else if constexpr (is_integer_v<To> && (sizeof(To) >= sizeof(NativeT)))
|
||||
{
|
||||
NativeT whole = getWholePart(decimal, scale);
|
||||
|
||||
if constexpr (is_unsigned_v<To>)
|
||||
if (whole < 0)
|
||||
throw Exception("Convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
return static_cast<To>(whole);
|
||||
}
|
||||
else if constexpr (is_integer_v<To>)
|
||||
{
|
||||
using ToNativeT = typename NativeType<To>::Type;
|
||||
using CastTo = std::conditional_t<(is_big_int_v<NativeT> && std::is_same_v<ToNativeT, UInt8>), uint8_t, ToNativeT>;
|
||||
|
||||
const NativeT whole = getWholePart(decimal, scale);
|
||||
|
||||
static const constexpr CastTo min_to = std::numeric_limits<ToNativeT>::min();
|
||||
static const constexpr CastTo max_to = std::numeric_limits<ToNativeT>::max();
|
||||
|
||||
if (whole < min_to || whole > max_to)
|
||||
throw Exception("Convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
return static_cast<CastTo>(whole);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -197,6 +197,13 @@ void readBinary(Tuple & x, ReadBuffer & buf)
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Int128:
|
||||
{
|
||||
Int64 value;
|
||||
DB::readVarInt(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Float64:
|
||||
{
|
||||
Float64 value;
|
||||
@ -211,6 +218,20 @@ void readBinary(Tuple & x, ReadBuffer & buf)
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::bUInt256:
|
||||
{
|
||||
bUInt256 value;
|
||||
DB::readBinary(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::bInt256:
|
||||
{
|
||||
bInt256 value;
|
||||
DB::readBinary(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Array:
|
||||
{
|
||||
Array value;
|
||||
@ -265,6 +286,11 @@ void writeBinary(const Tuple & x, WriteBuffer & buf)
|
||||
DB::writeVarInt(get<Int64>(elem), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Int128:
|
||||
{
|
||||
DB::writeVarInt(get<Int64>(elem), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Float64:
|
||||
{
|
||||
DB::writeFloatBinary(get<Float64>(elem), buf);
|
||||
@ -275,6 +301,16 @@ void writeBinary(const Tuple & x, WriteBuffer & buf)
|
||||
DB::writeStringBinary(get<std::string>(elem), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::bUInt256:
|
||||
{
|
||||
DB::writeBinary(get<bUInt256>(elem), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::bInt256:
|
||||
{
|
||||
DB::writeBinary(get<bInt256>(elem), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Array:
|
||||
{
|
||||
DB::writeBinary(get<Array>(elem), buf);
|
||||
@ -312,7 +348,7 @@ void readQuoted(DecimalField<T> & x, ReadBuffer & buf)
|
||||
if (exponent > 0)
|
||||
{
|
||||
scale = 0;
|
||||
if (common::mulOverflow(value.value, T::getScaleMultiplier(exponent), value.value))
|
||||
if (common::mulOverflow(value.value, DecimalUtils::scaleMultiplier<T>(exponent), value.value))
|
||||
throw Exception("Decimal math overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
}
|
||||
else
|
||||
@ -324,7 +360,7 @@ void readQuoted(DecimalField<T> & x, ReadBuffer & buf)
|
||||
template void readQuoted<Decimal32>(DecimalField<Decimal32> & x, ReadBuffer & buf);
|
||||
template void readQuoted<Decimal64>(DecimalField<Decimal64> & x, ReadBuffer & buf);
|
||||
template void readQuoted<Decimal128>(DecimalField<Decimal128> & x, ReadBuffer & buf);
|
||||
|
||||
template void readQuoted<Decimal256>(DecimalField<Decimal256> & x, ReadBuffer & buf);
|
||||
|
||||
void writeFieldText(const Field & x, WriteBuffer & buf)
|
||||
{
|
||||
@ -365,6 +401,27 @@ Field Field::restoreFromDump(const std::string_view & dump_)
|
||||
return value;
|
||||
}
|
||||
|
||||
prefix = std::string_view{"Int128_"};
|
||||
if (dump.starts_with(prefix))
|
||||
{
|
||||
Int128 value = parseFromString<Int128>(dump.substr(prefix.length()));
|
||||
return value;
|
||||
}
|
||||
|
||||
prefix = std::string_view{"Int256_"};
|
||||
if (dump.starts_with(prefix))
|
||||
{
|
||||
bInt256 value = parseFromString<bInt256>(dump.substr(prefix.length()));
|
||||
return value;
|
||||
}
|
||||
|
||||
prefix = std::string_view{"UInt256_"};
|
||||
if (dump.starts_with(prefix))
|
||||
{
|
||||
bUInt256 value = parseFromString<bUInt256>(dump.substr(prefix.length()));
|
||||
return value;
|
||||
}
|
||||
|
||||
prefix = std::string_view{"Float64_"};
|
||||
if (dump.starts_with(prefix))
|
||||
{
|
||||
@ -399,6 +456,15 @@ Field Field::restoreFromDump(const std::string_view & dump_)
|
||||
return decimal;
|
||||
}
|
||||
|
||||
prefix = std::string_view{"Decimal256_"};
|
||||
if (dump_.starts_with(prefix))
|
||||
{
|
||||
DecimalField<Decimal256> decimal;
|
||||
ReadBufferFromString buf{dump.substr(prefix.length())};
|
||||
readQuoted(decimal, buf);
|
||||
return decimal;
|
||||
}
|
||||
|
||||
prefix = std::string_view{"UUID_"};
|
||||
if (dump.starts_with(prefix))
|
||||
{
|
||||
@ -522,6 +588,10 @@ template <> bool decimalEqual(Decimal128 x, Decimal128 y, UInt32 x_scale, UInt32
|
||||
template <> bool decimalLess(Decimal128 x, Decimal128 y, UInt32 x_scale, UInt32 y_scale) { return decLess(x, y, x_scale, y_scale); }
|
||||
template <> bool decimalLessOrEqual(Decimal128 x, Decimal128 y, UInt32 x_scale, UInt32 y_scale) { return decLessOrEqual(x, y, x_scale, y_scale); }
|
||||
|
||||
template <> bool decimalEqual(Decimal256 x, Decimal256 y, UInt32 x_scale, UInt32 y_scale) { return decEqual(x, y, x_scale, y_scale); }
|
||||
template <> bool decimalLess(Decimal256 x, Decimal256 y, UInt32 x_scale, UInt32 y_scale) { return decLess(x, y, x_scale, y_scale); }
|
||||
template <> bool decimalLessOrEqual(Decimal256 x, Decimal256 y, UInt32 x_scale, UInt32 y_scale) { return decLessOrEqual(x, y, x_scale, y_scale); }
|
||||
|
||||
inline void writeText(const Null &, WriteBuffer & buf)
|
||||
{
|
||||
writeText(std::string("Null"), buf);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <Common/UInt128.h>
|
||||
#include <Core/Types.h>
|
||||
#include <Core/Defines.h>
|
||||
#include <Core/DecimalFunctions.h>
|
||||
#include <Core/UUID.h>
|
||||
#include <common/DayNum.h>
|
||||
#include <common/strong_typedef.h>
|
||||
@ -91,18 +92,22 @@ template <typename T> bool decimalEqual(T x, T y, UInt32 x_scale, UInt32 y_scale
|
||||
template <typename T> bool decimalLess(T x, T y, UInt32 x_scale, UInt32 y_scale);
|
||||
template <typename T> bool decimalLessOrEqual(T x, T y, UInt32 x_scale, UInt32 y_scale);
|
||||
|
||||
#if !__clang__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
template <typename T>
|
||||
class DecimalField
|
||||
{
|
||||
public:
|
||||
DecimalField(T value = 0, UInt32 scale_ = 0)
|
||||
DecimalField(T value = {}, UInt32 scale_ = 0)
|
||||
: dec(value),
|
||||
scale(scale_)
|
||||
{}
|
||||
|
||||
operator T() const { return dec; }
|
||||
T getValue() const { return dec; }
|
||||
T getScaleMultiplier() const { return T::getScaleMultiplier(scale); }
|
||||
T getScaleMultiplier() const { return DecimalUtils::scaleMultiplier<T>(scale); }
|
||||
UInt32 getScale() const { return scale; }
|
||||
|
||||
template <typename U>
|
||||
@ -150,6 +155,9 @@ private:
|
||||
T dec;
|
||||
UInt32 scale;
|
||||
};
|
||||
#if !__clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
/// char may be signed or unsigned, and behave identically to signed char or unsigned char,
|
||||
/// but they are always three different types.
|
||||
@ -177,13 +185,18 @@ template <> struct NearestFieldTypeImpl<long long> { using Type = Int64; };
|
||||
template <> struct NearestFieldTypeImpl<unsigned long> { using Type = UInt64; };
|
||||
template <> struct NearestFieldTypeImpl<unsigned long long> { using Type = UInt64; };
|
||||
|
||||
template <> struct NearestFieldTypeImpl<bUInt256> { using Type = bUInt256; };
|
||||
template <> struct NearestFieldTypeImpl<bInt256> { using Type = bInt256; };
|
||||
|
||||
template <> struct NearestFieldTypeImpl<Int128> { using Type = Int128; };
|
||||
template <> struct NearestFieldTypeImpl<Decimal32> { using Type = DecimalField<Decimal32>; };
|
||||
template <> struct NearestFieldTypeImpl<Decimal64> { using Type = DecimalField<Decimal64>; };
|
||||
template <> struct NearestFieldTypeImpl<Decimal128> { using Type = DecimalField<Decimal128>; };
|
||||
template <> struct NearestFieldTypeImpl<Decimal256> { using Type = DecimalField<Decimal256>; };
|
||||
template <> struct NearestFieldTypeImpl<DecimalField<Decimal32>> { using Type = DecimalField<Decimal32>; };
|
||||
template <> struct NearestFieldTypeImpl<DecimalField<Decimal64>> { using Type = DecimalField<Decimal64>; };
|
||||
template <> struct NearestFieldTypeImpl<DecimalField<Decimal128>> { using Type = DecimalField<Decimal128>; };
|
||||
template <> struct NearestFieldTypeImpl<DecimalField<Decimal256>> { using Type = DecimalField<Decimal256>; };
|
||||
template <> struct NearestFieldTypeImpl<Float32> { using Type = Float64; };
|
||||
template <> struct NearestFieldTypeImpl<Float64> { using Type = Float64; };
|
||||
template <> struct NearestFieldTypeImpl<const char *> { using Type = String; };
|
||||
@ -241,6 +254,9 @@ public:
|
||||
Decimal64 = 20,
|
||||
Decimal128 = 21,
|
||||
AggregateFunctionState = 22,
|
||||
Decimal256 = 23,
|
||||
bUInt256 = 24,
|
||||
bInt256 = 25,
|
||||
};
|
||||
|
||||
static const int MIN_NON_POD = 16;
|
||||
@ -261,7 +277,10 @@ public:
|
||||
case Decimal32: return "Decimal32";
|
||||
case Decimal64: return "Decimal64";
|
||||
case Decimal128: return "Decimal128";
|
||||
case Decimal256: return "Decimal256";
|
||||
case AggregateFunctionState: return "AggregateFunctionState";
|
||||
case bUInt256: return "UInt256";
|
||||
case bInt256: return "Int256";
|
||||
}
|
||||
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
@ -273,6 +292,10 @@ public:
|
||||
template <typename T> struct TypeToEnum;
|
||||
template <Types::Which which> struct EnumToType;
|
||||
|
||||
static bool IsDecimal(Types::Which which)
|
||||
{
|
||||
return (which >= Types::Decimal32 && which <= Types::Decimal128) || which == Types::Decimal256;
|
||||
}
|
||||
|
||||
/// Templates to avoid ambiguity.
|
||||
template <typename T, typename Z = void *>
|
||||
@ -442,7 +465,10 @@ public:
|
||||
case Types::Decimal32: return get<DecimalField<Decimal32>>() < rhs.get<DecimalField<Decimal32>>();
|
||||
case Types::Decimal64: return get<DecimalField<Decimal64>>() < rhs.get<DecimalField<Decimal64>>();
|
||||
case Types::Decimal128: return get<DecimalField<Decimal128>>() < rhs.get<DecimalField<Decimal128>>();
|
||||
case Types::Decimal256: return get<DecimalField<Decimal256>>() < rhs.get<DecimalField<Decimal256>>();
|
||||
case Types::AggregateFunctionState: return get<AggregateFunctionStateData>() < rhs.get<AggregateFunctionStateData>();
|
||||
case Types::bUInt256: return get<bUInt256>() < rhs.get<bUInt256>();
|
||||
case Types::bInt256: return get<bInt256>() < rhs.get<bInt256>();
|
||||
}
|
||||
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
@ -474,7 +500,10 @@ public:
|
||||
case Types::Decimal32: return get<DecimalField<Decimal32>>() <= rhs.get<DecimalField<Decimal32>>();
|
||||
case Types::Decimal64: return get<DecimalField<Decimal64>>() <= rhs.get<DecimalField<Decimal64>>();
|
||||
case Types::Decimal128: return get<DecimalField<Decimal128>>() <= rhs.get<DecimalField<Decimal128>>();
|
||||
case Types::Decimal256: return get<DecimalField<Decimal256>>() <= rhs.get<DecimalField<Decimal256>>();
|
||||
case Types::AggregateFunctionState: return get<AggregateFunctionStateData>() <= rhs.get<AggregateFunctionStateData>();
|
||||
case Types::bUInt256: return get<bUInt256>() <= rhs.get<bUInt256>();
|
||||
case Types::bInt256: return get<bInt256>() <= rhs.get<bInt256>();
|
||||
}
|
||||
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
@ -510,7 +539,10 @@ public:
|
||||
case Types::Decimal32: return get<DecimalField<Decimal32>>() == rhs.get<DecimalField<Decimal32>>();
|
||||
case Types::Decimal64: return get<DecimalField<Decimal64>>() == rhs.get<DecimalField<Decimal64>>();
|
||||
case Types::Decimal128: return get<DecimalField<Decimal128>>() == rhs.get<DecimalField<Decimal128>>();
|
||||
case Types::Decimal256: return get<DecimalField<Decimal256>>() == rhs.get<DecimalField<Decimal256>>();
|
||||
case Types::AggregateFunctionState: return get<AggregateFunctionStateData>() == rhs.get<AggregateFunctionStateData>();
|
||||
case Types::bUInt256: return get<bUInt256>() == rhs.get<bUInt256>();
|
||||
case Types::bInt256: return get<bInt256>() == rhs.get<bInt256>();
|
||||
}
|
||||
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
@ -541,20 +573,17 @@ public:
|
||||
case Types::String: return f(field.template get<String>());
|
||||
case Types::Array: return f(field.template get<Array>());
|
||||
case Types::Tuple: return f(field.template get<Tuple>());
|
||||
#if !__clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
case Types::Decimal32: return f(field.template get<DecimalField<Decimal32>>());
|
||||
case Types::Decimal64: return f(field.template get<DecimalField<Decimal64>>());
|
||||
case Types::Decimal128: return f(field.template get<DecimalField<Decimal128>>());
|
||||
case Types::Decimal256: return f(field.template get<DecimalField<Decimal256>>());
|
||||
case Types::AggregateFunctionState: return f(field.template get<AggregateFunctionStateData>());
|
||||
case Types::Int128:
|
||||
// TODO: investigate where we need Int128 Fields. There are no
|
||||
// field visitors that support them, and they only arise indirectly
|
||||
// in some functions that use Decimal columns: they get the
|
||||
// underlying Field value with get<Int128>(). Probably should be
|
||||
// switched to DecimalField, but this is a whole endeavor in itself.
|
||||
throw Exception("Unexpected Int128 in Field::dispatch()", ErrorCodes::LOGICAL_ERROR);
|
||||
case Types::Int128: return f(field.template get<Int128>());
|
||||
case Types::bUInt256: return f(field.template get<bUInt256>());
|
||||
case Types::bInt256: return f(field.template get<bInt256>());
|
||||
#if !__clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
// GCC 9 complains that control reaches the end, despite that we handle
|
||||
@ -570,7 +599,9 @@ public:
|
||||
private:
|
||||
std::aligned_union_t<DBMS_MIN_FIELD_SIZE - sizeof(Types::Which),
|
||||
Null, UInt64, UInt128, Int64, Int128, Float64, String, Array, Tuple,
|
||||
DecimalField<Decimal32>, DecimalField<Decimal64>, DecimalField<Decimal128>, AggregateFunctionStateData
|
||||
DecimalField<Decimal32>, DecimalField<Decimal64>, DecimalField<Decimal128>, DecimalField<Decimal256>,
|
||||
AggregateFunctionStateData,
|
||||
bUInt256, bInt256
|
||||
> storage;
|
||||
|
||||
Types::Which which;
|
||||
@ -699,7 +730,10 @@ template <> struct Field::TypeToEnum<Tuple> { static const Types::Which value
|
||||
template <> struct Field::TypeToEnum<DecimalField<Decimal32>>{ static const Types::Which value = Types::Decimal32; };
|
||||
template <> struct Field::TypeToEnum<DecimalField<Decimal64>>{ static const Types::Which value = Types::Decimal64; };
|
||||
template <> struct Field::TypeToEnum<DecimalField<Decimal128>>{ static const Types::Which value = Types::Decimal128; };
|
||||
template <> struct Field::TypeToEnum<DecimalField<Decimal256>>{ static const Types::Which value = Types::Decimal256; };
|
||||
template <> struct Field::TypeToEnum<AggregateFunctionStateData>{ static const Types::Which value = Types::AggregateFunctionState; };
|
||||
template <> struct Field::TypeToEnum<bUInt256> { static const Types::Which value = Types::bUInt256; };
|
||||
template <> struct Field::TypeToEnum<bInt256> { static const Types::Which value = Types::bInt256; };
|
||||
|
||||
template <> struct Field::EnumToType<Field::Types::Null> { using Type = Null; };
|
||||
template <> struct Field::EnumToType<Field::Types::UInt64> { using Type = UInt64; };
|
||||
@ -713,7 +747,10 @@ template <> struct Field::EnumToType<Field::Types::Tuple> { using Type = Tuple
|
||||
template <> struct Field::EnumToType<Field::Types::Decimal32> { using Type = DecimalField<Decimal32>; };
|
||||
template <> struct Field::EnumToType<Field::Types::Decimal64> { using Type = DecimalField<Decimal64>; };
|
||||
template <> struct Field::EnumToType<Field::Types::Decimal128> { using Type = DecimalField<Decimal128>; };
|
||||
template <> struct Field::EnumToType<Field::Types::Decimal256> { using Type = DecimalField<Decimal256>; };
|
||||
template <> struct Field::EnumToType<Field::Types::AggregateFunctionState> { using Type = DecimalField<AggregateFunctionStateData>; };
|
||||
template <> struct Field::EnumToType<Field::Types::bUInt256> { using Type = bUInt256; };
|
||||
template <> struct Field::EnumToType<Field::Types::bInt256> { using Type = bInt256; };
|
||||
|
||||
inline constexpr bool isInt64FieldType(Field::Types::Which t)
|
||||
{
|
||||
|
@ -375,6 +375,7 @@ class IColumn;
|
||||
M(String, function_implementation, "", "Choose function implementation for specific target or variant (experimental). If empty enable all of them.", 0) \
|
||||
\
|
||||
M(Bool, allow_experimental_geo_types, false, "Allow geo data types such as Point, Ring, Polygon, MultiPolygon", 0) \
|
||||
M(Bool, allow_experimental_bigint_types, false, "Allow Int128, Int256, UInt256 and Decimal256 types", 0) \
|
||||
M(Bool, data_type_default_nullable, false, "Data types without NULL or NOT NULL will make Nullable", 0) \
|
||||
M(Bool, cast_keep_nullable, false, "CAST operator keep Nullable for result data type", 0) \
|
||||
M(Bool, alter_partition_verbose_result, false, "Output information about affected parts. Currently works only for FREEZE and ATTACH commands.", 0) \
|
||||
|
@ -77,9 +77,9 @@ void SettingFieldNumber<T>::parseFromString(const String & str)
|
||||
template <typename T>
|
||||
void SettingFieldNumber<T>::writeBinary(WriteBuffer & out) const
|
||||
{
|
||||
if constexpr (is_integral_v<T> && is_unsigned_v<T>)
|
||||
if constexpr (std::is_integral_v<T> && is_unsigned_v<T>)
|
||||
writeVarUInt(static_cast<UInt64>(value), out);
|
||||
else if constexpr (is_integral_v<T> && is_signed_v<T>)
|
||||
else if constexpr (std::is_integral_v<T> && is_signed_v<T>)
|
||||
writeVarInt(static_cast<Int64>(value), out);
|
||||
else
|
||||
{
|
||||
@ -91,13 +91,13 @@ void SettingFieldNumber<T>::writeBinary(WriteBuffer & out) const
|
||||
template <typename T>
|
||||
void SettingFieldNumber<T>::readBinary(ReadBuffer & in)
|
||||
{
|
||||
if constexpr (is_integral_v<T> && is_unsigned_v<T>)
|
||||
if constexpr (std::is_integral_v<T> && is_unsigned_v<T>)
|
||||
{
|
||||
UInt64 x;
|
||||
readVarUInt(x, in);
|
||||
*this = static_cast<T>(x);
|
||||
}
|
||||
else if constexpr (is_integral_v<T> && is_signed_v<T>)
|
||||
else if constexpr (std::is_integral_v<T> && is_signed_v<T>)
|
||||
{
|
||||
Int64 x;
|
||||
readVarInt(x, in);
|
||||
|
@ -8,8 +8,11 @@ namespace DB
|
||||
{
|
||||
|
||||
using TypeListNativeNumbers = TypeList<UInt8, UInt16, UInt32, UInt64, Int8, Int16, Int32, Int64, Float32, Float64>;
|
||||
using TypeListDecimalNumbers = TypeList<Decimal32, Decimal64, Decimal128>;
|
||||
using TypeListNumbers = typename TypeListConcat<TypeListNativeNumbers, TypeListDecimalNumbers>::Type;
|
||||
using TypeListExtendedNumbers = TypeList<Int128, bUInt256, bInt256>;
|
||||
using TypeListDecimalNumbers = TypeList<Decimal32, Decimal64, Decimal128, Decimal256>;
|
||||
|
||||
using TypeListGeneralNumbers = typename TypeListConcat<TypeListNativeNumbers, TypeListExtendedNumbers>::Type;
|
||||
using TypeListNumbers = typename TypeListConcat<TypeListGeneralNumbers, TypeListDecimalNumbers>::Type;
|
||||
|
||||
/// Currently separate because UInt128 cannot be used in every context where other numbers can be used.
|
||||
using TypeListNumbersAndUInt128 = typename AppendToTypeList<UInt128, TypeListNumbers>::Type;
|
||||
|
101
src/Core/Types.h
101
src/Core/Types.h
@ -4,7 +4,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <common/types.h>
|
||||
#include <Common/intExp.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -23,11 +22,13 @@ enum class TypeIndex
|
||||
UInt32,
|
||||
UInt64,
|
||||
UInt128,
|
||||
bUInt256,
|
||||
Int8,
|
||||
Int16,
|
||||
Int32,
|
||||
Int64,
|
||||
Int128,
|
||||
bInt256,
|
||||
Float32,
|
||||
Float64,
|
||||
Date,
|
||||
@ -40,6 +41,7 @@ enum class TypeIndex
|
||||
Decimal32,
|
||||
Decimal64,
|
||||
Decimal128,
|
||||
Decimal256,
|
||||
UUID,
|
||||
Array,
|
||||
Tuple,
|
||||
@ -51,16 +53,19 @@ enum class TypeIndex
|
||||
LowCardinality,
|
||||
};
|
||||
|
||||
using UInt8 = char8_t; /// This is needed for more strict aliasing. https://godbolt.org/z/xpJBSb https://stackoverflow.com/a/57453713
|
||||
/// defined in common/types.h
|
||||
using UInt8 = ::UInt8;
|
||||
using UInt16 = ::UInt16;
|
||||
using UInt32 = ::UInt32;
|
||||
using UInt64 = ::UInt64;
|
||||
using bUInt256 = ::bUInt256;
|
||||
|
||||
using UInt16 = uint16_t;
|
||||
using UInt32 = uint32_t;
|
||||
using UInt64 = uint64_t;
|
||||
|
||||
using Int8 = int8_t;
|
||||
using Int16 = int16_t;
|
||||
using Int32 = int32_t;
|
||||
using Int64 = int64_t;
|
||||
using Int8 = ::Int8;
|
||||
using Int16 = ::Int16;
|
||||
using Int32 = ::Int32;
|
||||
using Int64 = ::Int64;
|
||||
using Int128 = ::Int128;
|
||||
using bInt256 = ::bInt256;
|
||||
|
||||
using Float32 = float;
|
||||
using Float64 = double;
|
||||
@ -76,10 +81,13 @@ template <> inline constexpr bool IsNumber<UInt8> = true;
|
||||
template <> inline constexpr bool IsNumber<UInt16> = true;
|
||||
template <> inline constexpr bool IsNumber<UInt32> = true;
|
||||
template <> inline constexpr bool IsNumber<UInt64> = true;
|
||||
template <> inline constexpr bool IsNumber<bUInt256> = true;
|
||||
template <> inline constexpr bool IsNumber<Int8> = true;
|
||||
template <> inline constexpr bool IsNumber<Int16> = true;
|
||||
template <> inline constexpr bool IsNumber<Int32> = true;
|
||||
template <> inline constexpr bool IsNumber<Int64> = true;
|
||||
template <> inline constexpr bool IsNumber<Int128> = true;
|
||||
template <> inline constexpr bool IsNumber<bInt256> = true;
|
||||
template <> inline constexpr bool IsNumber<Float32> = true;
|
||||
template <> inline constexpr bool IsNumber<Float64> = true;
|
||||
|
||||
@ -89,10 +97,13 @@ template <> struct TypeName<UInt8> { static constexpr const char * get() { ret
|
||||
template <> struct TypeName<UInt16> { static constexpr const char * get() { return "UInt16"; } };
|
||||
template <> struct TypeName<UInt32> { static constexpr const char * get() { return "UInt32"; } };
|
||||
template <> struct TypeName<UInt64> { static constexpr const char * get() { return "UInt64"; } };
|
||||
template <> struct TypeName<bUInt256> { static constexpr const char * get() { return "UInt256"; } };
|
||||
template <> struct TypeName<Int8> { static constexpr const char * get() { return "Int8"; } };
|
||||
template <> struct TypeName<Int16> { static constexpr const char * get() { return "Int16"; } };
|
||||
template <> struct TypeName<Int32> { static constexpr const char * get() { return "Int32"; } };
|
||||
template <> struct TypeName<Int64> { static constexpr const char * get() { return "Int64"; } };
|
||||
template <> struct TypeName<Int128> { static constexpr const char * get() { return "Int128"; } };
|
||||
template <> struct TypeName<bInt256> { static constexpr const char * get() { return "Int256"; } };
|
||||
template <> struct TypeName<Float32> { static constexpr const char * get() { return "Float32"; } };
|
||||
template <> struct TypeName<Float64> { static constexpr const char * get() { return "Float64"; } };
|
||||
template <> struct TypeName<String> { static constexpr const char * get() { return "String"; } };
|
||||
@ -102,22 +113,19 @@ template <> struct TypeId<UInt8> { static constexpr const TypeIndex value = T
|
||||
template <> struct TypeId<UInt16> { static constexpr const TypeIndex value = TypeIndex::UInt16; };
|
||||
template <> struct TypeId<UInt32> { static constexpr const TypeIndex value = TypeIndex::UInt32; };
|
||||
template <> struct TypeId<UInt64> { static constexpr const TypeIndex value = TypeIndex::UInt64; };
|
||||
template <> struct TypeId<bUInt256> { static constexpr const TypeIndex value = TypeIndex::bUInt256; };
|
||||
template <> struct TypeId<Int8> { static constexpr const TypeIndex value = TypeIndex::Int8; };
|
||||
template <> struct TypeId<Int16> { static constexpr const TypeIndex value = TypeIndex::Int16; };
|
||||
template <> struct TypeId<Int32> { static constexpr const TypeIndex value = TypeIndex::Int32; };
|
||||
template <> struct TypeId<Int64> { static constexpr const TypeIndex value = TypeIndex::Int64; };
|
||||
template <> struct TypeId<Int128> { static constexpr const TypeIndex value = TypeIndex::Int128; };
|
||||
template <> struct TypeId<bInt256> { static constexpr const TypeIndex value = TypeIndex::bInt256; };
|
||||
template <> struct TypeId<Float32> { static constexpr const TypeIndex value = TypeIndex::Float32; };
|
||||
template <> struct TypeId<Float64> { static constexpr const TypeIndex value = TypeIndex::Float64; };
|
||||
|
||||
/// Not a data type in database, defined just for convenience.
|
||||
using Strings = std::vector<String>;
|
||||
|
||||
|
||||
using Int128 = __int128;
|
||||
template <> inline constexpr bool IsNumber<Int128> = true;
|
||||
template <> struct TypeName<Int128> { static constexpr const char * get() { return "Int128"; } };
|
||||
template <> struct TypeId<Int128> { static constexpr const TypeIndex value = TypeIndex::Int128; };
|
||||
|
||||
/// Own FieldType for Decimal.
|
||||
/// It is only a "storage" for decimal. To perform operations, you also have to provide a scale (number of digits after point).
|
||||
template <typename T>
|
||||
@ -135,7 +143,7 @@ struct Decimal
|
||||
|
||||
template <typename U>
|
||||
Decimal(const Decimal<U> & x)
|
||||
: value(x)
|
||||
: value(x.value)
|
||||
{}
|
||||
|
||||
constexpr Decimal<T> & operator = (Decimal<T> &&) = default;
|
||||
@ -143,45 +151,78 @@ struct Decimal
|
||||
|
||||
operator T () const { return value; }
|
||||
|
||||
template <typename U>
|
||||
U convertTo()
|
||||
{
|
||||
/// no IsDecimalNumber defined yet
|
||||
if constexpr (std::is_same_v<U, Decimal<Int32>> ||
|
||||
std::is_same_v<U, Decimal<Int64>> ||
|
||||
std::is_same_v<U, Decimal<Int128>> ||
|
||||
std::is_same_v<U, Decimal<bInt256>>)
|
||||
{
|
||||
return convertTo<typename U::NativeType>();
|
||||
}
|
||||
else if constexpr (is_big_int_v<NativeType>)
|
||||
{
|
||||
return value. template convert_to<U>();
|
||||
}
|
||||
else
|
||||
return static_cast<U>(value);
|
||||
}
|
||||
|
||||
const Decimal<T> & operator += (const T & x) { value += x; return *this; }
|
||||
const Decimal<T> & operator -= (const T & x) { value -= x; return *this; }
|
||||
const Decimal<T> & operator *= (const T & x) { value *= x; return *this; }
|
||||
const Decimal<T> & operator /= (const T & x) { value /= x; return *this; }
|
||||
const Decimal<T> & operator %= (const T & x) { value %= x; return *this; }
|
||||
|
||||
static T getScaleMultiplier(UInt32 scale);
|
||||
|
||||
T value;
|
||||
};
|
||||
|
||||
template <typename T> inline bool operator< (const Decimal<T> & x, const Decimal<T> & y) { return x.value < y.value; }
|
||||
template <typename T> inline bool operator> (const Decimal<T> & x, const Decimal<T> & y) { return x.value > y.value; }
|
||||
template <typename T> inline bool operator== (const Decimal<T> & x, const Decimal<T> & y) { return x.value == y.value; }
|
||||
template <typename T> inline bool operator!= (const Decimal<T> & x, const Decimal<T> & y) { return x.value != y.value; }
|
||||
|
||||
template <typename T> inline Decimal<T> operator+ (const Decimal<T> & x, const Decimal<T> & y) { return x.value + y.value; }
|
||||
template <typename T> inline Decimal<T> operator- (const Decimal<T> & x, const Decimal<T> & y) { return x.value - y.value; }
|
||||
template <typename T> inline Decimal<T> operator* (const Decimal<T> & x, const Decimal<T> & y) { return x.value * y.value; }
|
||||
template <typename T> inline Decimal<T> operator/ (const Decimal<T> & x, const Decimal<T> & y) { return x.value / y.value; }
|
||||
template <typename T> inline Decimal<T> operator- (const Decimal<T> & x) { return -x.value; }
|
||||
|
||||
using Decimal32 = Decimal<Int32>;
|
||||
using Decimal64 = Decimal<Int64>;
|
||||
using Decimal128 = Decimal<Int128>;
|
||||
using Decimal256 = Decimal<bInt256>;
|
||||
|
||||
using DateTime64 = Decimal64;
|
||||
|
||||
template <> struct TypeName<Decimal32> { static constexpr const char * get() { return "Decimal32"; } };
|
||||
template <> struct TypeName<Decimal64> { static constexpr const char * get() { return "Decimal64"; } };
|
||||
template <> struct TypeName<Decimal128> { static constexpr const char * get() { return "Decimal128"; } };
|
||||
template <> struct TypeName<Decimal256> { static constexpr const char * get() { return "Decimal256"; } };
|
||||
|
||||
template <> struct TypeId<Decimal32> { static constexpr const TypeIndex value = TypeIndex::Decimal32; };
|
||||
template <> struct TypeId<Decimal64> { static constexpr const TypeIndex value = TypeIndex::Decimal64; };
|
||||
template <> struct TypeId<Decimal128> { static constexpr const TypeIndex value = TypeIndex::Decimal128; };
|
||||
template <> struct TypeId<Decimal256> { static constexpr const TypeIndex value = TypeIndex::Decimal256; };
|
||||
|
||||
template <typename T> constexpr bool IsDecimalNumber = false;
|
||||
template <> inline constexpr bool IsDecimalNumber<Decimal32> = true;
|
||||
template <> inline constexpr bool IsDecimalNumber<Decimal64> = true;
|
||||
template <> inline constexpr bool IsDecimalNumber<Decimal128> = true;
|
||||
template <> inline constexpr bool IsDecimalNumber<Decimal256> = true;
|
||||
|
||||
template <typename T> struct NativeType { using Type = T; };
|
||||
template <> struct NativeType<Decimal32> { using Type = Int32; };
|
||||
template <> struct NativeType<Decimal64> { using Type = Int64; };
|
||||
template <> struct NativeType<Decimal128> { using Type = Int128; };
|
||||
template <> struct NativeType<Decimal256> { using Type = bInt256; };
|
||||
|
||||
template <> inline Int32 Decimal32::getScaleMultiplier(UInt32 scale) { return common::exp10_i32(scale); }
|
||||
template <> inline Int64 Decimal64::getScaleMultiplier(UInt32 scale) { return common::exp10_i64(scale); }
|
||||
template <> inline Int128 Decimal128::getScaleMultiplier(UInt32 scale) { return common::exp10_i128(scale); }
|
||||
template <typename T> constexpr bool OverBigInt = false;
|
||||
template <> inline constexpr bool OverBigInt<bInt256> = true;
|
||||
template <> inline constexpr bool OverBigInt<bUInt256> = true;
|
||||
template <> inline constexpr bool OverBigInt<Decimal256> = true;
|
||||
|
||||
inline constexpr const char * getTypeName(TypeIndex idx)
|
||||
{
|
||||
@ -193,11 +234,13 @@ inline constexpr const char * getTypeName(TypeIndex idx)
|
||||
case TypeIndex::UInt32: return TypeName<UInt32>::get();
|
||||
case TypeIndex::UInt64: return TypeName<UInt64>::get();
|
||||
case TypeIndex::UInt128: return "UInt128";
|
||||
case TypeIndex::bUInt256: return TypeName<bUInt256>::get();
|
||||
case TypeIndex::Int8: return TypeName<Int8>::get();
|
||||
case TypeIndex::Int16: return TypeName<Int16>::get();
|
||||
case TypeIndex::Int32: return TypeName<Int32>::get();
|
||||
case TypeIndex::Int64: return TypeName<Int64>::get();
|
||||
case TypeIndex::Int128: return TypeName<Int128>::get();
|
||||
case TypeIndex::bInt256: return TypeName<bInt256>::get();
|
||||
case TypeIndex::Float32: return TypeName<Float32>::get();
|
||||
case TypeIndex::Float64: return TypeName<Float64>::get();
|
||||
case TypeIndex::Date: return "Date";
|
||||
@ -210,6 +253,7 @@ inline constexpr const char * getTypeName(TypeIndex idx)
|
||||
case TypeIndex::Decimal32: return TypeName<Decimal32>::get();
|
||||
case TypeIndex::Decimal64: return TypeName<Decimal64>::get();
|
||||
case TypeIndex::Decimal128: return TypeName<Decimal128>::get();
|
||||
case TypeIndex::Decimal256: return TypeName<Decimal256>::get();
|
||||
case TypeIndex::UUID: return "UUID";
|
||||
case TypeIndex::Array: return "Array";
|
||||
case TypeIndex::Tuple: return "Tuple";
|
||||
@ -241,4 +285,17 @@ namespace std
|
||||
^ std::hash<DB::Int64>()(x.value & std::numeric_limits<DB::UInt64>::max());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct hash<DB::Decimal256>
|
||||
{
|
||||
size_t operator()(const DB::Decimal256 & x) const
|
||||
{
|
||||
// temp solution
|
||||
static constexpr DB::UInt64 max_uint_mask = std::numeric_limits<DB::UInt64>::max();
|
||||
return std::hash<DB::Int64>()(static_cast<DB::Int64>(x.value >> 64 & max_uint_mask))
|
||||
^ std::hash<DB::Int64>()(static_cast<DB::Int64>(x.value & max_uint_mask));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -26,15 +26,17 @@ bool callOnBasicType(TypeIndex number, F && f)
|
||||
case TypeIndex::UInt16: return f(TypePair<T, UInt16>());
|
||||
case TypeIndex::UInt32: return f(TypePair<T, UInt32>());
|
||||
case TypeIndex::UInt64: return f(TypePair<T, UInt64>());
|
||||
case TypeIndex::bUInt256: return f(TypePair<T, bUInt256>());
|
||||
|
||||
case TypeIndex::Int8: return f(TypePair<T, Int8>());
|
||||
case TypeIndex::Int16: return f(TypePair<T, Int16>());
|
||||
case TypeIndex::Int32: return f(TypePair<T, Int32>());
|
||||
case TypeIndex::Int64: return f(TypePair<T, Int64>());
|
||||
case TypeIndex::Int128: return f(TypePair<T, Int128>());
|
||||
case TypeIndex::bInt256: return f(TypePair<T, bInt256>());
|
||||
|
||||
case TypeIndex::Enum8: return f(TypePair<T, Int8>());
|
||||
case TypeIndex::Enum16: return f(TypePair<T, Int16>());
|
||||
case TypeIndex::Enum16: return f(TypePair<T, Int16>());
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -48,6 +50,7 @@ bool callOnBasicType(TypeIndex number, F && f)
|
||||
case TypeIndex::Decimal32: return f(TypePair<T, Decimal32>());
|
||||
case TypeIndex::Decimal64: return f(TypePair<T, Decimal64>());
|
||||
case TypeIndex::Decimal128: return f(TypePair<T, Decimal128>());
|
||||
case TypeIndex::Decimal256: return f(TypePair<T, Decimal256>());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -91,12 +94,14 @@ inline bool callOnBasicTypes(TypeIndex type_num1, TypeIndex type_num2, F && f)
|
||||
case TypeIndex::UInt16: return callOnBasicType<UInt16, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::UInt32: return callOnBasicType<UInt32, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::UInt64: return callOnBasicType<UInt64, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::bUInt256: return callOnBasicType<bUInt256, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
|
||||
case TypeIndex::Int8: return callOnBasicType<Int8, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::Int16: return callOnBasicType<Int16, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::Int32: return callOnBasicType<Int32, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::Int64: return callOnBasicType<Int64, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::Int128: return callOnBasicType<Int128, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::bInt256: return callOnBasicType<bInt256, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
|
||||
case TypeIndex::Enum8: return callOnBasicType<Int8, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::Enum16: return callOnBasicType<Int16, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
@ -113,6 +118,7 @@ inline bool callOnBasicTypes(TypeIndex type_num1, TypeIndex type_num2, F && f)
|
||||
case TypeIndex::Decimal32: return callOnBasicType<Decimal32, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::Decimal64: return callOnBasicType<Decimal64, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::Decimal128: return callOnBasicType<Decimal128, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
case TypeIndex::Decimal256: return callOnBasicType<Decimal256, _int, _float, _decimal, _datetime>(type_num2, std::forward<F>(f));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -165,11 +171,14 @@ bool callOnIndexAndDataType(TypeIndex number, F && f)
|
||||
case TypeIndex::UInt16: return f(TypePair<DataTypeNumber<UInt16>, T>());
|
||||
case TypeIndex::UInt32: return f(TypePair<DataTypeNumber<UInt32>, T>());
|
||||
case TypeIndex::UInt64: return f(TypePair<DataTypeNumber<UInt64>, T>());
|
||||
case TypeIndex::bUInt256: return f(TypePair<DataTypeNumber<bUInt256>, T>());
|
||||
|
||||
case TypeIndex::Int8: return f(TypePair<DataTypeNumber<Int8>, T>());
|
||||
case TypeIndex::Int16: return f(TypePair<DataTypeNumber<Int16>, T>());
|
||||
case TypeIndex::Int32: return f(TypePair<DataTypeNumber<Int32>, T>());
|
||||
case TypeIndex::Int64: return f(TypePair<DataTypeNumber<Int64>, T>());
|
||||
case TypeIndex::Int128: return f(TypePair<DataTypeNumber<Int128>, T>());
|
||||
case TypeIndex::bInt256: return f(TypePair<DataTypeNumber<bInt256>, T>());
|
||||
|
||||
case TypeIndex::Float32: return f(TypePair<DataTypeNumber<Float32>, T>());
|
||||
case TypeIndex::Float64: return f(TypePair<DataTypeNumber<Float64>, T>());
|
||||
@ -177,6 +186,7 @@ bool callOnIndexAndDataType(TypeIndex number, F && f)
|
||||
case TypeIndex::Decimal32: return f(TypePair<DataTypeDecimal<Decimal32>, T>());
|
||||
case TypeIndex::Decimal64: return f(TypePair<DataTypeDecimal<Decimal64>, T>());
|
||||
case TypeIndex::Decimal128: return f(TypePair<DataTypeDecimal<Decimal128>, T>());
|
||||
case TypeIndex::Decimal256: return f(TypePair<DataTypeDecimal<Decimal256>, T>());
|
||||
|
||||
case TypeIndex::Date: return f(TypePair<DataTypeDate, T>());
|
||||
case TypeIndex::DateTime: return f(TypePair<DataTypeDateTime, T>());
|
||||
|
@ -101,5 +101,6 @@ T DataTypeDecimalBase<T>::getScaleMultiplier(UInt32 scale_)
|
||||
template class DataTypeDecimalBase<Decimal32>;
|
||||
template class DataTypeDecimalBase<Decimal64>;
|
||||
template class DataTypeDecimalBase<Decimal128>;
|
||||
template class DataTypeDecimalBase<Decimal256>;
|
||||
|
||||
}
|
||||
|
@ -50,8 +50,9 @@ inline UInt32 leastDecimalPrecisionFor(TypeIndex int_type)
|
||||
/// Int32 9
|
||||
/// Int64 18
|
||||
/// Int128 38
|
||||
/// Int256 76
|
||||
/// Operation between two decimals leads to Decimal(P, S), where
|
||||
/// P is one of (9, 18, 38); equals to the maximum precision for the biggest underlying type of operands.
|
||||
/// P is one of (9, 18, 38, 76); equals to the maximum precision for the biggest underlying type of operands.
|
||||
/// S is maximum scale of operands. The allowed valuas are [0, precision]
|
||||
template <typename T>
|
||||
class DataTypeDecimalBase : public DataTypeWithSimpleSerialization
|
||||
@ -143,7 +144,7 @@ public:
|
||||
T scaleFactorFor(const DataTypeNumber<U> & , bool is_multiply_or_divisor) const
|
||||
{
|
||||
if (is_multiply_or_divisor)
|
||||
return 1;
|
||||
return T(1);
|
||||
return getScaleMultiplier();
|
||||
}
|
||||
|
||||
@ -194,7 +195,7 @@ const DecimalType<U> decimalResultType(const DataTypeNumber<T> &, const DecimalT
|
||||
template <template <typename> typename DecimalType>
|
||||
DataTypePtr createDecimal(UInt64 precision_value, UInt64 scale_value)
|
||||
{
|
||||
if (precision_value < DecimalUtils::minPrecision() || precision_value > DecimalUtils::maxPrecision<Decimal128>())
|
||||
if (precision_value < DecimalUtils::minPrecision() || precision_value > DecimalUtils::maxPrecision<Decimal256>())
|
||||
throw Exception("Wrong precision", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
|
||||
|
||||
if (static_cast<UInt64>(scale_value) > precision_value)
|
||||
@ -204,7 +205,9 @@ DataTypePtr createDecimal(UInt64 precision_value, UInt64 scale_value)
|
||||
return std::make_shared<DecimalType<Decimal32>>(precision_value, scale_value);
|
||||
else if (precision_value <= DecimalUtils::maxPrecision<Decimal64>())
|
||||
return std::make_shared<DecimalType<Decimal64>>(precision_value, scale_value);
|
||||
return std::make_shared<DecimalType<Decimal128>>(precision_value, scale_value);
|
||||
else if (precision_value <= DecimalUtils::maxPrecision<Decimal128>())
|
||||
return std::make_shared<DecimalType<Decimal128>>(precision_value, scale_value);
|
||||
return std::make_shared<DecimalType<Decimal256>>(precision_value, scale_value);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ void DataTypeNumberBase<T>::deserializeText(IColumn & column, ReadBuffer & istr,
|
||||
{
|
||||
T x;
|
||||
|
||||
if constexpr (is_integral_v<T> && is_arithmetic_v<T>)
|
||||
if constexpr (is_integer_v<T> && is_arithmetic_v<T>)
|
||||
readIntTextUnsafe(x, istr);
|
||||
else
|
||||
readText(x, istr);
|
||||
@ -68,7 +68,7 @@ void DataTypeNumberBase<T>::serializeTextJSON(const IColumn & column, size_t row
|
||||
auto x = assert_cast<const ColumnVector<T> &>(column).getData()[row_num];
|
||||
bool is_finite = isFinite(x);
|
||||
|
||||
const bool need_quote = (is_integral_v<T> && (sizeof(T) == 8) && settings.json.quote_64bit_integers)
|
||||
const bool need_quote = (is_integer_v<T> && (sizeof(T) >= 8) && settings.json.quote_64bit_integers)
|
||||
|| (settings.json.quote_denormals && !is_finite);
|
||||
|
||||
if (need_quote)
|
||||
@ -242,13 +242,13 @@ MutableColumnPtr DataTypeNumberBase<T>::createColumn() const
|
||||
template <typename T>
|
||||
bool DataTypeNumberBase<T>::isValueRepresentedByInteger() const
|
||||
{
|
||||
return is_integral_v<T>;
|
||||
return std::is_integral_v<T>;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DataTypeNumberBase<T>::isValueRepresentedByUnsignedInteger() const
|
||||
{
|
||||
return is_integral_v<T> && is_unsigned_v<T>;
|
||||
return std::is_integral_v<T> && is_unsigned_v<T>;
|
||||
}
|
||||
|
||||
|
||||
@ -258,10 +258,13 @@ template class DataTypeNumberBase<UInt16>;
|
||||
template class DataTypeNumberBase<UInt32>;
|
||||
template class DataTypeNumberBase<UInt64>;
|
||||
template class DataTypeNumberBase<UInt128>; // used only in UUID
|
||||
template class DataTypeNumberBase<bUInt256>;
|
||||
template class DataTypeNumberBase<Int8>;
|
||||
template class DataTypeNumberBase<Int16>;
|
||||
template class DataTypeNumberBase<Int32>;
|
||||
template class DataTypeNumberBase<Int64>;
|
||||
template class DataTypeNumberBase<Int128>;
|
||||
template class DataTypeNumberBase<bInt256>;
|
||||
template class DataTypeNumberBase<Float32>;
|
||||
template class DataTypeNumberBase<Float64>;
|
||||
|
||||
|
@ -64,7 +64,7 @@ bool DataTypeDecimal<T>::tryReadText(T & x, ReadBuffer & istr, UInt32 precision,
|
||||
if (!tryReadDecimalText(istr, x, precision, unread_scale))
|
||||
return false;
|
||||
|
||||
if (common::mulOverflow(x.value, T::getScaleMultiplier(unread_scale), x.value))
|
||||
if (common::mulOverflow(x.value, DecimalUtils::scaleMultiplier<T>(unread_scale), x.value))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@ -79,7 +79,7 @@ void DataTypeDecimal<T>::readText(T & x, ReadBuffer & istr, UInt32 precision, UI
|
||||
else
|
||||
readDecimalText(istr, x, precision, unread_scale);
|
||||
|
||||
if (common::mulOverflow(x.value, T::getScaleMultiplier(unread_scale), x.value))
|
||||
if (common::mulOverflow(x.value, DecimalUtils::scaleMultiplier<T>(unread_scale), x.value))
|
||||
throw Exception("Decimal math overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ T DataTypeDecimal<T>::parseFromString(const String & str) const
|
||||
UInt32 unread_scale = this->scale;
|
||||
readDecimalText(buf, x, this->precision, unread_scale, true);
|
||||
|
||||
if (common::mulOverflow(x.value, T::getScaleMultiplier(unread_scale), x.value))
|
||||
if (common::mulOverflow(x.value, DecimalUtils::scaleMultiplier<T>(unread_scale), x.value))
|
||||
throw Exception("Decimal math overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
|
||||
return x;
|
||||
@ -183,6 +183,7 @@ void registerDataTypeDecimal(DataTypeFactory & factory)
|
||||
factory.registerDataType("Decimal32", createExact<Decimal32>, DataTypeFactory::CaseInsensitive);
|
||||
factory.registerDataType("Decimal64", createExact<Decimal64>, DataTypeFactory::CaseInsensitive);
|
||||
factory.registerDataType("Decimal128", createExact<Decimal128>, DataTypeFactory::CaseInsensitive);
|
||||
factory.registerDataType("Decimal256", createExact<Decimal256>, DataTypeFactory::CaseInsensitive);
|
||||
|
||||
factory.registerDataType("Decimal", create, DataTypeFactory::CaseInsensitive);
|
||||
factory.registerAlias("DEC", "Decimal", DataTypeFactory::CaseInsensitive);
|
||||
@ -194,5 +195,6 @@ void registerDataTypeDecimal(DataTypeFactory & factory)
|
||||
template class DataTypeDecimal<Decimal32>;
|
||||
template class DataTypeDecimal<Decimal64>;
|
||||
template class DataTypeDecimal<Decimal128>;
|
||||
template class DataTypeDecimal<Decimal256>;
|
||||
|
||||
}
|
||||
|
@ -19,8 +19,9 @@ namespace ErrorCodes
|
||||
/// Int32 9
|
||||
/// Int64 18
|
||||
/// Int128 38
|
||||
/// Int256 76
|
||||
/// Operation between two decimals leads to Decimal(P, S), where
|
||||
/// P is one of (9, 18, 38); equals to the maximum precision for the biggest underlying type of operands.
|
||||
/// P is one of (9, 18, 38, 76); equals to the maximum precision for the biggest underlying type of operands.
|
||||
/// S is maximum scale of operands. The allowed valuas are [0, precision]
|
||||
template <typename T>
|
||||
class DataTypeDecimal final : public DataTypeDecimalBase<T>
|
||||
@ -71,6 +72,8 @@ inline UInt32 getDecimalScale(const IDataType & data_type, UInt32 default_value
|
||||
return decimal_type->getScale();
|
||||
if (auto * decimal_type = checkDecimal<Decimal128>(data_type))
|
||||
return decimal_type->getScale();
|
||||
if (auto * decimal_type = checkDecimal<Decimal256>(data_type))
|
||||
return decimal_type->getScale();
|
||||
return default_value;
|
||||
}
|
||||
|
||||
@ -92,13 +95,13 @@ convertDecimals(const typename FromDataType::FieldType & value, UInt32 scale_fro
|
||||
MaxNativeType converted_value;
|
||||
if (scale_to > scale_from)
|
||||
{
|
||||
converted_value = MaxFieldType::getScaleMultiplier(scale_to - scale_from);
|
||||
if (common::mulOverflow(static_cast<MaxNativeType>(value), converted_value, converted_value))
|
||||
converted_value = DecimalUtils::scaleMultiplier<MaxNativeType>(scale_to - scale_from);
|
||||
if (common::mulOverflow(static_cast<MaxNativeType>(value.value), converted_value, converted_value))
|
||||
throw Exception(std::string(ToDataType::family_name) + " convert overflow",
|
||||
ErrorCodes::DECIMAL_OVERFLOW);
|
||||
}
|
||||
else
|
||||
converted_value = value / MaxFieldType::getScaleMultiplier(scale_from - scale_to);
|
||||
converted_value = value.value / DecimalUtils::scaleMultiplier<MaxNativeType>(scale_from - scale_to);
|
||||
|
||||
if constexpr (sizeof(FromFieldType) > sizeof(ToFieldType))
|
||||
{
|
||||
@ -108,43 +111,16 @@ convertDecimals(const typename FromDataType::FieldType & value, UInt32 scale_fro
|
||||
ErrorCodes::DECIMAL_OVERFLOW);
|
||||
}
|
||||
|
||||
return converted_value;
|
||||
return static_cast<typename ToFieldType::NativeType>(converted_value);
|
||||
}
|
||||
|
||||
template <typename FromDataType, typename ToDataType>
|
||||
inline std::enable_if_t<IsDataTypeDecimal<FromDataType> && IsNumber<typename ToDataType::FieldType>, typename ToDataType::FieldType>
|
||||
convertFromDecimal(const typename FromDataType::FieldType & value, UInt32 scale)
|
||||
{
|
||||
using FromFieldType = typename FromDataType::FieldType;
|
||||
using ToFieldType = typename ToDataType::FieldType;
|
||||
|
||||
if constexpr (std::is_floating_point_v<ToFieldType>)
|
||||
return static_cast<ToFieldType>(value) / FromFieldType::getScaleMultiplier(scale);
|
||||
else
|
||||
{
|
||||
FromFieldType converted_value = convertDecimals<FromDataType, FromDataType>(value, scale, 0);
|
||||
|
||||
if constexpr (sizeof(FromFieldType) > sizeof(ToFieldType) || !std::numeric_limits<ToFieldType>::is_signed)
|
||||
{
|
||||
if constexpr (std::numeric_limits<ToFieldType>::is_signed)
|
||||
{
|
||||
if (converted_value < std::numeric_limits<ToFieldType>::min() ||
|
||||
converted_value > std::numeric_limits<ToFieldType>::max())
|
||||
throw Exception(std::string(FromDataType::family_name) + " convert overflow",
|
||||
ErrorCodes::DECIMAL_OVERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
using CastIntType = std::conditional_t<std::is_same_v<ToFieldType, UInt64>, Int128, Int64>;
|
||||
|
||||
if (converted_value < 0 ||
|
||||
converted_value > static_cast<CastIntType>(std::numeric_limits<ToFieldType>::max()))
|
||||
throw Exception(std::string(FromDataType::family_name) + " convert overflow",
|
||||
ErrorCodes::DECIMAL_OVERFLOW);
|
||||
}
|
||||
}
|
||||
return converted_value;
|
||||
}
|
||||
return DecimalUtils::convertTo<ToFieldType>(value, scale);
|
||||
}
|
||||
|
||||
template <typename FromDataType, typename ToDataType>
|
||||
@ -161,30 +137,32 @@ convertToDecimal(const typename FromDataType::FieldType & value, UInt32 scale)
|
||||
throw Exception(std::string(ToDataType::family_name) + " convert overflow. Cannot convert infinity or NaN to decimal",
|
||||
ErrorCodes::DECIMAL_OVERFLOW);
|
||||
|
||||
auto out = value * ToFieldType::getScaleMultiplier(scale);
|
||||
auto out = value * static_cast<FromFieldType>(DecimalUtils::scaleMultiplier<ToNativeType>(scale));
|
||||
if constexpr (std::is_same_v<ToNativeType, Int128>)
|
||||
{
|
||||
static constexpr __int128 min_int128 = __int128(0x8000000000000000ll) << 64;
|
||||
static constexpr __int128 max_int128 = (__int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll;
|
||||
static constexpr Int128 min_int128 = Int128(0x8000000000000000ll) << 64;
|
||||
static constexpr Int128 max_int128 = (Int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll;
|
||||
if (out <= static_cast<ToNativeType>(min_int128) || out >= static_cast<ToNativeType>(max_int128))
|
||||
throw Exception(std::string(ToDataType::family_name) + " convert overflow. Float is out of Decimal range",
|
||||
ErrorCodes::DECIMAL_OVERFLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (out <= std::numeric_limits<ToNativeType>::min() || out >= std::numeric_limits<ToNativeType>::max())
|
||||
if (out <= static_cast<FromFieldType>(std::numeric_limits<ToNativeType>::min()) ||
|
||||
out >= static_cast<FromFieldType>(std::numeric_limits<ToNativeType>::max()))
|
||||
throw Exception(std::string(ToDataType::family_name) + " convert overflow. Float is out of Decimal range",
|
||||
ErrorCodes::DECIMAL_OVERFLOW);
|
||||
}
|
||||
return out;
|
||||
return static_cast<ToNativeType>(out);
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (std::is_same_v<FromFieldType, UInt64>)
|
||||
if (value > static_cast<UInt64>(std::numeric_limits<Int64>::max()))
|
||||
return convertDecimals<DataTypeDecimal<Decimal128>, ToDataType>(value, 0, scale);
|
||||
|
||||
return convertDecimals<DataTypeDecimal<Decimal64>, ToDataType>(value, 0, scale);
|
||||
if constexpr (is_big_int_v<FromFieldType>)
|
||||
return convertDecimals<DataTypeDecimal<Decimal256>, ToDataType>(static_cast<bInt256>(value), 0, scale);
|
||||
else if constexpr (std::is_same_v<FromFieldType, UInt64>)
|
||||
return convertDecimals<DataTypeDecimal<Decimal128>, ToDataType>(value, 0, scale);
|
||||
else
|
||||
return convertDecimals<DataTypeDecimal<Decimal64>, ToDataType>(value, 0, scale);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,11 @@ void registerDataTypeNumbers(DataTypeFactory & factory)
|
||||
factory.registerDataType("Float32", createNumericDataType<Float32>);
|
||||
factory.registerDataType("Float64", createNumericDataType<Float64>);
|
||||
|
||||
/// These synonims are added for compatibility.
|
||||
factory.registerSimpleDataType("UInt256", [] { return DataTypePtr(std::make_shared<DataTypeUInt256>()); });
|
||||
factory.registerSimpleDataType("Int128", [] { return DataTypePtr(std::make_shared<DataTypeInt128>()); });
|
||||
factory.registerSimpleDataType("Int256", [] { return DataTypePtr(std::make_shared<DataTypeInt256>()); });
|
||||
|
||||
/// These synonyms are added for compatibility.
|
||||
|
||||
factory.registerAlias("TINYINT", "Int8", DataTypeFactory::CaseInsensitive);
|
||||
factory.registerAlias("BOOL", "Int8", DataTypeFactory::CaseInsensitive);
|
||||
|
@ -38,4 +38,8 @@ using DataTypeInt64 = DataTypeNumber<Int64>;
|
||||
using DataTypeFloat32 = DataTypeNumber<Float32>;
|
||||
using DataTypeFloat64 = DataTypeNumber<Float64>;
|
||||
|
||||
using DataTypeInt128 = DataTypeNumber<Int128>;
|
||||
using DataTypeUInt256 = DataTypeNumber<bUInt256>;
|
||||
using DataTypeInt256 = DataTypeNumber<bInt256>;
|
||||
|
||||
}
|
||||
|
@ -49,6 +49,15 @@ DataTypePtr FieldToDataType::operator() (const Int64 & x) const
|
||||
return std::make_shared<DataTypeInt64>();
|
||||
}
|
||||
|
||||
DataTypePtr FieldToDataType::operator() (const Int128 & x) const
|
||||
{
|
||||
if (x <= std::numeric_limits<Int8>::max() && x >= std::numeric_limits<Int8>::min()) return std::make_shared<DataTypeInt8>();
|
||||
if (x <= std::numeric_limits<Int16>::max() && x >= std::numeric_limits<Int16>::min()) return std::make_shared<DataTypeInt16>();
|
||||
if (x <= std::numeric_limits<Int32>::max() && x >= std::numeric_limits<Int32>::min()) return std::make_shared<DataTypeInt32>();
|
||||
if (x <= std::numeric_limits<Int64>::max() && x >= std::numeric_limits<Int64>::min()) return std::make_shared<DataTypeInt64>();
|
||||
return std::make_shared<DataTypeInt128>();
|
||||
}
|
||||
|
||||
DataTypePtr FieldToDataType::operator() (const Float64 &) const
|
||||
{
|
||||
return std::make_shared<DataTypeFloat64>();
|
||||
@ -77,6 +86,11 @@ DataTypePtr FieldToDataType::operator() (const DecimalField<Decimal128> & x) con
|
||||
return std::make_shared<Type>(Type::maxPrecision(), x.getScale());
|
||||
}
|
||||
|
||||
DataTypePtr FieldToDataType::operator() (const DecimalField<Decimal256> & x) const
|
||||
{
|
||||
using Type = DataTypeDecimal<Decimal256>;
|
||||
return std::make_shared<Type>(Type::maxPrecision(), x.getScale());
|
||||
}
|
||||
|
||||
DataTypePtr FieldToDataType::operator() (const Array & x) const
|
||||
{
|
||||
@ -110,4 +124,14 @@ DataTypePtr FieldToDataType::operator() (const AggregateFunctionStateData & x) c
|
||||
return DataTypeFactory::instance().get(name);
|
||||
}
|
||||
|
||||
DataTypePtr FieldToDataType::operator() (const bUInt256 &) const
|
||||
{
|
||||
throw Exception("There are no UInt256 literals in SQL", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
DataTypePtr FieldToDataType::operator() (const bInt256 &) const
|
||||
{
|
||||
throw Exception("There are no Int256 literals in SQL", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ public:
|
||||
DataTypePtr operator() (const UInt64 & x) const;
|
||||
DataTypePtr operator() (const UInt128 & x) const;
|
||||
DataTypePtr operator() (const Int64 & x) const;
|
||||
DataTypePtr operator() (const Int128 & x) const;
|
||||
DataTypePtr operator() (const Float64 & x) const;
|
||||
DataTypePtr operator() (const String & x) const;
|
||||
DataTypePtr operator() (const Array & x) const;
|
||||
@ -28,7 +29,10 @@ public:
|
||||
DataTypePtr operator() (const DecimalField<Decimal32> & x) const;
|
||||
DataTypePtr operator() (const DecimalField<Decimal64> & x) const;
|
||||
DataTypePtr operator() (const DecimalField<Decimal128> & x) const;
|
||||
DataTypePtr operator() (const DecimalField<Decimal256> & x) const;
|
||||
DataTypePtr operator() (const AggregateFunctionStateData & x) const;
|
||||
DataTypePtr operator() (const bUInt256 & x) const;
|
||||
DataTypePtr operator() (const bInt256 & x) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -482,7 +482,8 @@ struct WhichDataType
|
||||
bool isUInt32() const { return idx == TypeIndex::UInt32; }
|
||||
bool isUInt64() const { return idx == TypeIndex::UInt64; }
|
||||
bool isUInt128() const { return idx == TypeIndex::UInt128; }
|
||||
bool isUInt() const { return isUInt8() || isUInt16() || isUInt32() || isUInt64() || isUInt128(); }
|
||||
bool isbUInt256() const { return idx == TypeIndex::bUInt256; }
|
||||
bool isUInt() const { return isUInt8() || isUInt16() || isUInt32() || isUInt64() || isUInt128() || isbUInt256(); }
|
||||
bool isNativeUInt() const { return isUInt8() || isUInt16() || isUInt32() || isUInt64(); }
|
||||
|
||||
bool isInt8() const { return idx == TypeIndex::Int8; }
|
||||
@ -490,13 +491,15 @@ struct WhichDataType
|
||||
bool isInt32() const { return idx == TypeIndex::Int32; }
|
||||
bool isInt64() const { return idx == TypeIndex::Int64; }
|
||||
bool isInt128() const { return idx == TypeIndex::Int128; }
|
||||
bool isInt() const { return isInt8() || isInt16() || isInt32() || isInt64() || isInt128(); }
|
||||
bool isbInt256() const { return idx == TypeIndex::bInt256; }
|
||||
bool isInt() const { return isInt8() || isInt16() || isInt32() || isInt64() || isInt128() || isbInt256(); }
|
||||
bool isNativeInt() const { return isInt8() || isInt16() || isInt32() || isInt64(); }
|
||||
|
||||
bool isDecimal32() const { return idx == TypeIndex::Decimal32; }
|
||||
bool isDecimal64() const { return idx == TypeIndex::Decimal64; }
|
||||
bool isDecimal128() const { return idx == TypeIndex::Decimal128; }
|
||||
bool isDecimal() const { return isDecimal32() || isDecimal64() || isDecimal128(); }
|
||||
bool isDecimal256() const { return idx == TypeIndex::Decimal256; }
|
||||
bool isDecimal() const { return isDecimal32() || isDecimal64() || isDecimal128() || isDecimal256(); }
|
||||
|
||||
bool isFloat32() const { return idx == TypeIndex::Float32; }
|
||||
bool isFloat64() const { return idx == TypeIndex::Float64; }
|
||||
@ -525,6 +528,8 @@ struct WhichDataType
|
||||
bool isNullable() const { return idx == TypeIndex::Nullable; }
|
||||
bool isFunction() const { return idx == TypeIndex::Function; }
|
||||
bool isAggregateFunction() const { return idx == TypeIndex::AggregateFunction; }
|
||||
|
||||
bool IsBigIntOrDeimal() const { return isInt128() || isbInt256() || isbUInt256() || isDecimal256(); }
|
||||
};
|
||||
|
||||
/// IDataType helpers (alternative for IDataType virtual methods with single point of truth)
|
||||
|
@ -33,6 +33,18 @@ constexpr size_t nextSize(size_t size)
|
||||
return min(size * 2, 8);
|
||||
}
|
||||
|
||||
template <bool is_signed>
|
||||
constexpr size_t nextSize2(size_t size)
|
||||
{
|
||||
// old way for built-in integers
|
||||
if (size <= 8) return nextSize(size);
|
||||
|
||||
if constexpr (is_signed)
|
||||
return size <= 32 ? 32 : 48;
|
||||
else
|
||||
return size <= 32 ? 16 : 48;
|
||||
}
|
||||
|
||||
template <bool is_signed, bool is_floating, size_t size>
|
||||
struct Construct
|
||||
{
|
||||
@ -43,6 +55,9 @@ template <> struct Construct<false, false, 1> { using Type = UInt8; };
|
||||
template <> struct Construct<false, false, 2> { using Type = UInt16; };
|
||||
template <> struct Construct<false, false, 4> { using Type = UInt32; };
|
||||
template <> struct Construct<false, false, 8> { using Type = UInt64; };
|
||||
template <> struct Construct<false, false, 16> { using Type = bUInt256; };
|
||||
template <> struct Construct<false, false, 32> { using Type = bUInt256; };
|
||||
template <> struct Construct<false, false, 48> { using Type = bUInt256; };
|
||||
template <> struct Construct<false, true, 1> { using Type = Float32; };
|
||||
template <> struct Construct<false, true, 2> { using Type = Float32; };
|
||||
template <> struct Construct<false, true, 4> { using Type = Float32; };
|
||||
@ -51,6 +66,9 @@ template <> struct Construct<true, false, 1> { using Type = Int8; };
|
||||
template <> struct Construct<true, false, 2> { using Type = Int16; };
|
||||
template <> struct Construct<true, false, 4> { using Type = Int32; };
|
||||
template <> struct Construct<true, false, 8> { using Type = Int64; };
|
||||
template <> struct Construct<true, false, 16> { using Type = Int128; };
|
||||
template <> struct Construct<true, false, 32> { using Type = Int128; };
|
||||
template <> struct Construct<true, false, 48> { using Type = bInt256; };
|
||||
template <> struct Construct<true, true, 1> { using Type = Float32; };
|
||||
template <> struct Construct<true, true, 2> { using Type = Float32; };
|
||||
template <> struct Construct<true, true, 4> { using Type = Float32; };
|
||||
@ -68,7 +86,7 @@ template <typename A, typename B> struct ResultOfAdditionMultiplication
|
||||
using Type = typename Construct<
|
||||
is_signed_v<A> || is_signed_v<B>,
|
||||
std::is_floating_point_v<A> || std::is_floating_point_v<B>,
|
||||
nextSize(max(sizeof(A), sizeof(B)))>::Type;
|
||||
nextSize2< is_signed_v<A> || is_signed_v<B> >(max(sizeof(A), sizeof(B)))>::Type;
|
||||
};
|
||||
|
||||
template <typename A, typename B> struct ResultOfSubtraction
|
||||
@ -76,7 +94,7 @@ template <typename A, typename B> struct ResultOfSubtraction
|
||||
using Type = typename Construct<
|
||||
true,
|
||||
std::is_floating_point_v<A> || std::is_floating_point_v<B>,
|
||||
nextSize(max(sizeof(A), sizeof(B)))>::Type;
|
||||
nextSize2< is_signed_v<A> || is_signed_v<B> >(max(sizeof(A), sizeof(B)))>::Type;
|
||||
};
|
||||
|
||||
/** When dividing, you always get a floating-point number.
|
||||
@ -100,12 +118,8 @@ template <typename A, typename B> struct ResultOfIntegerDivision
|
||||
*/
|
||||
template <typename A, typename B> struct ResultOfModulo
|
||||
{
|
||||
using Type = std::conditional_t<std::is_floating_point_v<A> || std::is_floating_point_v<B>,
|
||||
Float64,
|
||||
typename Construct<
|
||||
is_signed_v<A> || is_signed_v<B>,
|
||||
false,
|
||||
sizeof(B)>::Type>;
|
||||
using Type0 = typename Construct<is_signed_v<A> || is_signed_v<B>, false, sizeof(B)>::Type;
|
||||
using Type = std::conditional_t<std::is_floating_point_v<A> || std::is_floating_point_v<B>, Float64, Type0>;
|
||||
};
|
||||
|
||||
template <typename A> struct ResultOfNegate
|
||||
@ -113,7 +127,7 @@ template <typename A> struct ResultOfNegate
|
||||
using Type = typename Construct<
|
||||
true,
|
||||
std::is_floating_point_v<A>,
|
||||
is_signed_v<A> ? sizeof(A) : nextSize(sizeof(A))>::Type;
|
||||
is_signed_v<A> ? sizeof(A) : nextSize2<true>(sizeof(A))>::Type;
|
||||
};
|
||||
|
||||
template <typename A> struct ResultOfAbs
|
||||
@ -158,13 +172,14 @@ template <typename A, typename B>
|
||||
struct ResultOfIf
|
||||
{
|
||||
static constexpr bool has_float = std::is_floating_point_v<A> || std::is_floating_point_v<B>;
|
||||
static constexpr bool has_integer = is_integral_v<A> || is_integral_v<B>;
|
||||
static constexpr bool has_integer = is_integer_v<A> || is_integer_v<B>;
|
||||
static constexpr bool has_signed = is_signed_v<A> || is_signed_v<B>;
|
||||
static constexpr bool has_unsigned = !is_signed_v<A> || !is_signed_v<B>;
|
||||
static constexpr bool has_big_int = is_big_int_v<A> || is_big_int_v<B>;
|
||||
|
||||
static constexpr size_t max_size_of_unsigned_integer = max(is_signed_v<A> ? 0 : sizeof(A), is_signed_v<B> ? 0 : sizeof(B));
|
||||
static constexpr size_t max_size_of_signed_integer = max(is_signed_v<A> ? sizeof(A) : 0, is_signed_v<B> ? sizeof(B) : 0);
|
||||
static constexpr size_t max_size_of_integer = max(is_integral_v<A> ? sizeof(A) : 0, is_integral_v<B> ? sizeof(B) : 0);
|
||||
static constexpr size_t max_size_of_integer = max(is_integer_v<A> ? sizeof(A) : 0, is_integer_v<B> ? sizeof(B) : 0);
|
||||
static constexpr size_t max_size_of_float = max(std::is_floating_point_v<A> ? sizeof(A) : 0, std::is_floating_point_v<B> ? sizeof(B) : 0);
|
||||
|
||||
using ConstructedType = typename Construct<has_signed, has_float,
|
||||
@ -173,7 +188,8 @@ struct ResultOfIf
|
||||
? max(sizeof(A), sizeof(B)) * 2
|
||||
: max(sizeof(A), sizeof(B))>::Type;
|
||||
|
||||
using ConstructedWithUUID = std::conditional_t<std::is_same_v<A, UInt128> && std::is_same_v<B, UInt128>, A, ConstructedType>;
|
||||
using ConstructedTypeWithoutUUID = std::conditional_t<std::is_same_v<A, UInt128> || std::is_same_v<B, UInt128>, Error, ConstructedType>;
|
||||
using ConstructedWithUUID = std::conditional_t<std::is_same_v<A, UInt128> && std::is_same_v<B, UInt128>, A, ConstructedTypeWithoutUUID>;
|
||||
|
||||
using Type = std::conditional_t<!IsDecimalNumber<A> && !IsDecimalNumber<B>, ConstructedWithUUID,
|
||||
std::conditional_t<IsDecimalNumber<A> && IsDecimalNumber<B>, std::conditional_t<(sizeof(A) > sizeof(B)), A, B>, Error>>;
|
||||
@ -193,7 +209,7 @@ template <typename A> struct ToInteger
|
||||
// NOTE: This case is applied for 64-bit integers only (for backward compatibility), but could be used for any-bit integers
|
||||
template <typename A, typename B>
|
||||
constexpr bool LeastGreatestSpecialCase =
|
||||
is_integral_v<A> && is_integral_v<B>
|
||||
std::is_integral_v<A> && std::is_integral_v<B>
|
||||
&& (8 == sizeof(A) && sizeof(A) == sizeof(B))
|
||||
&& (is_signed_v<A> ^ is_signed_v<B>);
|
||||
|
||||
@ -209,4 +225,13 @@ using ResultOfGreatest = std::conditional_t<LeastGreatestSpecialCase<A, B>,
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline auto littleBits(const T & x)
|
||||
{
|
||||
if constexpr (is_big_int_v<T>)
|
||||
return x. template convert_to<UInt32>();
|
||||
else
|
||||
return UInt8(x);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ String DatabaseAtomic::getTableDataPath(const ASTCreateQuery & query) const
|
||||
|
||||
void DatabaseAtomic::drop(const Context &)
|
||||
{
|
||||
assert(tables.empty());
|
||||
try
|
||||
{
|
||||
Poco::File(path_to_metadata_symlink).remove();
|
||||
|
@ -367,6 +367,7 @@ ASTPtr DatabaseOnDisk::getCreateDatabaseQuery() const
|
||||
|
||||
void DatabaseOnDisk::drop(const Context & context)
|
||||
{
|
||||
assert(tables.empty());
|
||||
Poco::File(context.getPath() + getDataPath()).remove(false);
|
||||
Poco::File(getMetadataPath()).remove(false);
|
||||
}
|
||||
|
@ -1191,7 +1191,7 @@ void SSDCacheStorage::update(DictionarySourcePtr & source_ptr, const std::vector
|
||||
|
||||
if (update_error_count)
|
||||
{
|
||||
/// TODO: юзать старые значения.
|
||||
/// TODO: use old values
|
||||
|
||||
/// We don't have expired data for that `id` so all we can do is to rethrow `last_exception`.
|
||||
std::rethrow_exception(last_update_exception);
|
||||
|
@ -76,7 +76,7 @@ public:
|
||||
{
|
||||
using time_point_t = std::chrono::system_clock::time_point;
|
||||
using time_point_rep_t = time_point_t::rep;
|
||||
using time_point_urep_t = std::make_unsigned_t<time_point_rep_t>;
|
||||
using time_point_urep_t = make_unsigned_t<time_point_rep_t>;
|
||||
|
||||
time_point_t expiresAt() const;
|
||||
void setExpiresAt(const time_point_t & t);
|
||||
|
@ -455,6 +455,10 @@ public:
|
||||
cannotConvertType("UInt128");
|
||||
}
|
||||
|
||||
bool readInt128(Int128 &) override { cannotConvertType("Int128"); }
|
||||
bool readbInt256(bInt256 &) override { cannotConvertType("Int256"); }
|
||||
bool readbUInt256(bUInt256 &) override { cannotConvertType("UInt256"); }
|
||||
|
||||
bool readFloat32(Float32 &) override
|
||||
{
|
||||
cannotConvertType("Float32");
|
||||
@ -513,6 +517,12 @@ public:
|
||||
cannotConvertType("Decimal128");
|
||||
}
|
||||
|
||||
bool readDecimal256(Decimal256 &, UInt32, UInt32) override
|
||||
{
|
||||
cannotConvertType("Decimal256");
|
||||
}
|
||||
|
||||
|
||||
bool readAggregateFunction(const AggregateFunctionPtr &, AggregateDataPtr, Arena &) override
|
||||
{
|
||||
cannotConvertType("AggregateFunction");
|
||||
@ -641,6 +651,7 @@ public:
|
||||
bool readDecimal32(Decimal32 & decimal, UInt32 precision, UInt32 scale) override { return readDecimal(decimal, precision, scale); }
|
||||
bool readDecimal64(Decimal64 & decimal, UInt32 precision, UInt32 scale) override { return readDecimal(decimal, precision, scale); }
|
||||
bool readDecimal128(Decimal128 & decimal, UInt32 precision, UInt32 scale) override { return readDecimal(decimal, precision, scale); }
|
||||
bool readDecimal256(Decimal256 & decimal, UInt32 precision, UInt32 scale) override { return readDecimal(decimal, precision, scale); }
|
||||
|
||||
bool readAggregateFunction(const AggregateFunctionPtr & function, AggregateDataPtr place, Arena & arena) override
|
||||
{
|
||||
@ -797,7 +808,7 @@ private:
|
||||
template<typename EnumType>
|
||||
bool readEnum(EnumType & value)
|
||||
{
|
||||
if constexpr (!is_integral_v<FromType>)
|
||||
if constexpr (!is_integer_v<FromType>)
|
||||
cannotConvertType("Enum"); // It's not correct to convert floating point to enum.
|
||||
FromType number;
|
||||
if (!readField(number))
|
||||
|
@ -60,7 +60,10 @@ public:
|
||||
bool readNumber(UInt32 & value) { return current_converter->readUInt32(value); }
|
||||
bool readNumber(Int64 & value) { return current_converter->readInt64(value); }
|
||||
bool readNumber(UInt64 & value) { return current_converter->readUInt64(value); }
|
||||
bool readNumber(Int128 & value) { return current_converter->readInt128(value); }
|
||||
bool readNumber(UInt128 & value) { return current_converter->readUInt128(value); }
|
||||
bool readNumber(bInt256 & value) { return current_converter->readbInt256(value); }
|
||||
bool readNumber(bUInt256 & value) { return current_converter->readbUInt256(value); }
|
||||
bool readNumber(Float32 & value) { return current_converter->readFloat32(value); }
|
||||
bool readNumber(Float64 & value) { return current_converter->readFloat64(value); }
|
||||
|
||||
@ -79,6 +82,7 @@ public:
|
||||
bool readDecimal(Decimal32 & decimal, UInt32 precision, UInt32 scale) { return current_converter->readDecimal32(decimal, precision, scale); }
|
||||
bool readDecimal(Decimal64 & decimal, UInt32 precision, UInt32 scale) { return current_converter->readDecimal64(decimal, precision, scale); }
|
||||
bool readDecimal(Decimal128 & decimal, UInt32 precision, UInt32 scale) { return current_converter->readDecimal128(decimal, precision, scale); }
|
||||
bool readDecimal(Decimal256 & decimal, UInt32 precision, UInt32 scale) { return current_converter->readDecimal256(decimal, precision, scale); }
|
||||
|
||||
bool readAggregateFunction(const AggregateFunctionPtr & function, AggregateDataPtr place, Arena & arena) { return current_converter->readAggregateFunction(function, place, arena); }
|
||||
|
||||
@ -145,7 +149,12 @@ private:
|
||||
virtual bool readUInt32(UInt32 &) = 0;
|
||||
virtual bool readInt64(Int64 &) = 0;
|
||||
virtual bool readUInt64(UInt64 &) = 0;
|
||||
virtual bool readInt128(Int128 &) = 0;
|
||||
virtual bool readUInt128(UInt128 &) = 0;
|
||||
|
||||
virtual bool readbInt256(bInt256 &) = 0;
|
||||
virtual bool readbUInt256(bUInt256 &) = 0;
|
||||
|
||||
virtual bool readFloat32(Float32 &) = 0;
|
||||
virtual bool readFloat64(Float64 &) = 0;
|
||||
virtual void prepareEnumMapping8(const std::vector<std::pair<std::string, Int8>> &) = 0;
|
||||
@ -159,6 +168,7 @@ private:
|
||||
virtual bool readDecimal32(Decimal32 &, UInt32, UInt32) = 0;
|
||||
virtual bool readDecimal64(Decimal64 &, UInt32, UInt32) = 0;
|
||||
virtual bool readDecimal128(Decimal128 &, UInt32, UInt32) = 0;
|
||||
virtual bool readDecimal256(Decimal256 &, UInt32, UInt32) = 0;
|
||||
virtual bool readAggregateFunction(const AggregateFunctionPtr &, AggregateDataPtr, Arena &) = 0;
|
||||
};
|
||||
|
||||
@ -220,7 +230,10 @@ public:
|
||||
bool readNumber(UInt32 &) { return false; }
|
||||
bool readNumber(Int64 &) { return false; }
|
||||
bool readNumber(UInt64 &) { return false; }
|
||||
bool readNumber(Int128 &) { return false; }
|
||||
bool readNumber(UInt128 &) { return false; }
|
||||
bool readNumber(bInt256 &) { return false; }
|
||||
bool readNumber(bUInt256 &) { return false; }
|
||||
bool readNumber(Float32 &) { return false; }
|
||||
bool readNumber(Float64 &) { return false; }
|
||||
bool readStringInto(PaddedPODArray<UInt8> &) { return false; }
|
||||
@ -235,6 +248,7 @@ public:
|
||||
bool readDecimal(Decimal32 &, UInt32, UInt32) { return false; }
|
||||
bool readDecimal(Decimal64 &, UInt32, UInt32) { return false; }
|
||||
bool readDecimal(Decimal128 &, UInt32, UInt32) { return false; }
|
||||
bool readDecimal(Decimal256 &, UInt32, UInt32) { return false; }
|
||||
bool readAggregateFunction(const AggregateFunctionPtr &, AggregateDataPtr, Arena &) { return false; }
|
||||
bool canReadMoreValues() const { return false; }
|
||||
};
|
||||
|
@ -317,7 +317,10 @@ public:
|
||||
virtual void writeUInt32(UInt32) override { cannotConvertType("UInt32"); }
|
||||
virtual void writeInt64(Int64) override { cannotConvertType("Int64"); }
|
||||
virtual void writeUInt64(UInt64) override { cannotConvertType("UInt64"); }
|
||||
virtual void writeInt128(Int128) override { cannotConvertType("Int128"); }
|
||||
virtual void writeUInt128(const UInt128 &) override { cannotConvertType("UInt128"); }
|
||||
virtual void writebInt256(const bInt256 &) override { cannotConvertType("Int256"); }
|
||||
virtual void writebUInt256(const bUInt256 &) override { cannotConvertType("UInt256"); }
|
||||
virtual void writeFloat32(Float32) override { cannotConvertType("Float32"); }
|
||||
virtual void writeFloat64(Float64) override { cannotConvertType("Float64"); }
|
||||
virtual void prepareEnumMapping8(const std::vector<std::pair<std::string, Int8>> &) override {}
|
||||
@ -331,6 +334,7 @@ public:
|
||||
virtual void writeDecimal32(Decimal32, UInt32) override { cannotConvertType("Decimal32"); }
|
||||
virtual void writeDecimal64(Decimal64, UInt32) override { cannotConvertType("Decimal64"); }
|
||||
virtual void writeDecimal128(const Decimal128 &, UInt32) override { cannotConvertType("Decimal128"); }
|
||||
virtual void writeDecimal256(const Decimal256 &, UInt32) override { cannotConvertType("Decimal256"); }
|
||||
|
||||
virtual void writeAggregateFunction(const AggregateFunctionPtr &, ConstAggregateDataPtr) override { cannotConvertType("AggregateFunction"); }
|
||||
|
||||
@ -532,7 +536,7 @@ public:
|
||||
|
||||
void writeEnum16(Int16 value) override
|
||||
{
|
||||
if constexpr (!is_integral_v<ToType>)
|
||||
if constexpr (!is_integer_v<ToType>)
|
||||
cannotConvertType("Enum"); // It's not correct to convert enum to floating point.
|
||||
castNumericAndWriteField(value);
|
||||
}
|
||||
|
@ -62,7 +62,12 @@ public:
|
||||
bool writeNumber(UInt32 value) { return writeValueIfPossible(&IConverter::writeUInt32, value); }
|
||||
bool writeNumber(Int64 value) { return writeValueIfPossible(&IConverter::writeInt64, value); }
|
||||
bool writeNumber(UInt64 value) { return writeValueIfPossible(&IConverter::writeUInt64, value); }
|
||||
bool writeNumber(Int128 value) { return writeValueIfPossible(&IConverter::writeInt128, value); }
|
||||
bool writeNumber(UInt128 value) { return writeValueIfPossible(&IConverter::writeUInt128, value); }
|
||||
|
||||
bool writeNumber(bInt256 value) { return writeValueIfPossible(&IConverter::writebInt256, value); }
|
||||
bool writeNumber(bUInt256 value) { return writeValueIfPossible(&IConverter::writebUInt256, value); }
|
||||
|
||||
bool writeNumber(Float32 value) { return writeValueIfPossible(&IConverter::writeFloat32, value); }
|
||||
bool writeNumber(Float64 value) { return writeValueIfPossible(&IConverter::writeFloat64, value); }
|
||||
bool writeString(const StringRef & str) { return writeValueIfPossible(&IConverter::writeString, str); }
|
||||
@ -77,6 +82,7 @@ public:
|
||||
bool writeDecimal(Decimal32 decimal, UInt32 scale) { return writeValueIfPossible(&IConverter::writeDecimal32, decimal, scale); }
|
||||
bool writeDecimal(Decimal64 decimal, UInt32 scale) { return writeValueIfPossible(&IConverter::writeDecimal64, decimal, scale); }
|
||||
bool writeDecimal(const Decimal128 & decimal, UInt32 scale) { return writeValueIfPossible(&IConverter::writeDecimal128, decimal, scale); }
|
||||
bool writeDecimal(const Decimal256 & decimal, UInt32 scale) { return writeValueIfPossible(&IConverter::writeDecimal256, decimal, scale); }
|
||||
bool writeAggregateFunction(const AggregateFunctionPtr & function, ConstAggregateDataPtr place) { return writeValueIfPossible(&IConverter::writeAggregateFunction, function, place); }
|
||||
|
||||
private:
|
||||
@ -147,7 +153,12 @@ private:
|
||||
virtual void writeUInt32(UInt32) = 0;
|
||||
virtual void writeInt64(Int64) = 0;
|
||||
virtual void writeUInt64(UInt64) = 0;
|
||||
virtual void writeInt128(Int128) = 0;
|
||||
virtual void writeUInt128(const UInt128 &) = 0;
|
||||
|
||||
virtual void writebInt256(const bInt256 &) = 0;
|
||||
virtual void writebUInt256(const bUInt256 &) = 0;
|
||||
|
||||
virtual void writeFloat32(Float32) = 0;
|
||||
virtual void writeFloat64(Float64) = 0;
|
||||
virtual void prepareEnumMapping8(const std::vector<std::pair<std::string, Int8>> &) = 0;
|
||||
@ -161,6 +172,7 @@ private:
|
||||
virtual void writeDecimal32(Decimal32, UInt32) = 0;
|
||||
virtual void writeDecimal64(Decimal64, UInt32) = 0;
|
||||
virtual void writeDecimal128(const Decimal128 &, UInt32) = 0;
|
||||
virtual void writeDecimal256(const Decimal256 &, UInt32) = 0;
|
||||
virtual void writeAggregateFunction(const AggregateFunctionPtr &, ConstAggregateDataPtr) = 0;
|
||||
};
|
||||
|
||||
@ -253,7 +265,10 @@ public:
|
||||
bool writeNumber(UInt32 /* value */) { return false; }
|
||||
bool writeNumber(Int64 /* value */) { return false; }
|
||||
bool writeNumber(UInt64 /* value */) { return false; }
|
||||
bool writeNumber(Int128 /* value */) { return false; }
|
||||
bool writeNumber(UInt128 /* value */) { return false; }
|
||||
bool writeNumber(bInt256 /* value */) { return false; }
|
||||
bool writeNumber(bUInt256 /* value */) { return false; }
|
||||
bool writeNumber(Float32 /* value */) { return false; }
|
||||
bool writeNumber(Float64 /* value */) { return false; }
|
||||
bool writeString(const StringRef & /* value */) { return false; }
|
||||
@ -268,6 +283,7 @@ public:
|
||||
bool writeDecimal(Decimal32 /* decimal */, UInt32 /* scale */) { return false; }
|
||||
bool writeDecimal(Decimal64 /* decimal */, UInt32 /* scale */) { return false; }
|
||||
bool writeDecimal(const Decimal128 & /* decimal */, UInt32 /* scale */) { return false; }
|
||||
bool writeDecimal(const Decimal256 & /* decimal */, UInt32 /* scale */) { return false; }
|
||||
bool writeAggregateFunction(const AggregateFunctionPtr & /* function */, ConstAggregateDataPtr /* place */) { return false; }
|
||||
};
|
||||
|
||||
|
@ -49,7 +49,13 @@ template <typename A, typename B>
|
||||
inline auto checkedDivision(A a, B b)
|
||||
{
|
||||
throwIfDivisionLeadsToFPE(a, b);
|
||||
return a / b;
|
||||
|
||||
if constexpr (is_big_int_v<A> && is_big_int_v<B>)
|
||||
return static_cast<A>(a / b);
|
||||
else if constexpr (!is_big_int_v<A> && is_big_int_v<B>)
|
||||
return static_cast<A>(B(a) / b);
|
||||
else
|
||||
return a / b;
|
||||
}
|
||||
|
||||
|
||||
@ -64,11 +70,26 @@ struct DivideIntegralImpl
|
||||
template <typename Result = ResultType>
|
||||
static inline Result apply(A a, B b)
|
||||
{
|
||||
if constexpr (is_big_int_v<A> && std::is_floating_point_v<B>)
|
||||
return Result(static_cast<B>(a) / b);
|
||||
else if constexpr (is_big_int_v<B> && std::is_floating_point_v<A>)
|
||||
return a / static_cast<Result>(b);
|
||||
else if constexpr (is_big_int_v<A> && std::is_same_v<B, UInt8>)
|
||||
return static_cast<Result>(checkedDivision(make_signed_t<A>(a), Int16(b)));
|
||||
else if constexpr (is_big_int_v<B> && std::is_same_v<A, UInt8>)
|
||||
return checkedDivision(Int16(a), make_signed_t<B>(b));
|
||||
/// Otherwise overflow may occur due to integer promotion. Example: int8_t(-1) / uint64_t(2).
|
||||
/// NOTE: overflow is still possible when dividing large signed number to large unsigned number or vice-versa. But it's less harmful.
|
||||
if constexpr (is_integral_v<A> && is_integral_v<B> && (is_signed_v<A> || is_signed_v<B>))
|
||||
return checkedDivision(std::make_signed_t<A>(a),
|
||||
sizeof(A) > sizeof(B) ? std::make_signed_t<A>(b) : std::make_signed_t<B>(b));
|
||||
else if constexpr (is_signed_v<A> || is_signed_v<B>)
|
||||
{
|
||||
if constexpr (is_integer_v<A> && is_integer_v<B>)
|
||||
{
|
||||
return checkedDivision(make_signed_t<A>(a),
|
||||
sizeof(A) > sizeof(B) ? make_signed_t<A>(b) : make_signed_t<B>(b));
|
||||
}
|
||||
else
|
||||
return checkedDivision(a, b);
|
||||
}
|
||||
else
|
||||
return checkedDivision(a, b);
|
||||
}
|
||||
@ -78,11 +99,28 @@ struct DivideIntegralImpl
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename Result, typename A, typename B>
|
||||
inline Result applyBigIntModulo(A a, B b)
|
||||
{
|
||||
if constexpr (std::is_same_v<A, UInt8>)
|
||||
return UInt16(a) % b;
|
||||
else if constexpr (std::is_same_v<B, UInt8>)
|
||||
return static_cast<UInt16>(a % UInt16(b));
|
||||
else if constexpr (sizeof(A) > sizeof(B))
|
||||
return static_cast<Result>(a % A(b));
|
||||
else
|
||||
return static_cast<Result>(B(a) % b);
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
struct ModuloImpl
|
||||
{
|
||||
using ResultType = typename NumberTraits::ResultOfModulo<A, B>::Type;
|
||||
using IntegerAType = typename NumberTraits::ToInteger<A>::Type;
|
||||
using IntegerBType = typename NumberTraits::ToInteger<B>::Type;
|
||||
|
||||
static const constexpr bool allow_fixed_string = false;
|
||||
static const constexpr bool is_special = is_big_int_v<IntegerAType> || is_big_int_v<IntegerBType>;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static inline Result apply(A a, B b)
|
||||
@ -94,8 +132,12 @@ struct ModuloImpl
|
||||
}
|
||||
else
|
||||
{
|
||||
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<A>::Type(a), typename NumberTraits::ToInteger<B>::Type(b));
|
||||
return typename NumberTraits::ToInteger<A>::Type(a) % typename NumberTraits::ToInteger<B>::Type(b);
|
||||
throwIfDivisionLeadsToFPE(IntegerAType(a), IntegerBType(b));
|
||||
|
||||
if constexpr (is_special)
|
||||
return applyBigIntModulo<Result>(IntegerAType(a), IntegerBType(b));
|
||||
else
|
||||
return IntegerAType(a) % IntegerBType(b);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,8 @@ struct DecimalBinaryOperation
|
||||
using ArrayC = typename ColumnDecimal<ResultType>::Container;
|
||||
using SelfNoOverflow = DecimalBinaryOperation<A, B, Operation, ResultType_, false>;
|
||||
|
||||
static void vectorVector(const ArrayA & a, const ArrayB & b, ArrayC & c, ResultType scale_a, ResultType scale_b, bool check_overflow)
|
||||
static void vectorVector(const ArrayA & a, const ArrayB & b, ArrayC & c,
|
||||
NativeResultType scale_a, NativeResultType scale_b, bool check_overflow)
|
||||
{
|
||||
if (check_overflow)
|
||||
vectorVector(a, b, c, scale_a, scale_b);
|
||||
@ -217,7 +218,8 @@ struct DecimalBinaryOperation
|
||||
SelfNoOverflow::vectorVector(a, b, c, scale_a, scale_b);
|
||||
}
|
||||
|
||||
static void vectorConstant(const ArrayA & a, B b, ArrayC & c, ResultType scale_a, ResultType scale_b, bool check_overflow)
|
||||
static void vectorConstant(const ArrayA & a, B b, ArrayC & c,
|
||||
NativeResultType scale_a, NativeResultType scale_b, bool check_overflow)
|
||||
{
|
||||
if (check_overflow)
|
||||
vectorConstant(a, b, c, scale_a, scale_b);
|
||||
@ -225,7 +227,8 @@ struct DecimalBinaryOperation
|
||||
SelfNoOverflow::vectorConstant(a, b, c, scale_a, scale_b);
|
||||
}
|
||||
|
||||
static void constantVector(A a, const ArrayB & b, ArrayC & c, ResultType scale_a, ResultType scale_b, bool check_overflow)
|
||||
static void constantVector(A a, const ArrayB & b, ArrayC & c,
|
||||
NativeResultType scale_a, NativeResultType scale_b, bool check_overflow)
|
||||
{
|
||||
if (check_overflow)
|
||||
constantVector(a, b, c, scale_a, scale_b);
|
||||
@ -233,7 +236,7 @@ struct DecimalBinaryOperation
|
||||
SelfNoOverflow::constantVector(a, b, c, scale_a, scale_b);
|
||||
}
|
||||
|
||||
static ResultType constantConstant(A a, B b, ResultType scale_a, ResultType scale_b, bool check_overflow)
|
||||
static ResultType constantConstant(A a, B b, NativeResultType scale_a, NativeResultType scale_b, bool check_overflow)
|
||||
{
|
||||
if (check_overflow)
|
||||
return constantConstant(a, b, scale_a, scale_b);
|
||||
@ -242,7 +245,7 @@ struct DecimalBinaryOperation
|
||||
}
|
||||
|
||||
static void NO_INLINE vectorVector(const ArrayA & a, const ArrayB & b, ArrayC & c,
|
||||
ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
|
||||
NativeResultType scale_a [[maybe_unused]], NativeResultType scale_b [[maybe_unused]])
|
||||
{
|
||||
size_t size = a.size();
|
||||
if constexpr (is_plus_minus_compare)
|
||||
@ -273,7 +276,7 @@ struct DecimalBinaryOperation
|
||||
}
|
||||
|
||||
static void NO_INLINE vectorConstant(const ArrayA & a, B b, ArrayC & c,
|
||||
ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
|
||||
NativeResultType scale_a [[maybe_unused]], NativeResultType scale_b [[maybe_unused]])
|
||||
{
|
||||
size_t size = a.size();
|
||||
if constexpr (is_plus_minus_compare)
|
||||
@ -304,7 +307,7 @@ struct DecimalBinaryOperation
|
||||
}
|
||||
|
||||
static void NO_INLINE constantVector(A a, const ArrayB & b, ArrayC & c,
|
||||
ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
|
||||
NativeResultType scale_a [[maybe_unused]], NativeResultType scale_b [[maybe_unused]])
|
||||
{
|
||||
size_t size = b.size();
|
||||
if constexpr (is_plus_minus_compare)
|
||||
@ -334,7 +337,7 @@ struct DecimalBinaryOperation
|
||||
c[i] = apply(a, b[i]);
|
||||
}
|
||||
|
||||
static ResultType constantConstant(A a, B b, ResultType scale_a [[maybe_unused]], ResultType scale_b [[maybe_unused]])
|
||||
static ResultType constantConstant(A a, B b, NativeResultType scale_a [[maybe_unused]], NativeResultType scale_b [[maybe_unused]])
|
||||
{
|
||||
if constexpr (is_plus_minus_compare)
|
||||
{
|
||||
@ -349,8 +352,68 @@ struct DecimalBinaryOperation
|
||||
}
|
||||
|
||||
private:
|
||||
/// there's implicit type conversion here
|
||||
static NativeResultType apply(NativeResultType a, NativeResultType b)
|
||||
template <typename T, typename U>
|
||||
static NativeResultType apply(const T & a, const U & b)
|
||||
{
|
||||
if constexpr (OverBigInt<T> || OverBigInt<U>)
|
||||
{
|
||||
if constexpr (IsDecimalNumber<T>)
|
||||
return apply(a.value, b);
|
||||
else if constexpr (IsDecimalNumber<U>)
|
||||
return apply(a, b.value);
|
||||
else if constexpr (std::is_same_v<T, UInt8>)
|
||||
return apply(UInt16(a), b);
|
||||
else if constexpr (std::is_same_v<U, UInt8>)
|
||||
return apply(a, UInt16(b));
|
||||
else
|
||||
return applyNative(static_cast<NativeResultType>(a), static_cast<NativeResultType>(b));
|
||||
}
|
||||
else
|
||||
return applyNative(a, b);
|
||||
}
|
||||
|
||||
template <bool scale_left, typename T, typename U>
|
||||
static NativeResultType applyScaled(const T & a, const U & b, NativeResultType scale)
|
||||
{
|
||||
if constexpr (OverBigInt<T> || OverBigInt<U>)
|
||||
{
|
||||
if constexpr (IsDecimalNumber<T>)
|
||||
return applyScaled<scale_left>(a.value, b, scale);
|
||||
else if constexpr (IsDecimalNumber<U>)
|
||||
return applyScaled<scale_left>(a, b.value, scale);
|
||||
else if constexpr (std::is_same_v<T, UInt8>)
|
||||
return applyScaled<scale_left>(UInt16(a), b, scale);
|
||||
else if constexpr (std::is_same_v<U, UInt8>)
|
||||
return applyScaled<scale_left>(a, UInt16(b), scale);
|
||||
else
|
||||
return applyNativeScaled<scale_left>(static_cast<NativeResultType>(a), static_cast<NativeResultType>(b), scale);
|
||||
}
|
||||
else
|
||||
return applyNativeScaled<scale_left>(a, b, scale);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
static NativeResultType applyScaledDiv(const T & a, const U & b, NativeResultType scale)
|
||||
{
|
||||
if constexpr (OverBigInt<T> || OverBigInt<U>)
|
||||
{
|
||||
if constexpr (IsDecimalNumber<T>)
|
||||
return applyScaledDiv(a.value, b, scale);
|
||||
else if constexpr (IsDecimalNumber<U>)
|
||||
return applyScaledDiv(a, b.value, scale);
|
||||
else if constexpr (std::is_same_v<T, UInt8>)
|
||||
return applyScaledDiv(UInt16(a), b, scale);
|
||||
else if constexpr (std::is_same_v<U, UInt8>)
|
||||
return applyScaledDiv(a, UInt16(b), scale);
|
||||
else
|
||||
return applyNativeScaledDiv(static_cast<NativeResultType>(a), static_cast<NativeResultType>(b), scale);
|
||||
}
|
||||
else
|
||||
return applyNativeScaledDiv(a, b, scale);
|
||||
}
|
||||
|
||||
/// there's implicit type convertion here
|
||||
static NativeResultType applyNative(NativeResultType a, NativeResultType b)
|
||||
{
|
||||
if constexpr (can_overflow && _check_overflow)
|
||||
{
|
||||
@ -364,7 +427,7 @@ private:
|
||||
}
|
||||
|
||||
template <bool scale_left>
|
||||
static NO_SANITIZE_UNDEFINED NativeResultType applyScaled(NativeResultType a, NativeResultType b, NativeResultType scale)
|
||||
static NO_SANITIZE_UNDEFINED NativeResultType applyNativeScaled(NativeResultType a, NativeResultType b, NativeResultType scale)
|
||||
{
|
||||
if constexpr (is_plus_minus_compare)
|
||||
{
|
||||
@ -399,7 +462,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
static NO_SANITIZE_UNDEFINED NativeResultType applyScaledDiv(NativeResultType a, NativeResultType b, NativeResultType scale)
|
||||
static NO_SANITIZE_UNDEFINED NativeResultType applyNativeScaledDiv(NativeResultType a, NativeResultType b, NativeResultType scale)
|
||||
{
|
||||
if constexpr (is_division)
|
||||
{
|
||||
@ -443,6 +506,14 @@ template <> inline constexpr bool IsIntegral<DataTypeInt16> = true;
|
||||
template <> inline constexpr bool IsIntegral<DataTypeInt32> = true;
|
||||
template <> inline constexpr bool IsIntegral<DataTypeInt64> = true;
|
||||
|
||||
template <typename DataType> constexpr bool IsExtended = false;
|
||||
template <> inline constexpr bool IsExtended<DataTypeUInt256> = true;
|
||||
template <> inline constexpr bool IsExtended<DataTypeInt128> = true;
|
||||
template <> inline constexpr bool IsExtended<DataTypeInt256> = true;
|
||||
|
||||
template <typename DataType> constexpr bool IsIntegralOrExtended = IsIntegral<DataType> || IsExtended<DataType>;
|
||||
template <typename DataType> constexpr bool IsIntegralOrExtendedOrDecimal = IsIntegralOrExtended<DataType> || IsDataTypeDecimal<DataType>;
|
||||
|
||||
template <typename DataType> constexpr bool IsFloatingPoint = false;
|
||||
template <> inline constexpr bool IsFloatingPoint<DataTypeFloat32> = true;
|
||||
template <> inline constexpr bool IsFloatingPoint<DataTypeFloat64> = true;
|
||||
@ -452,6 +523,9 @@ template <> inline constexpr bool IsDateOrDateTime<DataTypeDate> = true;
|
||||
template <> inline constexpr bool IsDateOrDateTime<DataTypeDateTime> = true;
|
||||
|
||||
template <typename T0, typename T1> constexpr bool UseLeftDecimal = false;
|
||||
template <> inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal256>, DataTypeDecimal<Decimal128>> = true;
|
||||
template <> inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal256>, DataTypeDecimal<Decimal64>> = true;
|
||||
template <> inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal256>, DataTypeDecimal<Decimal32>> = true;
|
||||
template <> inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal128>, DataTypeDecimal<Decimal32>> = true;
|
||||
template <> inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal128>, DataTypeDecimal<Decimal64>> = true;
|
||||
template <> inline constexpr bool UseLeftDecimal<DataTypeDecimal<Decimal64>, DataTypeDecimal<Decimal32>> = true;
|
||||
@ -484,11 +558,11 @@ public:
|
||||
Case<!allow_decimal && (IsDataTypeDecimal<LeftDataType> || IsDataTypeDecimal<RightDataType>), InvalidType>,
|
||||
Case<IsDataTypeDecimal<LeftDataType> && IsDataTypeDecimal<RightDataType> && UseLeftDecimal<LeftDataType, RightDataType>, LeftDataType>,
|
||||
Case<IsDataTypeDecimal<LeftDataType> && IsDataTypeDecimal<RightDataType>, RightDataType>,
|
||||
Case<IsDataTypeDecimal<LeftDataType> && !IsDataTypeDecimal<RightDataType> && IsIntegral<RightDataType>, LeftDataType>,
|
||||
Case<!IsDataTypeDecimal<LeftDataType> && IsDataTypeDecimal<RightDataType> && IsIntegral<LeftDataType>, RightDataType>,
|
||||
Case<IsDataTypeDecimal<LeftDataType> && IsIntegralOrExtended<RightDataType>, LeftDataType>,
|
||||
Case<IsDataTypeDecimal<RightDataType> && IsIntegralOrExtended<LeftDataType>, RightDataType>,
|
||||
/// Decimal <op> Real is not supported (traditional DBs convert Decimal <op> Real to Real)
|
||||
Case<IsDataTypeDecimal<LeftDataType> && !IsDataTypeDecimal<RightDataType> && !IsIntegral<RightDataType>, InvalidType>,
|
||||
Case<!IsDataTypeDecimal<LeftDataType> && IsDataTypeDecimal<RightDataType> && !IsIntegral<LeftDataType>, InvalidType>,
|
||||
Case<IsDataTypeDecimal<LeftDataType> && !IsIntegralOrExtendedOrDecimal<RightDataType>, InvalidType>,
|
||||
Case<IsDataTypeDecimal<RightDataType> && !IsIntegralOrExtendedOrDecimal<LeftDataType>, InvalidType>,
|
||||
/// number <op> number -> see corresponding impl
|
||||
Case<!IsDateOrDateTime<LeftDataType> && !IsDateOrDateTime<RightDataType>,
|
||||
DataTypeFromFieldType<typename Op::ResultType>>,
|
||||
@ -528,10 +602,13 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
DataTypeUInt16,
|
||||
DataTypeUInt32,
|
||||
DataTypeUInt64,
|
||||
DataTypeUInt256,
|
||||
DataTypeInt8,
|
||||
DataTypeInt16,
|
||||
DataTypeInt32,
|
||||
DataTypeInt64,
|
||||
DataTypeInt128,
|
||||
DataTypeInt256,
|
||||
DataTypeFloat32,
|
||||
DataTypeFloat64,
|
||||
DataTypeDate,
|
||||
@ -539,6 +616,7 @@ class FunctionBinaryArithmetic : public IFunction
|
||||
DataTypeDecimal<Decimal32>,
|
||||
DataTypeDecimal<Decimal64>,
|
||||
DataTypeDecimal<Decimal128>,
|
||||
DataTypeDecimal<Decimal256>,
|
||||
DataTypeFixedString
|
||||
>(type, std::forward<F>(f));
|
||||
}
|
||||
|
@ -76,8 +76,18 @@ private:
|
||||
if (rows_remaining != 0)
|
||||
{
|
||||
RightType right_src_remaining[Impl::rows_per_iteration];
|
||||
memcpy(right_src_remaining, &right_src_data[rows_size], rows_remaining * sizeof(RightType));
|
||||
memset(right_src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(RightType));
|
||||
if constexpr (!is_big_int_v<RightType> && !std::is_same_v<RightType, Decimal256>)
|
||||
{
|
||||
memcpy(right_src_remaining, &right_src_data[rows_size], rows_remaining * sizeof(RightType));
|
||||
memset(right_src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(RightType));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < rows_remaining; i++)
|
||||
right_src_remaining[i] = right_src_data[rows_size + i];
|
||||
for (size_t i = rows_remaining; i < Impl::rows_per_iteration; i++)
|
||||
right_src_remaining[i] = 0;
|
||||
}
|
||||
Float64 dst_remaining[Impl::rows_per_iteration];
|
||||
|
||||
Impl::execute(left_src_data, right_src_remaining, dst_remaining);
|
||||
@ -114,11 +124,32 @@ private:
|
||||
if (rows_remaining != 0)
|
||||
{
|
||||
LeftType left_src_remaining[Impl::rows_per_iteration];
|
||||
memcpy(left_src_remaining, &left_src_data[rows_size], rows_remaining * sizeof(LeftType));
|
||||
memset(left_src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(LeftType));
|
||||
if constexpr (!is_big_int_v<LeftType> && !std::is_same_v<LeftType, Decimal256>)
|
||||
{
|
||||
memcpy(left_src_remaining, &left_src_data[rows_size], rows_remaining * sizeof(LeftType));
|
||||
memset(left_src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(LeftType));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < rows_remaining; i++)
|
||||
left_src_remaining[i] = left_src_data[rows_size + i];
|
||||
for (size_t i = rows_remaining; i < Impl::rows_per_iteration; i++)
|
||||
left_src_remaining[i] = 0;
|
||||
}
|
||||
|
||||
RightType right_src_remaining[Impl::rows_per_iteration];
|
||||
memcpy(right_src_remaining, &right_src_data[rows_size], rows_remaining * sizeof(RightType));
|
||||
memset(right_src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(RightType));
|
||||
if constexpr (!is_big_int_v<RightType> && !std::is_same_v<RightType, Decimal256>)
|
||||
{
|
||||
memcpy(right_src_remaining, &right_src_data[rows_size], rows_remaining * sizeof(RightType));
|
||||
memset(right_src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(RightType));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < rows_remaining; i++)
|
||||
right_src_remaining[i] = right_src_data[rows_size + i];
|
||||
for (size_t i = rows_remaining; i < Impl::rows_per_iteration; i++)
|
||||
right_src_remaining[i] = 0;
|
||||
}
|
||||
Float64 dst_remaining[Impl::rows_per_iteration];
|
||||
|
||||
Impl::execute(left_src_remaining, right_src_remaining, dst_remaining);
|
||||
@ -149,8 +180,19 @@ private:
|
||||
if (rows_remaining != 0)
|
||||
{
|
||||
LeftType left_src_remaining[Impl::rows_per_iteration];
|
||||
memcpy(left_src_remaining, &left_src_data[rows_size], rows_remaining * sizeof(LeftType));
|
||||
memset(left_src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(LeftType));
|
||||
if constexpr (!is_big_int_v<LeftType> && !std::is_same_v<LeftType, Decimal256>)
|
||||
{
|
||||
memcpy(left_src_remaining, &left_src_data[rows_size], rows_remaining * sizeof(LeftType));
|
||||
memset(left_src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(LeftType));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < rows_remaining; i++)
|
||||
left_src_remaining[i] = left_src_data[rows_size + i];
|
||||
for (size_t i = rows_remaining; i < Impl::rows_per_iteration; i++)
|
||||
left_src_remaining[i] = 0;
|
||||
}
|
||||
|
||||
Float64 dst_remaining[Impl::rows_per_iteration];
|
||||
|
||||
Impl::execute(left_src_remaining, right_src_data, dst_remaining);
|
||||
|
@ -67,7 +67,7 @@ private:
|
||||
{
|
||||
PODArray<Float64> tmp_vec(size);
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
tmp_vec[i] = src_data[i];
|
||||
tmp_vec[i] = static_cast<Float64>(src_data[i]);
|
||||
|
||||
Impl::execute(tmp_vec.data(), size, dst_data);
|
||||
}
|
||||
@ -87,13 +87,27 @@ private:
|
||||
if (rows_remaining != 0)
|
||||
{
|
||||
T src_remaining[Impl::rows_per_iteration];
|
||||
memcpy(src_remaining, &src_data[rows_size], rows_remaining * sizeof(T));
|
||||
memset(src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(T));
|
||||
if constexpr (is_big_int_v<T> || std::is_same_v<T, Decimal256>)
|
||||
{
|
||||
for (size_t i = 0; i < rows_remaining; i++)
|
||||
src_remaining[i] = src_data[rows_size + i];
|
||||
for (size_t i = rows_remaining; i < Impl::rows_per_iteration; i++)
|
||||
src_remaining[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(src_remaining, &src_data[rows_size], rows_remaining * sizeof(T));
|
||||
memset(src_remaining + rows_remaining, 0, (Impl::rows_per_iteration - rows_remaining) * sizeof(T));
|
||||
}
|
||||
ReturnType dst_remaining[Impl::rows_per_iteration];
|
||||
|
||||
Impl::execute(src_remaining, dst_remaining);
|
||||
|
||||
memcpy(&dst_data[rows_size], dst_remaining, rows_remaining * sizeof(ReturnType));
|
||||
if constexpr (is_big_int_v<T> || std::is_same_v<T, Decimal256>)
|
||||
for (size_t i = 0; i < rows_remaining; i++)
|
||||
dst_data[rows_size + i] = dst_remaining[i];
|
||||
else
|
||||
memcpy(&dst_data[rows_size], dst_remaining, rows_remaining * sizeof(ReturnType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user