Add Documentation to FunctionFactory

This commit is contained in:
Alexey Milovidov 2022-08-27 22:06:03 +02:00
parent f86242c17e
commit 6139cc8f7a
83 changed files with 1277 additions and 148 deletions

View File

@ -43,7 +43,7 @@ namespace DB
* Documentation does not support multiple languages.
* The only available language is English.
*/
struct Doc
struct Documentation
{
using Description = std::string;
using ExampleName = std::string;
@ -56,13 +56,13 @@ struct Doc
Examples examples;
Categories categories;
Doc(Description description_) : description(std::move(description_)) {}
Doc(Description description_, Examples examples_) : description(std::move(description_)), examples(std::move(examples_)) {}
Doc(Description description_, Examples examples_, Categories categories_)
Documentation(Description description_) : description(std::move(description_)) {}
Documentation(Description description_, Examples examples_) : description(std::move(description_)), examples(std::move(examples_)) {}
Documentation(Description description_, Examples examples_, Categories categories_)
: description(std::move(description_)), examples(std::move(examples_)), categories(std::move(categories_)) {}
/// TODO: Please remove this constructor. Documentation should always be non-empty.
Doc() {}
Documentation() {}
};
}

View File

@ -140,7 +140,7 @@ using FunctionCRC64ECMA = FunctionCRC<CRC64ECMAImpl>;
template <class T>
void registerFunctionCRCImpl(FunctionFactory & factory)
{
factory.registerFunction<T>(T::name, FunctionFactory::CaseInsensitive);
factory.registerFunction<T>(T::name, {}, FunctionFactory::CaseInsensitive);
}
REGISTER_FUNCTION(CRC)

View File

@ -7,10 +7,10 @@ namespace DB
REGISTER_FUNCTION(CastOverloadResolvers)
{
factory.registerFunction<CastInternalOverloadResolver<CastType::nonAccurate>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<CastInternalOverloadResolver<CastType::nonAccurate>>({}, FunctionFactory::CaseInsensitive);
/// Note: "internal" (not affected by null preserving setting) versions of accurate cast functions are unneeded.
factory.registerFunction<CastOverloadResolver<CastType::nonAccurate>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<CastOverloadResolver<CastType::nonAccurate>>({}, FunctionFactory::CaseInsensitive);
factory.registerFunction<CastOverloadResolver<CastType::accurate>>();
factory.registerFunction<CastOverloadResolver<CastType::accurateOrNull>>();
}

View File

