Skip to content

Commit 5f8501c

Browse files
authored
Merge pull request ClickHouse#80115 from Blargian/array_functions_part_1
Docs: Array functions source code documentation - part 1
2 parents d771063 + 7e696bf commit 5f8501c

11 files changed

+265
-97
lines changed

src/Functions/array/array.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,42 @@ class FunctionArray : public IFunction
287287

288288
REGISTER_FUNCTION(Array)
289289
{
290-
factory.registerFunction<FunctionArray>();
290+
FunctionDocumentation::Description description = R"(
291+
Creates an array from the function arguments.
292+
293+
The arguments should be constants and have types that share a common supertype.
294+
At least one argument must be passed, because otherwise it isn't clear which type of array to create.
295+
This means that you can't use this function to create an empty array. To do so, use the `emptyArray*` function.
296+
297+
Use the `[ ]` operator for the same functionality.
298+
)";
299+
FunctionDocumentation::Syntax syntax = "array(x1 [, x2, ..., xN])";
300+
FunctionDocumentation::Arguments arguments = {
301+
{"x1", "Constant value of any type T. If only this argument is provided, the array will be of type T."},
302+
{"[, x2, ..., xN]", "Additional N constant values sharing a common supertype with `x1`"},
303+
};
304+
FunctionDocumentation::ReturnedValue returned_value = "Returns an 'Array(T)' type result, where 'T' is the smallest common type out of the passed arguments.";
305+
FunctionDocumentation::Examples examples = {{"Valid usage", R"(
306+
SELECT array(toInt32(1), toUInt16(2), toInt8(3)) AS a, toTypeName(a)
307+
)",
308+
R"(
309+
┌─a───────┬─toTypeName(a)─┐
310+
│ [1,2,3] │ Array(Int32) │
311+
└─────────┴───────────────┘
312+
)"},
313+
{"Invalid usage", R"(
314+
SELECT array(toInt32(5), toDateTime('1998-06-16'), toInt8(5)) AS a, toTypeName(a)
315+
)",
316+
R"(
317+
Received exception from server (version 25.4.3):
318+
Code: 386. DB::Exception: Received from localhost:9000. DB::Exception:
319+
There is no supertype for types Int32, DateTime, Int8 ...
320+
)"}};
321+
FunctionDocumentation::IntroducedIn introduced_in = {1, 1};
322+
FunctionDocumentation::Category category = FunctionDocumentation::Category::Array;
323+
FunctionDocumentation documentation = {description, syntax, arguments, returned_value, examples, introduced_in, category};
324+
325+
factory.registerFunction<FunctionArray>(documentation);
291326
}
292327

293328
}

