support clamp function

This commit is contained in:
skyoct 2024-04-07 09:02:43 +00:00
parent 633aeaaa76
commit 307f69380e
4 changed files with 107 additions and 0 deletions

View File

@ -234,3 +234,34 @@ SELECT least(toDateTime32(now() + toIntervalDay(1)), toDateTime64(now(), 3))
:::note
The type returned is a DateTime64 as the DataTime32 must be promoted to 64 bit for the comparison.
:::
## clamp
Constrain the return value between A and B.
**Syntax**
``` sql
if(x, min, max)
```
**Arguments**
- `x` Input value.
- `min` Limit the lower bound.
- `max` Limit the upper bound.
**Returned values**
If the value is less than the minimum value, return the minimum value; if it is greater than the maximum value, return the maximum value; otherwise, return the current value.
Examples:
```sql
SELECT least(1, 2, 3) result, toTypeName(result) type;
```
```response
┌─result─┬─type────┐
│ 2 │ Float64 │
└────────┴─────────┘
```

68
src/Functions/clamp.cpp Normal file
View File

@ -0,0 +1,68 @@
#include <Functions/IFunction.h>
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionHelpers.h>
#include <DataTypes/getLeastSupertype.h>
#include <Interpreters/castColumn.h>
#include <Interpreters/Context.h>
namespace DB
{
namespace ErrorCodes
{
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
}
class FunctionClamp : public IFunction
{
public:
static constexpr auto name = "clamp";
String getName() const override { return name; }
size_t getNumberOfArguments() const override { return 0; }
bool isVariadic() const override { return true; }
bool useDefaultImplementationForConstants() const override { return true; }
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return false; }
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionClamp>(); }
DataTypePtr getReturnTypeImpl(const DataTypes & types) const override
{
if (types.size() != 3)
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function {} must be 3 arguments", getName());
return getLeastSupertype(types);
}
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
{
size_t arg_size = arguments.size();
Columns converted_columns(arg_size);
for (size_t arg = 0; arg < arg_size; ++arg)
converted_columns[arg] = castColumn(arguments[arg], result_type)->convertToFullColumnIfConst();
auto result_column = result_type->createColumn();
for (size_t row_num = 0; row_num < input_rows_count; ++row_num)
{
size_t best_arg = 0;
if (converted_columns[1]->compareAt(row_num, row_num, *converted_columns[best_arg], 1) > 0)
best_arg = 1;
else if (converted_columns[2]->compareAt(row_num, row_num, *converted_columns[best_arg], 1) < 0)
best_arg = 2;
result_column->insertFrom(*converted_columns[best_arg], row_num);
}
return result_column;
}
};
REGISTER_FUNCTION(Clamp)
{
factory.registerFunction<FunctionClamp>();
}
}

View File

@ -0,0 +1,4 @@
10
20
15
b

View File

@ -0,0 +1,4 @@
SELECT clamp(1, 10, 20);
SELECT clamp(30, 10, 20);
SELECT clamp(15, 10, 20);
SELECT clamp('a', 'b', 'c');