@ -115,7 +115,7 @@ private:
REGISTER_FUNCTION(Char)
{
factory.registerFunction<FunctionChar>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionChar>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -46,7 +46,7 @@ public:
REGISTER_FUNCTION(FQDN)
{
factory.registerFunction<FunctionFQDN>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionFQDN>({}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionFQDN>("fullHostName");
}

View File

@ -28,10 +28,11 @@ const String & getFunctionCanonicalNameIfAny(const String & name)
void FunctionFactory::registerFunction(
const std::string & name,
Value creator,
FunctionCreator creator,
Documentation doc,
CaseSensitiveness case_sensitiveness)
{
if (!functions.emplace(name, creator).second)
if (!functions.emplace(name, FunctionFactoryData{creator, doc}).second)
throw Exception("FunctionFactory: the function name '" + name + "' is not unique",
ErrorCodes::LOGICAL_ERROR);
@ -42,7 +43,7 @@ void FunctionFactory::registerFunction(
if (case_sensitiveness == CaseInsensitive)
{
if (!case_insensitive_functions.emplace(function_name_lowercase, creator).second)
if (!case_insensitive_functions.emplace(function_name_lowercase, FunctionFactoryData{creator, doc}).second)
throw Exception("FunctionFactory: the case insensitive function name '" + name + "' is not unique",
ErrorCodes::LOGICAL_ERROR);
case_insensitive_name_mapping[function_name_lowercase] = name;
@ -105,13 +106,13 @@ FunctionOverloadResolverPtr FunctionFactory::tryGetImpl(
auto it = functions.find(name);
if (functions.end() != it)
res = it->second(context);
res = it->second.first(context);
else
{
name = Poco::toLower(name);
it = case_insensitive_functions.find(name);
if (case_insensitive_functions.end() != it)
res = it->second(context);
res = it->second.first(context);
}
if (!res)
@ -141,4 +142,13 @@ FunctionFactory & FunctionFactory::instance()
return ret;
}
Documentation FunctionFactory::getDocumentation(const std::string & name) const
{
auto it = functions.find(name);
if (it == functions.end())
throw Exception(ErrorCodes::UNKNOWN_FUNCTION, "Unknown function {}", name);
return it->second.second;
}
}

View File

@ -3,6 +3,7 @@
#include <Interpreters/Context_fwd.h>
#include <Common/register_objects.h>
#include <Common/IFactoryWithAliases.h>
#include <Common/Documentation.h>
#include <Functions/IFunction.h>
#include <Functions/IFunctionAdaptors.h>
@ -15,30 +16,32 @@
namespace DB
{
using FunctionCreator = std::function<FunctionOverloadResolverPtr(ContextPtr)>;
using FunctionFactoryData = std::pair<FunctionCreator, Documentation>;
/** Creates function by name.
* Function could use for initialization (take ownership of shared_ptr, for example)
* some dictionaries from Context.
*/
class FunctionFactory : private boost::noncopyable,
public IFactoryWithAliases<std::function<FunctionOverloadResolverPtr(ContextPtr)>>
class FunctionFactory : private boost::noncopyable, public IFactoryWithAliases<FunctionFactoryData>
{
public:
static FunctionFactory & instance();
template <typename Function>
void registerFunction(CaseSensitiveness case_sensitiveness = CaseSensitive)
void registerFunction(Documentation doc = {}, CaseSensitiveness case_sensitiveness = CaseSensitive)
{
registerFunction<Function>(Function::name, case_sensitiveness);
registerFunction<Function>(Function::name, std::move(doc), case_sensitiveness);
}
template <typename Function>
void registerFunction(const std::string & name, CaseSensitiveness case_sensitiveness = CaseSensitive)
void registerFunction(const std::string & name, Documentation doc = {}, CaseSensitiveness case_sensitiveness = CaseSensitive)
{
if constexpr (std::is_base_of_v<IFunction, Function>)
registerFunction(name, &adaptFunctionToOverloadResolver<Function>, case_sensitiveness);
registerFunction(name, &adaptFunctionToOverloadResolver<Function>, std::move(doc), case_sensitiveness);
else
registerFunction(name, &Function::create, case_sensitiveness);
registerFunction(name, &Function::create, std::move(doc), case_sensitiveness);
}
/// This function is used by YQL - innovative transactional DBMS that depends on ClickHouse by source code.
@ -60,9 +63,12 @@ public:
/// No locking, you must register all functions before usage of get.
void registerFunction(
const std::string & name,
Value creator,
FunctionCreator creator,
Documentation doc = {},
CaseSensitiveness case_sensitiveness = CaseSensitive);
Documentation getDocumentation(const std::string & name) const;
private:
using Functions = std::unordered_map<std::string, Value>;

View File

@ -623,10 +623,10 @@ public:
REGISTER_FUNCTION(BinaryRepr)
{
factory.registerFunction<EncodeToBinaryRepresentation<HexImpl>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<DecodeFromBinaryRepresentation<UnhexImpl>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<EncodeToBinaryRepresentation<BinImpl>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<DecodeFromBinaryRepresentation<UnbinImpl>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<EncodeToBinaryRepresentation<HexImpl>>({}, FunctionFactory::CaseInsensitive);
factory.registerFunction<DecodeFromBinaryRepresentation<UnhexImpl>>({}, FunctionFactory::CaseInsensitive);
factory.registerFunction<EncodeToBinaryRepresentation<BinImpl>>({}, FunctionFactory::CaseInsensitive);
factory.registerFunction<DecodeFromBinaryRepresentation<UnbinImpl>>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -29,7 +29,7 @@ REGISTER_FUNCTION(Conversion)
factory.registerFunction<FunctionToDate>();
/// MySQL compatibility alias.
factory.registerFunction<FunctionToDate>("DATE", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToDate>("DATE", {}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToDate32>();
factory.registerFunction<FunctionToDateTime>();
factory.registerFunction<FunctionToDateTime32>();

View File

@ -27,7 +27,7 @@ REGISTER_FUNCTION(Logical)
factory.registerFunction<FunctionAnd>();
factory.registerFunction<FunctionOr>();
factory.registerFunction<FunctionXor>();
factory.registerFunction<FunctionNot>(FunctionFactory::CaseInsensitive); /// Operator NOT(x) can be parsed as a function.
factory.registerFunction<FunctionNot>({}, FunctionFactory::CaseInsensitive); /// Operator NOT(x) can be parsed as a function.
}
namespace ErrorCodes

View File

@ -7,11 +7,11 @@ namespace DB
REGISTER_FUNCTION(Round)
{
factory.registerFunction<FunctionRound>("round", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionRoundBankers>("roundBankers", FunctionFactory::CaseSensitive);
factory.registerFunction<FunctionFloor>("floor", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionCeil>("ceil", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionTrunc>("trunc", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionRound>("round", {}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionRoundBankers>("roundBankers", {}, FunctionFactory::CaseSensitive);
factory.registerFunction<FunctionFloor>("floor", {}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionCeil>("ceil", {}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionTrunc>("trunc", {}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionRoundDown>();
/// Compatibility aliases.

View File

@ -52,7 +52,7 @@ template <> struct FunctionUnaryArithmeticMonotonicity<NameAbs>
REGISTER_FUNCTION(Abs)
{
factory.registerFunction<FunctionAbs>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionAbs>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -14,7 +14,7 @@ using FunctionAcos = FunctionMathUnary<UnaryFunctionVectorized<AcosName, acos>>;
REGISTER_FUNCTION(Acos)
{
factory.registerFunction<FunctionAcos>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionAcos>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -55,7 +55,42 @@ using FunctionLength = FunctionStringOrArrayToT<LengthImpl, NameLength, UInt64,
REGISTER_FUNCTION(Length)
{
factory.registerFunction<FunctionLength>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLength>(
{
R"(
Calculates the length of the string or array.
For String or FixedString argument: calculates the number of bytes in string.
[example:string1]
For Array argument: calculates the number of elements in the array.
[example:arr1]
If applied for FixedString argument, the function is a constant expression:
[example:constexpr]
Please note that the number of bytes in a string is not the same as the number of Unicode "code points"
and it is not the same as the number of Unicode "grapheme clusters" (what we usually call "characters")
and it is not the same as the visible string width.
[example:unicode]
It is ok to have ASCII NUL bytes in strings, and they will be counted as well.
[example:nul]
)",
Documentation::Examples{
{"string1", "SELECT length('Hello, world!')"},
{"arr1", "SELECT length(['Hello'], ['world'])"},
{"constexpr", "WITH 'hello' || toString(number) AS str\n"
"SELECT str, \n"
" isConstant(length(str)) AS str_length_is_constant, \n"
" isConstant(length(str::FixedString(6))) AS fixed_str_length_is_constant\n"
"FROM numbers(3)"},
{"unicode", "SELECT 'ёлка' AS str1, length(str1), lengthUTF8(str1), normalizeUTF8NFKD(str1) AS str2, length(str2), lengthUTF8(str2)"},
{"nul", R"(SELECT 'abc\\0\\0\\0' AS str, length(str))"},
},
Documentation::Categories{"String", "Array"}
},
FunctionFactory::CaseInsensitive);
}
}

View File

@ -14,7 +14,34 @@ using FunctionAsin = FunctionMathUnary<UnaryFunctionVectorized<AsinName, asin>>;
REGISTER_FUNCTION(Asin)
{
factory.registerFunction<FunctionAsin>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionAsin>(
{
R"(
Calculates the arcsine of the argument.
Takes arbitrary numeric type, which includes floating point and integer numbers, as well as big integers and decimals and returns Float64.
For arguments in range [-1, 1] it returns the value in range of [-pi() / 2, pi() / 2].
It represents an inverse function to function 'sin' on this range:
[example:inverse]
It always returns Float64, even if the argument has Float32 type:
[example:float32]
For arguments outside of this range, it returns nan:
[example:nan]
Every self-respectful data scientist knows how to apply arcsine to improve ads click-through rate with ClickHouse.
For more details, see [https://en.wikipedia.org/wiki/Inverse_trigonometric_functions].
)",
Documentation::Examples{
{"inverse", "SELECT asin(1.0) = pi() / 2, sin(asin(1)), asin(sin(1))"},
{"float32", "SELECT toTypeName(asin(1.0::Float32))"},
{"nan", "SELECT asin(1.1), asin(-2), asin(inf), asin(nan)"}},
Documentation::Categories{"Mathematical", "Trigonometric"}
},
FunctionFactory::CaseInsensitive);
}
}

View File

@ -14,7 +14,7 @@ using FunctionAtan = FunctionMathUnary<UnaryFunctionVectorized<AtanName, atan>>;
REGISTER_FUNCTION(Atan)
{
factory.registerFunction<FunctionAtan>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionAtan>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -15,7 +15,7 @@ namespace
REGISTER_FUNCTION(Atan2)
{
factory.registerFunction<FunctionAtan2>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionAtan2>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -12,7 +12,7 @@ REGISTER_FUNCTION(Base64Decode)
factory.registerFunction<FunctionBase64Conversion<Base64Decode>>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionBase64Conversion<Base64Decode>>("FROM_BASE64", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionBase64Conversion<Base64Decode>>("FROM_BASE64", {}, FunctionFactory::CaseInsensitive);
}
}
#endif

View File

@ -14,7 +14,7 @@ REGISTER_FUNCTION(Base64Encode)
factory.registerFunction<FunctionBase64Conversion<Base64Encode>>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionBase64Conversion<Base64Encode>>("TO_BASE64", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionBase64Conversion<Base64Encode>>("TO_BASE64", {}, FunctionFactory::CaseInsensitive);
}
}
#endif

View File

@ -176,7 +176,7 @@ private:
REGISTER_FUNCTION(Coalesce)
{
factory.registerFunction<FunctionCoalesce>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionCoalesce>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -230,7 +230,7 @@ private:
REGISTER_FUNCTION(Concat)
{
factory.registerFunction<ConcatOverloadResolver>(FunctionFactory::CaseInsensitive);
factory.registerFunction<ConcatOverloadResolver>({}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionConcatAssumeInjective>();
}

View File

@ -33,7 +33,7 @@ public:
REGISTER_FUNCTION(ConnectionId)
{
factory.registerFunction<FunctionConnectionId>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionConnectionId>({}, FunctionFactory::CaseInsensitive);
factory.registerAlias("connection_id", "connectionID", FunctionFactory::CaseInsensitive);
}

View File

@ -13,7 +13,7 @@ using FunctionCos = FunctionMathUnary<UnaryFunctionVectorized<CosName, cos>>;
REGISTER_FUNCTION(Cos)
{
factory.registerFunction<FunctionCos>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionCos>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -22,8 +22,8 @@ namespace DB
REGISTER_FUNCTION(CountMatches)
{
factory.registerFunction<FunctionCountMatches<FunctionCountMatchesCaseSensitive>>(FunctionFactory::CaseSensitive);
factory.registerFunction<FunctionCountMatches<FunctionCountMatchesCaseInsensitive>>(FunctionFactory::CaseSensitive);
factory.registerFunction<FunctionCountMatches<FunctionCountMatchesCaseSensitive>>({}, FunctionFactory::CaseSensitive);
factory.registerFunction<FunctionCountMatches<FunctionCountMatchesCaseInsensitive>>({}, FunctionFactory::CaseSensitive);
}
}

View File

@ -19,6 +19,6 @@ using FunctionCountSubstrings = FunctionsStringSearch<CountSubstringsImpl<NameCo
REGISTER_FUNCTION(CountSubstrings)
{
factory.registerFunction<FunctionCountSubstrings>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionCountSubstrings>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -54,7 +54,7 @@ public:
REGISTER_FUNCTION(CurrentDatabase)
{
factory.registerFunction<FunctionCurrentDatabase>();
factory.registerFunction<FunctionCurrentDatabase>("DATABASE", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionCurrentDatabase>("DATABASE", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -263,8 +263,7 @@ private:
REGISTER_FUNCTION(DateDiff)
{
factory.registerFunction<FunctionDateDiff>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionDateDiff>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -345,7 +345,7 @@ private:
REGISTER_FUNCTION(DateName)
{
factory.registerFunction<FunctionDateNameImpl>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionDateNameImpl>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -155,7 +155,7 @@ private:
REGISTER_FUNCTION(DateTrunc)
{
factory.registerFunction<FunctionDateTrunc>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionDateTrunc>({}, FunctionFactory::CaseInsensitive);
/// Compatibility alias.
factory.registerAlias("dateTrunc", FunctionDateTrunc::name);

View File

@ -23,7 +23,7 @@ namespace
REGISTER_FUNCTION(Degrees)
{
factory.registerFunction<FunctionDegrees>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionDegrees>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -36,7 +36,7 @@ using FunctionExp = FunctionMathUnary<UnaryFunctionVectorized<ExpName, exp>>;
REGISTER_FUNCTION(Exp)
{
factory.registerFunction<FunctionExp>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionExp>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -65,7 +65,7 @@ using FunctionGreatest = FunctionBinaryArithmetic<GreatestImpl, NameGreatest>;
REGISTER_FUNCTION(Greatest)
{
factory.registerFunction<LeastGreatestOverloadResolver<LeastGreatest::Greatest, FunctionGreatest>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<LeastGreatestOverloadResolver<LeastGreatest::Greatest, FunctionGreatest>>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -15,7 +15,7 @@ namespace
REGISTER_FUNCTION(Hypot)
{
factory.registerFunction<FunctionHypot>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionHypot>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -1122,7 +1122,7 @@ public:
REGISTER_FUNCTION(If)
{
factory.registerFunction<FunctionIf>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionIf>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -91,7 +91,7 @@ private:
REGISTER_FUNCTION(IfNull)
{
factory.registerFunction<FunctionIfNull>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionIfNull>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -74,7 +74,7 @@ public:
REGISTER_FUNCTION(IsNull)
{
factory.registerFunction<FunctionIsNull>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionIsNull>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -65,7 +65,7 @@ using FunctionLeast = FunctionBinaryArithmetic<LeastImpl, NameLeast>;
REGISTER_FUNCTION(Least)
{
factory.registerFunction<LeastGreatestOverloadResolver<LeastGreatest::Least, FunctionLeast>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<LeastGreatestOverloadResolver<LeastGreatest::Least, FunctionLeast>>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -6,8 +6,8 @@ namespace DB
REGISTER_FUNCTION(Left)
{
factory.registerFunction<FunctionLeftRight<false, SubstringDirection::Left>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLeftRight<true, SubstringDirection::Left>>(FunctionFactory::CaseSensitive);
factory.registerFunction<FunctionLeftRight<false, SubstringDirection::Left>>({}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLeftRight<true, SubstringDirection::Left>>({}, FunctionFactory::CaseSensitive);
}
}

View File

@ -122,7 +122,7 @@ public:
REGISTER_FUNCTION(Lemmatize)
{
factory.registerFunction<FunctionLemmatize>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLemmatize>();
}
}

View File

@ -73,8 +73,8 @@ REGISTER_FUNCTION(LengthUTF8)
factory.registerFunction<FunctionLengthUTF8>();
/// Compatibility aliases.
factory.registerFunction<FunctionLengthUTF8>("CHAR_LENGTH", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLengthUTF8>("CHARACTER_LENGTH", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLengthUTF8>("CHAR_LENGTH", {}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLengthUTF8>("CHARACTER_LENGTH", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -34,7 +34,7 @@ using FunctionLog = FunctionMathUnary<UnaryFunctionVectorized<LogName, log>>;
REGISTER_FUNCTION(Log)
{
factory.registerFunction<FunctionLog>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLog>({}, FunctionFactory::CaseInsensitive);
factory.registerAlias("ln", "log", FunctionFactory::CaseInsensitive);
}

View File

@ -13,7 +13,7 @@ using FunctionLog10 = FunctionMathUnary<UnaryFunctionVectorized<Log10Name, log10
REGISTER_FUNCTION(Log10)
{
factory.registerFunction<FunctionLog10>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLog10>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,7 +13,7 @@ using FunctionLog2 = FunctionMathUnary<UnaryFunctionVectorized<Log2Name, log2>>;
REGISTER_FUNCTION(Log2)
{
factory.registerFunction<FunctionLog2>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLog2>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -19,7 +19,7 @@ using FunctionLower = FunctionStringToString<LowerUpperImpl<'A', 'Z'>, NameLower
REGISTER_FUNCTION(Lower)
{
factory.registerFunction<FunctionLower>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLower>({}, FunctionFactory::CaseInsensitive);
factory.registerAlias("lcase", NameLower::name, FunctionFactory::CaseInsensitive);
}

View File

@ -41,7 +41,7 @@ REGISTER_FUNCTION(E)
REGISTER_FUNCTION(Pi)
{
factory.registerFunction<FunctionPi>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionPi>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -21,6 +21,6 @@ namespace
REGISTER_FUNCTION(Max2)
{
factory.registerFunction<FunctionMax2>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionMax2>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -22,6 +22,6 @@ namespace
REGISTER_FUNCTION(Min2)
{
factory.registerFunction<FunctionMin2>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionMin2>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -74,7 +74,7 @@ private:
REGISTER_FUNCTION(MonthName)
{
factory.registerFunction<FunctionMonthName>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionMonthName>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -128,7 +128,7 @@ public:
REGISTER_FUNCTION(Now)
{
factory.registerFunction<NowOverloadResolver>(FunctionFactory::CaseInsensitive);
factory.registerFunction<NowOverloadResolver>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -160,7 +160,7 @@ public:
REGISTER_FUNCTION(Now64)
{
factory.registerFunction<Now64OverloadResolver>(FunctionFactory::CaseInsensitive);
factory.registerFunction<Now64OverloadResolver>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -69,8 +69,7 @@ public:
REGISTER_FUNCTION(NullIf)
{
factory.registerFunction<FunctionNullIf>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionNullIf>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -19,7 +19,7 @@ using FunctionPosition = FunctionsStringSearch<PositionImpl<NamePosition, Positi
REGISTER_FUNCTION(Position)
{
factory.registerFunction<FunctionPosition>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionPosition>({}, FunctionFactory::CaseInsensitive);
factory.registerAlias("locate", NamePosition::name, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,7 +13,7 @@ using FunctionPow = FunctionMathBinaryFloat64<BinaryFunctionVectorized<PowName,
REGISTER_FUNCTION(Pow)
{
factory.registerFunction<FunctionPow>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionPow>({}, FunctionFactory::CaseInsensitive);
factory.registerAlias("power", "pow", FunctionFactory::CaseInsensitive);
}

View File

@ -23,7 +23,7 @@ namespace
REGISTER_FUNCTION(Radians)
{
factory.registerFunction<FunctionRadians>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionRadians>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,9 +13,8 @@ using FunctionRand = FunctionRandom<UInt32, NameRand>;
REGISTER_FUNCTION(Rand)
{
factory.registerFunction<FunctionRand>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionRand>({}, FunctionFactory::CaseInsensitive);
factory.registerAlias("rand32", NameRand::name);
}
}

View File

@ -254,7 +254,7 @@ public:
REGISTER_FUNCTION(Repeat)
{
factory.registerFunction<FunctionRepeat>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionRepeat>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -150,7 +150,7 @@ private:
REGISTER_FUNCTION(Reverse)
{
factory.registerFunction<ReverseOverloadResolver>(FunctionFactory::CaseInsensitive);
factory.registerFunction<ReverseOverloadResolver>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -6,8 +6,8 @@ namespace DB
REGISTER_FUNCTION(Right)
{
factory.registerFunction<FunctionLeftRight<false, SubstringDirection::Right>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLeftRight<true, SubstringDirection::Right>>(FunctionFactory::CaseSensitive);
factory.registerFunction<FunctionLeftRight<false, SubstringDirection::Right>>({}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionLeftRight<true, SubstringDirection::Right>>({}, FunctionFactory::CaseSensitive);
}
}

View File

@ -153,12 +153,12 @@ REGISTER_FUNCTION(Uptime)
REGISTER_FUNCTION(Version)
{
factory.registerFunction<FunctionVersion>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionVersion>({}, FunctionFactory::CaseInsensitive);
}
REGISTER_FUNCTION(Revision)
{
factory.registerFunction<FunctionRevision>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionRevision>({}, FunctionFactory::CaseInsensitive);
}
REGISTER_FUNCTION(ZooKeeperSessionUptime)
@ -174,4 +174,3 @@ REGISTER_FUNCTION(GetOSKernelVersion)
}

View File

@ -45,7 +45,7 @@ struct FunctionUnaryArithmeticMonotonicity<NameSign>
REGISTER_FUNCTION(Sign)
{
factory.registerFunction<FunctionSign>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionSign>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,7 +13,7 @@ using FunctionSin = FunctionMathUnary<UnaryFunctionVectorized<SinName, sin>>;
REGISTER_FUNCTION(Sin)
{
factory.registerFunction<FunctionSin>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionSin>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,7 +13,7 @@ using FunctionSqrt = FunctionMathUnary<UnaryFunctionVectorized<SqrtName, sqrt>>;
REGISTER_FUNCTION(Sqrt)
{
factory.registerFunction<FunctionSqrt>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionSqrt>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -127,7 +127,7 @@ public:
REGISTER_FUNCTION(Stem)
{
factory.registerFunction<FunctionStem>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionStem>();
}
}

View File

@ -188,11 +188,11 @@ public:
REGISTER_FUNCTION(Substring)
{
factory.registerFunction<FunctionSubstring<false>>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionSubstring<false>>({}, FunctionFactory::CaseInsensitive);
factory.registerAlias("substr", "substring", FunctionFactory::CaseInsensitive);
factory.registerAlias("mid", "substring", FunctionFactory::CaseInsensitive); /// from MySQL dialect
factory.registerFunction<FunctionSubstring<true>>(FunctionFactory::CaseSensitive);
factory.registerFunction<FunctionSubstring<true>>({}, FunctionFactory::CaseSensitive);
}
}

View File

@ -120,7 +120,7 @@ public:
REGISTER_FUNCTION(Synonyms)
{
factory.registerFunction<FunctionSynonyms>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionSynonyms>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,7 +13,7 @@ using FunctionTan = FunctionMathUnary<UnaryFunctionVectorized<TanName, tan>>;
REGISTER_FUNCTION(Tan)
{
factory.registerFunction<FunctionTan>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionTan>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -39,9 +39,7 @@ using FunctionTanh = FunctionMathUnary<UnaryFunctionVectorized<TanhName, tanh>>;
REGISTER_FUNCTION(Tanh)
{
factory.registerFunction<FunctionTanh>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionTanh>({}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -14,10 +14,8 @@ REGISTER_FUNCTION(ToDayOfMonth)
factory.registerFunction<FunctionToDayOfMonth>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionToDayOfMonth>("DAY", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToDayOfMonth>("DAYOFMONTH", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToDayOfMonth>("DAY", {}, FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToDayOfMonth>("DAYOFMONTH", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -14,9 +14,7 @@ REGISTER_FUNCTION(ToDayOfWeek)
factory.registerFunction<FunctionToDayOfWeek>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionToDayOfWeek>("DAYOFWEEK", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToDayOfWeek>("DAYOFWEEK", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -14,9 +14,7 @@ REGISTER_FUNCTION(ToDayOfYear)
factory.registerFunction<FunctionToDayOfYear>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionToDayOfYear>("DAYOFYEAR", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToDayOfYear>("DAYOFYEAR", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -14,9 +14,7 @@ REGISTER_FUNCTION(ToHour)
factory.registerFunction<FunctionToHour>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionToHour>("HOUR", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToHour>("HOUR", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,9 +13,7 @@ REGISTER_FUNCTION(ToLastDayOfMonth)
factory.registerFunction<FunctionToLastDayOfMonth>();
/// MySQL compatibility alias.
factory.registerFunction<FunctionToLastDayOfMonth>("LAST_DAY", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToLastDayOfMonth>("LAST_DAY", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,9 +13,7 @@ REGISTER_FUNCTION(ToMinute)
{
factory.registerFunction<FunctionToMinute>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionToMinute>("MINUTE", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToMinute>("MINUTE", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,9 +13,7 @@ REGISTER_FUNCTION(ToMonth)
{
factory.registerFunction<FunctionToMonth>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionToMonth>("MONTH", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToMonth>("MONTH", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,9 +13,7 @@ REGISTER_FUNCTION(ToQuarter)
{
factory.registerFunction<FunctionToQuarter>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionToQuarter>("QUARTER", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToQuarter>("QUARTER", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,9 +13,7 @@ REGISTER_FUNCTION(ToSecond)
{
factory.registerFunction<FunctionToSecond>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionToSecond>("SECOND", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToSecond>("SECOND", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -13,9 +13,7 @@ REGISTER_FUNCTION(ToYear)
{
factory.registerFunction<FunctionToYear>();
/// MysQL compatibility alias.
factory.registerFunction<FunctionToYear>("YEAR", FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionToYear>("YEAR", {}, FunctionFactory::CaseInsensitive);
}
}

View File

@ -18,7 +18,7 @@ using FunctionUpper = FunctionStringToString<LowerUpperImpl<'a', 'z'>, NameUpper
REGISTER_FUNCTION(Upper)
{
factory.registerFunction<FunctionUpper>(FunctionFactory::CaseInsensitive);
factory.registerFunction<FunctionUpper>({}, FunctionFactory::CaseInsensitive);
factory.registerAlias("ucase", FunctionUpper::name, FunctionFactory::CaseInsensitive);
}

View File

@ -38,7 +38,13 @@ namespace ErrorCodes
namespace
{
template <typename Factory>
void fillRow(MutableColumns & res_columns, const String & name, UInt64 is_aggregate, const String & create_query, FunctionOrigin function_origin, const Factory & f)
void fillRow(
MutableColumns & res_columns,
const String & name,
UInt64 is_aggregate,
const String & create_query,
FunctionOrigin function_origin,
const Factory & factory)
{
res_columns[0]->insert(name);
res_columns[1]->insert(is_aggregate);
@ -50,15 +56,25 @@ namespace
}
else
{
res_columns[2]->insert(f.isCaseInsensitive(name));
if (f.isAlias(name))
res_columns[3]->insert(f.aliasTo(name));
res_columns[2]->insert(factory.isCaseInsensitive(name));
if (factory.isAlias(name))
res_columns[3]->insert(factory.aliasTo(name));
else
res_columns[3]->insertDefault();
}
res_columns[4]->insert(create_query);
res_columns[5]->insert(static_cast<Int8>(function_origin));
if constexpr (std::is_same_v<Factory, FunctionFactory>)
{
if (factory.isAlias(name))
res_columns[6]->insertDefault();
else
res_columns[6]->insert(factory.getDocumentation(name).description);
}
else
res_columns[6]->insertDefault();
}
}
@ -79,7 +95,8 @@ NamesAndTypesList StorageSystemFunctions::getNamesAndTypes()
{"case_insensitive", std::make_shared<DataTypeUInt8>()},
{"alias_to", std::make_shared<DataTypeString>()},
{"create_query", std::make_shared<DataTypeString>()},
{"origin", std::make_shared<DataTypeEnum8>(getOriginEnumsAndValues())}
{"origin", std::make_shared<DataTypeEnum8>(getOriginEnumsAndValues())},
{"description", std::make_shared<DataTypeString>()},
};
}

View File

@ -17,14 +17,15 @@ namespace ErrorCodes
}
void TableFunctionFactory::registerFunction(const std::string & name, TableFunctionCreator creator, Doc doc, CaseSensitiveness case_sensitiveness)
void TableFunctionFactory::registerFunction(
const std::string & name, TableFunctionCreator creator, Documentation doc, CaseSensitiveness case_sensitiveness)
{
if (!table_functions.emplace(name, TableFunctionData{creator, doc}).second)
if (!table_functions.emplace(name, TableFunctionFactoryData{creator, doc}).second)
throw Exception("TableFunctionFactory: the table function name '" + name + "' is not unique",
ErrorCodes::LOGICAL_ERROR);
if (case_sensitiveness == CaseInsensitive
&& !case_insensitive_table_functions.emplace(Poco::toLower(name), TableFunctionData{creator, doc}).second)
&& !case_insensitive_table_functions.emplace(Poco::toLower(name), TableFunctionFactoryData{creator, doc}).second)
throw Exception("TableFunctionFactory: the case insensitive table function name '" + name + "' is not unique",
ErrorCodes::LOGICAL_ERROR);
}
@ -85,7 +86,7 @@ bool TableFunctionFactory::isTableFunctionName(const std::string & name) const
return table_functions.contains(name);
}
Doc TableFunctionFactory::getDocumentation(const std::string & name) const
Documentation TableFunctionFactory::getDocumentation(const std::string & name) const
{
auto it = table_functions.find(name);
if (it == table_functions.end())

View File

@ -18,21 +18,25 @@ namespace DB
class Context;
using TableFunctionCreator = std::function<TableFunctionPtr()>;
using TableFunctionData = std::pair<TableFunctionCreator, Doc>;
using TableFunctionFactoryData = std::pair<TableFunctionCreator, Documentation>;
/** Lets you get a table function by its name.
*/
class TableFunctionFactory final: private boost::noncopyable, public IFactoryWithAliases<TableFunctionData>
class TableFunctionFactory final: private boost::noncopyable, public IFactoryWithAliases<TableFunctionFactoryData>
{
public:
static TableFunctionFactory & instance();
/// Register a function by its name.
/// No locking, you must register all functions before usage of get.
void registerFunction(const std::string & name, TableFunctionCreator creator, Doc doc = {}, CaseSensitiveness case_sensitiveness = CaseSensitive);
void registerFunction(
const std::string & name,
TableFunctionCreator creator,
Documentation doc = {},
CaseSensitiveness case_sensitiveness = CaseSensitive);
template <typename Function>
void registerFunction(Doc doc = {}, CaseSensitiveness case_sensitiveness = CaseSensitive)
void registerFunction(Documentation doc = {}, CaseSensitiveness case_sensitiveness = CaseSensitive)
{
auto creator = []() -> TableFunctionPtr { return std::make_shared<Function>(); };
registerFunction(Function::name, std::move(creator), std::move(doc), case_sensitiveness);
@ -44,7 +48,7 @@ public:
/// Returns nullptr if not found.
TableFunctionPtr tryGet(const std::string & name, ContextPtr context) const;
Doc getDocumentation(const std::string & name) const;
Documentation getDocumentation(const std::string & name) const;
bool isTableFunctionName(const std::string & name) const;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
-- This outputs the list of undocumented functions. No new items in the list should appear.
-- Please help shorten this list down to zero elements.
SELECT name FROM system.functions WHERE NOT is_aggregate AND origin = 'System' AND alias_to = '' AND length(description) < 10 ORDER BY name;