src/Functions/array/arrayConcat.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,17 @@ ColumnPtr FunctionArrayConcat::executeImpl(const ColumnsWithTypeAndName & argume
8080

8181
REGISTER_FUNCTION(ArrayConcat)
8282
{
83+
FunctionDocumentation::Description description = "Combines arrays passed as arguments.";
84+
FunctionDocumentation::Syntax syntax = "arrayConcat(arr1 [, arr2, ... , arrN])";
85+
FunctionDocumentation::Arguments arguments = {
86+
{"arr1 [, arr2, ... , arrN]", "N number of arrays to concatenate. [`Array(T)`](/sql-reference/data-types/array)."}
87+
};
88+
FunctionDocumentation::ReturnedValue returned_value = "Returns a single combined array from the provided array arguments.";
89+
FunctionDocumentation::Examples example = {{"Usage example", "SELECT arrayConcat([1, 2], [3, 4], [5, 6]) AS res", "[1,2,3,4,5,6]"}};
90+
FunctionDocumentation::IntroducedIn introduced_in = {1, 1};
91+
FunctionDocumentation::Category category = FunctionDocumentation::Category::Array;
92+
FunctionDocumentation documentation = {description, syntax, arguments, returned_value, example, introduced_in, category};
93+
8394
factory.registerFunction<FunctionArrayConcat>();
8495
}
8596

src/Functions/array/arrayElement.cpp

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,23 +2202,61 @@ ColumnPtr FunctionArrayElement<mode>::perform(
22022202

22032203
REGISTER_FUNCTION(ArrayElement)
22042204
{
2205-
factory.registerFunction<FunctionArrayElement<ArrayElementExceptionMode::Zero>>(FunctionDocumentation{
2206-
.description = R"(
2207-
Get the element with the index `n` from the array `arr`. `n` must be any integer type. Indexes in an array begin from one.
2205+
FunctionDocumentation::Description description = R"(
2206+
Gets the element of the provided array with index `n` where `n` can be any integer type.
2207+
If the index falls outside of the bounds of an array, it returns a default value (0 for numbers, an empty string for strings, etc.),
2208+
except for arguments of a non-constant array and a constant index 0. In this case there will be an error `Array indices are 1-based`.
2209+
2210+
:::note
2211+
Arrays in ClickHouse are one-indexed.
2212+
:::
2213+
2214+
Negative indexes are supported. In this case, the corresponding element is selected, numbered from the end. For example, `arr[-1]` is the last item in the array.
2215+
2216+
Operator `[n]` provides the same functionality.
2217+
)";
2218+
FunctionDocumentation::Syntax syntax = "arrayElement(arr, n)";
2219+
FunctionDocumentation::Arguments arguments = {
2220+
{"arr", "The array to search. [`Array(T)`](/sql-reference/data-types/array)."},
2221+
{"n", "Position of the element to get. [`(U)Int*`](/sql-reference/data-types/int-uint)."}
2222+
};
2223+
FunctionDocumentation::ReturnedValue returned_value = "Returns a single combined array from the provided array arguments. [`Array(T)`](/sql-reference/data-types/array).";
2224+
FunctionDocumentation::Examples examples = {
2225+
{"Usage example", "SELECT arrayElement(arr, 2) FROM (SELECT [1, 2, 3] AS arr)", "2"},
2226+
{"Negative indexing", "SELECT arrayElement(arr, -1) FROM (SELECT [1, 2, 3] AS arr)", "3"},
2227+
{"Using [n] notation", "SELECT arr[2] FROM (SELECT [1, 2, 3] AS arr)", "2"},
2228+
{"Index out of array bounds", "SELECT arrayElement(arr, 4) FROM (SELECT [1, 2, 3] AS arr)", "0"}
2229+
};
2230+
FunctionDocumentation::IntroducedIn introduced_in = {1, 1};
2231+
FunctionDocumentation::Category category = FunctionDocumentation::Category::Array;
2232+
FunctionDocumentation documentation = {description, syntax, arguments, returned_value, examples, introduced_in, category};
2233+
2234+
factory.registerFunction<FunctionArrayElement<ArrayElementExceptionMode::Zero>>(documentation);
2235+
2236+
FunctionDocumentation::Description description_null = R"(
2237+
Gets the element of the provided array with index `n` where `n` can be any integer type.
2238+
If the index falls outside of the bounds of an array, `NULL` is returned instead of a default value.
2239+
2240+
:::note
2241+
Arrays in ClickHouse are one-indexed.
2242+
:::
22082243
22092244
Negative indexes are supported. In this case, it selects the corresponding element numbered from the end. For example, `arr[-1]` is the last item in the array.
2210-
2211-
If the index falls outside of the bounds of an array, it returns some default value (0 for numbers, an empty string for strings, etc.), except for the case with a non-constant array and a constant index 0 (in this case there will be an error `Array indices are 1-based`).
2212-
)",
2213-
.category = FunctionDocumentation::Category::Array});
2214-
factory.registerFunction<FunctionArrayElement<ArrayElementExceptionMode::Null>>(FunctionDocumentation{
2215-
.description = R"(
2216-
Get the element with the index `n`from the array `arr`. `n` must be any integer type. Indexes in an array begin from one.
2217-
2218-
Negative indexes are supported. In this case, it selects the corresponding element numbered from the end. For example, `arr[-1]` is the last item in the array.
2219-
2220-
If the index falls outside of the bounds of an array, it returns `NULL` instead of a default value.
2221-
)",
2222-
.category = FunctionDocumentation::Category::Array});
2245+
)";
2246+
FunctionDocumentation::Syntax syntax_null = "arrayElementOrNull(arrays)";
2247+
FunctionDocumentation::Arguments arguments_null = {
2248+
{"arrays", "Arbitrary number of arguments of [`Array`](/sql-reference/data-types/array) type."}
2249+
};
2250+
FunctionDocumentation::ReturnedValue returned_value_null = "Returns a single combined array from the provided array arguments.";
2251+
FunctionDocumentation::Examples examples_null = {
2252+
{"Usage example", "SELECT arrayElementOrNull(arr, 2) FROM (SELECT [1, 2, 3] AS arr)", "2"},
2253+
{"Negative indexing", "SELECT arrayElementOrNull(arr, -1) FROM (SELECT [1, 2, 3] AS arr)", "3"},
2254+
{"Index out of array bounds", "SELECT arrayElementOrNull(arr, 4) FROM (SELECT [1, 2, 3] AS arr)", "NULL"}
2255+
};
2256+
FunctionDocumentation::IntroducedIn introduced_in_null = {1, 1};
2257+
FunctionDocumentation::Category category_null = FunctionDocumentation::Category::Array;
2258+
FunctionDocumentation documentation_null = {description_null, syntax_null, arguments_null, returned_value_null, examples_null, introduced_in_null, category_null};
2259+
2260+
factory.registerFunction<FunctionArrayElement<ArrayElementExceptionMode::Null>>(documentation_null);
22232261
}
22242262
}

