diff --git a/base/base/CMakeLists.txt b/base/base/CMakeLists.txt
index 548ba01d86a4..610877eae734 100644
--- a/base/base/CMakeLists.txt
+++ b/base/base/CMakeLists.txt
@@ -13,6 +13,7 @@ set (SRCS
cgroupsv2.cpp
coverage.cpp
demangle.cpp
+ Decimal.cpp
getAvailableMemoryAmount.cpp
getFQDNOrHostName.cpp
getMemoryAmount.cpp
diff --git a/base/base/Decimal.cpp b/base/base/Decimal.cpp
new file mode 100644
index 000000000000..7e65c0eb8d12
--- /dev/null
+++ b/base/base/Decimal.cpp
@@ -0,0 +1,87 @@
+#include
+#include
+
+namespace DB
+{
+
+/// Explicit template instantiations.
+
+#define FOR_EACH_UNDERLYING_DECIMAL_TYPE(M) \
+ M(Int32) \
+ M(Int64) \
+ M(Int128) \
+ M(Int256)
+
+#define FOR_EACH_UNDERLYING_DECIMAL_TYPE_PASS(M, X) \
+ M(Int32, X) \
+ M(Int64, X) \
+ M(Int128, X) \
+ M(Int256, X)
+
+template const Decimal & Decimal::operator += (const T & x) { value += x; return *this; }
+template const Decimal & Decimal::operator -= (const T & x) { value -= x; return *this; }
+template const Decimal & Decimal::operator *= (const T & x) { value *= x; return *this; }
+template const Decimal & Decimal::operator /= (const T & x) { value /= x; return *this; }
+template const Decimal & Decimal::operator %= (const T & x) { value %= x; return *this; }
+
+template void NO_SANITIZE_UNDEFINED Decimal::addOverflow(const T & x) { value += x; }
+
+/// Maybe this explicit instantiation affects performance since operators cannot be inlined.
+
+template template const Decimal & Decimal::operator += (const Decimal & x) { value += static_cast(x.value); return *this; }
+template template const Decimal & Decimal::operator -= (const Decimal & x) { value -= static_cast(x.value); return *this; }
+template template const Decimal & Decimal::operator *= (const Decimal & x) { value *= static_cast(x.value); return *this; }
+template template const Decimal & Decimal::operator /= (const Decimal & x) { value /= static_cast(x.value); return *this; }
+template template const Decimal & Decimal::operator %= (const Decimal & x) { value %= static_cast(x.value); return *this; }
+
+#define DISPATCH(TYPE_T, TYPE_U) \
+ template const Decimal & Decimal::operator += (const Decimal & x); \
+ template const Decimal & Decimal::operator -= (const Decimal & x); \
+ template const Decimal & Decimal::operator *= (const Decimal & x); \
+ template const Decimal & Decimal::operator /= (const Decimal & x); \
+ template const Decimal & Decimal::operator %= (const Decimal & x);
+#define INVOKE(X) FOR_EACH_UNDERLYING_DECIMAL_TYPE_PASS(DISPATCH, X)
+FOR_EACH_UNDERLYING_DECIMAL_TYPE(INVOKE);
+#undef INVOKE
+#undef DISPATCH
+
+#define DISPATCH(TYPE) template struct Decimal;
+FOR_EACH_UNDERLYING_DECIMAL_TYPE(DISPATCH)
+#undef DISPATCH
+
+template bool operator< (const Decimal & x, const Decimal & y) { return x.value < y.value; }
+template bool operator> (const Decimal & x, const Decimal & y) { return x.value > y.value; }
+template bool operator<= (const Decimal & x, const Decimal & y) { return x.value <= y.value; }
+template bool operator>= (const Decimal & x, const Decimal & y) { return x.value >= y.value; }
+template bool operator== (const Decimal & x, const Decimal & y) { return x.value == y.value; }
+template bool operator!= (const Decimal & x, const Decimal & y) { return x.value != y.value; }
+
+#define DISPATCH(TYPE) \
+template bool operator< (const Decimal & x, const Decimal & y); \
+template bool operator> (const Decimal & x, const Decimal & y); \
+template bool operator<= (const Decimal & x, const Decimal & y); \
+template bool operator>= (const Decimal & x, const Decimal & y); \
+template bool operator== (const Decimal & x, const Decimal & y); \
+template bool operator!= (const Decimal & x, const Decimal & y);
+FOR_EACH_UNDERLYING_DECIMAL_TYPE(DISPATCH)
+#undef DISPATCH
+
+
+template Decimal operator+ (const Decimal & x, const Decimal & y) { return x.value + y.value; }
+template Decimal operator- (const Decimal & x, const Decimal & y) { return x.value - y.value; }
+template Decimal operator* (const Decimal & x, const Decimal & y) { return x.value * y.value; }
+template Decimal operator/ (const Decimal & x, const Decimal & y) { return x.value / y.value; }
+template Decimal operator- (const Decimal & x) { return -x.value; }
+
+#define DISPATCH(TYPE) \
+template Decimal operator+ (const Decimal & x, const Decimal & y); \
+template Decimal operator- (const Decimal & x, const Decimal & y); \
+template Decimal operator* (const Decimal & x, const Decimal & y); \
+template Decimal operator/ (const Decimal & x, const Decimal & y); \
+template Decimal operator- (const Decimal & x);
+FOR_EACH_UNDERLYING_DECIMAL_TYPE(DISPATCH)
+#undef DISPATCH
+
+#undef FOR_EACH_UNDERLYING_DECIMAL_TYPE_PASS
+#undef FOR_EACH_UNDERLYING_DECIMAL_TYPE
+}
diff --git a/base/base/Decimal.h b/base/base/Decimal.h
index 66ff623217cb..42f9e67c49df 100644
--- a/base/base/Decimal.h
+++ b/base/base/Decimal.h
@@ -2,6 +2,7 @@
#include
#include
+#include
#include
@@ -10,6 +11,18 @@ namespace DB
template struct Decimal;
class DateTime64;
+#define FOR_EACH_UNDERLYING_DECIMAL_TYPE(M) \
+ M(Int32) \
+ M(Int64) \
+ M(Int128) \
+ M(Int256)
+
+#define FOR_EACH_UNDERLYING_DECIMAL_TYPE_PASS(M, X) \
+ M(Int32, X) \
+ M(Int64, X) \
+ M(Int128, X) \
+ M(Int256, X)
+
using Decimal32 = Decimal;
using Decimal64 = Decimal;
using Decimal128 = Decimal;
@@ -50,36 +63,73 @@ struct Decimal
return static_cast(value);
}
- const Decimal & operator += (const T & x) { value += x; return *this; }
- const Decimal & operator -= (const T & x) { value -= x; return *this; }
- const Decimal & operator *= (const T & x) { value *= x; return *this; }
- const Decimal & operator /= (const T & x) { value /= x; return *this; }
- const Decimal & operator %= (const T & x) { value %= x; return *this; }
+ const Decimal & operator += (const T & x);
+ const Decimal & operator -= (const T & x);
+ const Decimal & operator *= (const T & x);
+ const Decimal & operator /= (const T & x);
+ const Decimal & operator %= (const T & x);
- template const Decimal & operator += (const Decimal & x) { value += x.value; return *this; }
- template const Decimal & operator -= (const Decimal & x) { value -= x.value; return *this; }
- template const Decimal & operator *= (const Decimal & x) { value *= x.value; return *this; }
- template const Decimal & operator /= (const Decimal & x) { value /= x.value; return *this; }
- template const Decimal & operator %= (const Decimal & x) { value %= x.value; return *this; }
+ template const Decimal & operator += (const Decimal & x);
+ template const Decimal & operator -= (const Decimal & x);
+ template const Decimal & operator *= (const Decimal & x);
+ template const Decimal & operator /= (const Decimal & x);
+ template const Decimal & operator %= (const Decimal & x);
/// This is to avoid UB for sumWithOverflow()
- void NO_SANITIZE_UNDEFINED addOverflow(const T & x) { value += x; }
+ void NO_SANITIZE_UNDEFINED addOverflow(const T & x);
T value;
};
-template inline bool operator< (const Decimal & x, const Decimal & y) { return x.value < y.value; }
-template inline bool operator> (const Decimal & x, const Decimal & y) { return x.value > y.value; }
-template inline bool operator<= (const Decimal & x, const Decimal & y) { return x.value <= y.value; }
-template inline bool operator>= (const Decimal & x, const Decimal & y) { return x.value >= y.value; }
-template inline bool operator== (const Decimal & x, const Decimal & y) { return x.value == y.value; }
-template inline bool operator!= (const Decimal & x, const Decimal & y) { return x.value != y.value; }
-
-template inline Decimal operator+ (const Decimal & x, const Decimal & y) { return x.value + y.value; }
-template inline Decimal operator- (const Decimal & x, const Decimal & y) { return x.value - y.value; }
-template inline Decimal operator* (const Decimal & x, const Decimal & y) { return x.value * y.value; }
-template inline Decimal operator/ (const Decimal & x, const Decimal & y) { return x.value / y.value; }
-template inline Decimal operator- (const Decimal & x) { return -x.value; }
+#define DISPATCH(TYPE) extern template struct Decimal;
+FOR_EACH_UNDERLYING_DECIMAL_TYPE(DISPATCH)
+#undef DISPATCH
+
+#define DISPATCH(TYPE_T, TYPE_U) \
+ extern template const Decimal & Decimal::operator += (const Decimal & x); \
+ extern template const Decimal & Decimal::operator -= (const Decimal & x); \
+ extern template const Decimal & Decimal::operator *= (const Decimal & x); \
+ extern template const Decimal & Decimal::operator /= (const Decimal & x); \
+ extern template const Decimal & Decimal::operator %= (const Decimal & x);
+#define INVOKE(X) FOR_EACH_UNDERLYING_DECIMAL_TYPE_PASS(DISPATCH, X)
+FOR_EACH_UNDERLYING_DECIMAL_TYPE(INVOKE);
+#undef INVOKE
+#undef DISPATCH
+
+template bool operator< (const Decimal & x, const Decimal & y);
+template bool operator> (const Decimal & x, const Decimal & y);
+template bool operator<= (const Decimal & x, const Decimal & y);
+template bool operator>= (const Decimal & x, const Decimal & y);
+template bool operator== (const Decimal & x, const Decimal & y);
+template bool operator!= (const Decimal & x, const Decimal & y);
+
+#define DISPATCH(TYPE) \
+extern template bool operator< (const Decimal & x, const Decimal & y); \
+extern template bool operator> (const Decimal & x, const Decimal & y); \
+extern template bool operator<= (const Decimal & x, const Decimal & y); \
+extern template bool operator>= (const Decimal & x, const Decimal & y); \
+extern template bool operator== (const Decimal & x, const Decimal & y); \
+extern template bool operator!= (const Decimal & x, const Decimal & y);
+FOR_EACH_UNDERLYING_DECIMAL_TYPE(DISPATCH)
+#undef DISPATCH
+
+template