1#pragma once
2
3#include <DataTypes/DataTypesNumber.h>
4#include <Columns/ColumnVector.h>
5#include <Functions/IFunctionImpl.h>
6#include <IO/WriteHelpers.h>
7
8
9namespace DB
10{
11
12namespace ErrorCodes
13{
14 extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
15}
16
17/** Pseudo-random number generation functions.
18 * The function can be called without arguments or with one argument.
19 * The argument is ignored and only serves to ensure that several calls to one function are considered different and do not stick together.
20 *
21 * Example:
22 * SELECT rand(), rand() - will output two identical columns.
23 * SELECT rand(1), rand(2) - will output two different columns.
24 *
25 * Non-cryptographic generators:
26 *
27 * rand - linear congruential generator 0 .. 2^32 - 1.
28 * rand64 - combines several rand values to get values from the range 0 .. 2^64 - 1.
29 *
30 * randConstant - service function, produces a constant column with a random value.
31 *
32 * The time is used as the seed.
33 * Note: it is reinitialized for each block.
34 * This means that the timer must be of sufficient resolution to give different values to each block.
35 */
36
37struct RandImpl
38{
39 /// Fill memory with random data. The memory region must be 15-bytes padded.
40 static void execute(char * output, size_t size);
41};
42
43
44template <typename ToType, typename Name>
45class FunctionRandom : public IFunction
46{
47public:
48 static constexpr auto name = Name::name;
49 static FunctionPtr create(const Context &) { return std::make_shared<FunctionRandom>(); }
50
51 String getName() const override
52 {
53 return name;
54 }
55
56 bool isDeterministic() const override { return false; }
57 bool isDeterministicInScopeOfQuery() const override { return false; }
58 bool useDefaultImplementationForNulls() const override { return false; }
59
60 bool isVariadic() const override { return true; }
61 size_t getNumberOfArguments() const override { return 0; }
62
63 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
64 {
65 if (arguments.size() > 1)
66 throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
67 + toString(arguments.size()) + ", should be 0 or 1.",
68 ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
69
70 return std::make_shared<DataTypeNumber<ToType>>();
71 }
72
73 void executeImpl(Block & block, const ColumnNumbers &, size_t result, size_t input_rows_count) override
74 {
75 auto col_to = ColumnVector<ToType>::create();
76 typename ColumnVector<ToType>::Container & vec_to = col_to->getData();
77
78 size_t size = input_rows_count;
79 vec_to.resize(size);
80 RandImpl::execute(reinterpret_cast<char *>(vec_to.data()), vec_to.size() * sizeof(ToType));
81
82 block.getByPosition(result).column = std::move(col_to);
83 }
84};
85
86}
87