src/Functions/array/arrayWithConstant.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,21 @@ class FunctionArrayWithConstant : public IFunction
8888

8989
REGISTER_FUNCTION(ArrayWithConstant)
9090
{
91-
factory.registerFunction<FunctionArrayWithConstant>();
91+
FunctionDocumentation::Description description = R"(
92+
Creates an array of length `length` filled with the constant `x`.
93+
)";
94+
FunctionDocumentation::Syntax syntax = "arrayWithConstant(N, x)";
95+
FunctionDocumentation::Arguments arguments = {
96+
{"length", "Number of elements in the array. [`(U)Int*`](/sql-reference/data-types/int-uint)."},
97+
{"x", "The value of the `N` elements in the array, of any type."},
98+
};
99+
FunctionDocumentation::ReturnedValue returned_value = "Returns an Array with `N` elements of value `x`.";
100+
FunctionDocumentation::Examples example = {{"Usage example", "SELECT arrayWithConstant(3, 1)", "[1,1,1]"}};
101+
FunctionDocumentation::IntroducedIn introduced_in = {20, 1};
102+
FunctionDocumentation::Category category = FunctionDocumentation::Category::Array;
103+
FunctionDocumentation documentation = {description, syntax, arguments, returned_value, example, introduced_in, category};
104+
105+
factory.registerFunction<FunctionArrayWithConstant>(documentation);
92106
}
93107

94108
}

src/Functions/array/emptyArray.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,20 @@ class FunctionEmptyArray : public IFunction
4848

4949
void registerFunction(FunctionFactory & factory, const String & element_type)
5050
{
51-
factory.registerFunction(FunctionEmptyArray::getNameImpl(element_type),
52-
[element_type](ContextPtr){ return std::make_shared<FunctionEmptyArray>(element_type); });
51+
FunctionDocumentation::Description description = fmt::format("Returns an empty {} array", element_type);
52+
FunctionDocumentation::Syntax syntax = fmt::format("emptyArray{}()", element_type);
53+
FunctionDocumentation::Arguments arguments = {{"", ""}};
54+
FunctionDocumentation::ReturnedValue returned_value = fmt::format("An empty {} array. [`Array(T)`](/sql-reference/data-types/array).", element_type);
55+
FunctionDocumentation::Examples examples = {{"Usage example", fmt::format("SELECT emptyArray{}", element_type), "[]"}};
56+
FunctionDocumentation::IntroducedIn introduced_in = {1, 1};
57+
FunctionDocumentation::Category category = FunctionDocumentation::Category::Array;
58+
FunctionDocumentation documentation = {description, syntax, arguments, returned_value, examples, introduced_in, category};
59+
60+
factory.registerFunction(
61+
FunctionEmptyArray::getNameImpl(element_type),
62+
[element_type](ContextPtr){ return std::make_shared<FunctionEmptyArray>(element_type); },
63+
documentation
64+
);
5365
}
5466

5567
}

