For example, if I use UInt8 constant for if condition then only one branch is evaluated:
```sql
SELECT if(1, 'success', throwIf(1, 'Executing FALSE branch'))

┌─'success'─┐
│ success   │
└───────────┘

1 rows in set. Elapsed: 0.003 sec.
```

But if I use some constant expression, then both branches are evaluated:
```sql
SELECT if(empty(''), 'success', throwIf(1, 'Executing FALSE branch'))

0 rows in set. Elapsed: 0.003 sec.

Received exception from server (version 21.12.2):
Code: 395. DB::Exception: Received from localhost:9000. DB::Exception: Executing FALSE branch: While processing if(empty(''), 'success', throwIf(1, 'Executing FALSE branch')). (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO)
```
{
        size_t size = cond.size();
        auto col_res = ColVecResult::create(size);
        ArrayResult & res = col_res->getData();
        for (size_t i = 0; i < size; ++i)
            res[i] = cond[i] ? static_cast<ResultType>(a) : static_cast<ResultType>(b);
        return col_res;
    }
};
template <typename A, typename B, typename R>
struct NumIfImpl<Decimal<A>, Decimal<B>, Decimal<R>>
{
    using ResultType = Decimal<R>;
    using ArrayCond = PaddedPODArray<UInt8>;
    using ArrayA = typename ColumnDecimal<Decimal<A>>::Container;
    using ArrayB = typename ColumnDecimal<Decimal<B>>::Container;
    using ColVecResult = ColumnDecimal<ResultType>;
    using Block = ColumnsWithTypeAndName;
    using ArrayResult = typename ColVecResult::Container;
    static ColumnPtr vectorVector(const ArrayCond & cond, const ArrayA & a, const ArrayB & b, UInt32 scale)
    {
        size_t size = cond.size();
        auto col_res = ColVecResult::create(size, scale);
        ArrayResult & res = col_res->getData();
        fillVectorVector<ArrayCond, ArrayA, ArrayB, ArrayResult, ResultType>(cond, a, b, res);
        return col_res;
    }
    static ColumnPtr vectorConstant(const ArrayCond & cond, const ArrayA & a, B b, UInt32 scale)