src/Functions/array/emptyArrayToSingle.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,34 @@ ColumnPtr FunctionEmptyArrayToSingle::executeImpl(const ColumnsWithTypeAndName &
392392

393393
REGISTER_FUNCTION(EmptyArrayToSingle)
394394
{
395-
factory.registerFunction<FunctionEmptyArrayToSingle>();
395+
FunctionDocumentation::Description description = R"(
396+
Accepts an empty array and returns a one-element array that is equal to the default value.
397+
)";
398+
FunctionDocumentation::Syntax syntax = "emptyArrayToSingle(arr)";
399+
FunctionDocumentation::Arguments arguments = {{"arr", "An empty array. [`Array(T)`](/sql-reference/data-types/array)"}};
400+
FunctionDocumentation::ReturnedValue returned_value = "An array with a single value of the Array's default type.";
401+
FunctionDocumentation::Examples examples = {{"Basic example", R"(
402+
CREATE TABLE test (
403+
a Array(Int32),
404+
b Array(String),
405+
c Array(DateTime)
406+
)
407+
ENGINE = MergeTree
408+
ORDER BY tuple();
409+
410+
INSERT INTO test VALUES ([], [], []);
411+
412+
SELECT emptyArrayToSingle(a), emptyArrayToSingle(b), emptyArrayToSingle(c) FROM test;
413+
)", R"(
414+
┌─emptyArrayToSingle(a)─┬─emptyArrayToSingle(b)─┬─emptyArrayToSingle(c)───┐
415+
│ [0] │ [''] │ ['1970-01-01 01:00:00'] │
416+
└───────────────────────┴───────────────────────┴─────────────────────────┘
417+
)"}};
418+
FunctionDocumentation::IntroducedIn introduced_in = {1, 1};
419+
FunctionDocumentation::Category category = FunctionDocumentation::Category::Array;
420+
FunctionDocumentation documentation = {description, syntax, arguments, returned_value, examples, introduced_in, category};
421+
422+
factory.registerFunction<FunctionEmptyArrayToSingle>(documentation);
396423
}
397424

398425
}

src/Functions/array/length.cpp

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -5,42 +5,54 @@ namespace DB
55

66
REGISTER_FUNCTION(Length)
77
{
8-
factory.registerFunction<FunctionLength>(
9-
FunctionDocumentation{
10-
.description=R"(
11-
Calculates the length of the string or array.
8+
FunctionDocumentation::Description description = R"(
9+
Calculates the length of a string or array.
1210
13-
For String or FixedString argument: calculates the number of bytes in string.
14-
[example:string1]
11+
- For String or FixedString arguments: calculates the number of bytes in the string.
12+
- For Array arguments: calculates the number of elements in the array.
13+
- If applied to a FixedString argument, the function is a constant expression.
1514
16-
For Array argument: calculates the number of elements in the array.
17-
[example:arr1]
18-
19-
If applied for FixedString argument, the function is a constant expression:
20-
[example:constexpr]
21-
22-
Please note that the number of bytes in a string is not the same as the number of Unicode "code points"
23-
and it is not the same as the number of Unicode "grapheme clusters" (what we usually call "characters")
24-
and it is not the same as the visible string width.
25-
[example:unicode]
15+
Please note that the number of bytes in a string is not the same as the number of
16+
Unicode "code points" and it is not the same as the number of Unicode "grapheme clusters"
17+
(what we usually call "characters") and it is not the same as the visible string width.
2618
2719
It is ok to have ASCII NUL bytes in strings, and they will be counted as well.
28-
[example:nul]
29-
)",
30-
.examples{
31-
{"string1", "SELECT length('Hello, world!')", ""},
32-
{"arr1", "SELECT length(['Hello'], ['world'])", ""},
33-
{"constexpr", "WITH 'hello' || toString(number) AS str\n"
34-
"SELECT str, \n"
35-
" isConstant(length(str)) AS str_length_is_constant, \n"
36-
" isConstant(length(str::FixedString(6))) AS fixed_str_length_is_constant\n"
37-
"FROM numbers(3)", ""},
38-
{"unicode", "SELECT 'ёлка' AS str1, length(str1), lengthUTF8(str1), normalizeUTF8NFKD(str1) AS str2, length(str2), lengthUTF8(str2)", ""},
39-
{"nul", R"(SELECT 'abc\0\0\0' AS str, length(str))", ""},
40-
},
41-
.category = FunctionDocumentation::Category::Array
42-
},
43-
FunctionFactory::Case::Insensitive);
20+
)";
21+
FunctionDocumentation::Syntax syntax = "length(x)";
22+
FunctionDocumentation::Arguments arguments = {{"x", "String, FixedString or Array for which to calculate the number of bytes (for String/FixedString) or elements (for Array)."}};
23+
FunctionDocumentation::ReturnedValue returned_value = "Returns the number of number of bytes in the String/FixedString `x` / the number of elements in array `x`";
24+
FunctionDocumentation::Examples examples {
25+
{"string1", "SELECT length('Hello, world!')", "13"},
26+
{"arr1", "SELECT length(['Hello', 'world'])", "2"},
27+
{"constexpr", R"(
28+
WITH 'hello' || toString(number) AS str
29+
SELECT str,
30+
isConstant(length(str)) AS str_length_is_constant,
31+
isConstant(length(str::FixedString(6))) AS fixed_str_length_is_constant
32+
FROM numbers(3)
33+
)", R"(
34+
┌─str────┬─str_length_is_constant─┬─fixed_str_length_is_constant─┐
35+
│ hello0 │ 0 │ 1 │
36+
│ hello1 │ 0 │ 1 │
37+
│ hello2 │ 0 │ 1 │
38+
└────────┴────────────────────────┴──────────────────────────────┘
39+
)"},
40+
{"unicode", "SELECT 'ёлка' AS str1, length(str1), lengthUTF8(str1), normalizeUTF8NFKD(str1) AS str2, length(str2), lengthUTF8(str2)", R"(
41+
┌─str1─┬─length(str1)─┬─lengthUTF8(str1)─┬─str2─┬─length(str2)─┬─lengthUTF8(str2)─┐
42+
│ ёлка │ 8 │ 4 │ ёлка │ 10 │ 5 │
43+
└──────┴──────────────┴──────────────────┴──────┴──────────────┴──────────────────┘
44+
)"},
45+
{"ascii_vs_utf8", "SELECT 'ábc' AS str, length(str), lengthUTF8(str)", R"(
46+
┌─str─┬─length(str)──┬─lengthUTF8(str)─┐
47+
│ ábc │ 4 │ 3 │
48+
└─────┴──────────────┴─────────────────┘
49+
)"}
50+
};
51+
FunctionDocumentation::IntroducedIn introduced_in = {1, 1};
52+
FunctionDocumentation::Category category = FunctionDocumentation::Category::Array;
53+
FunctionDocumentation documentation = {description, syntax, arguments, returned_value, examples, introduced_in, category};
54+
55+
factory.registerFunction<FunctionLength>(documentation, FunctionFactory::Case::Insensitive);
4456
factory.registerAlias("OCTET_LENGTH", "length", FunctionFactory::Case::Insensitive);
4557
}
4658

src/Functions/array/range.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,33 @@ class FunctionRange : public IFunction
572572

573573
REGISTER_FUNCTION(Range)
574574
{
575-
factory.registerFunction<FunctionRange>();
575+
FunctionDocumentation::Description description = R"(
576+
Returns an array of numbers from `start` to `end - 1` by `step`.
577+
578+
The supported types are:
579+
- `UInt8/16/32/64`
580+
- `Int8/16/32/64]`
581+
582+
- All arguments `start`, `end`, `step` must be one of the above supported types. Elements of the returned array will be a super type of the arguments.
583+
- An exception is thrown if the function returns an array with a total length more than the number of elements specified by setting [`function_range_max_elements_in_block`](../../operations/settings/settings.md#function_range_max_elements_in_block).
584+
- Returns `NULL` if any argument has Nullable(nothing) type. An exception is thrown if any argument has `NULL` value (Nullable(T) type).
585+
)";
586+
FunctionDocumentation::Syntax syntax = "range([start, ] end [, step])";
587+
FunctionDocumentation::Arguments arguments = {
588+
{"start", "Optional. The first element of the array. Required if `step` is used. Default value: `0`."},
589+
{"end", "Required. The number before which the array is constructed."},
590+
{"step", "Optional. Determines the incremental step between each element in the array. Default value: `1`."},};
591+
FunctionDocumentation::ReturnedValue returned_value = "Array of numbers from `start` to `end - 1` by `step`.";
592+
FunctionDocumentation::Examples examples = {{"Usage example", "SELECT range(5), range(1, 5), range(1, 5, 2), range(-1, 5, 2);", R"(
593+
┌─range(5)────┬─range(1, 5)─┬─range(1, 5, 2)─┬─range(-1, 5, 2)─┐
594+
│ [0,1,2,3,4] │ [1,2,3,4] │ [1,3] │ [-1,1,3] │
595+
└─────────────┴─────────────┴────────────────┴─────────────────┘
596+
)"}};
597+
FunctionDocumentation::IntroducedIn introduced_in = {1, 1};
598+
FunctionDocumentation::Category category = FunctionDocumentation::Category::Array;
599+
FunctionDocumentation documentation = {description, syntax, arguments, returned_value, examples, introduced_in, category};
600+
601+
factory.registerFunction<FunctionRange>(documentation);
576602
}
577603

578604
}

0 commit comments

Comments
 (0)