Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion pkg/sql/plan/function/func_binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -6722,15 +6722,25 @@ func Power(ivecs []*vector.Vector, result vector.FunctionResultWrapper, _ *proce
rs := vector.MustFunctionResult[float64](result)

for i := uint64(0); i < uint64(length); i++ {
if selectList != nil && (selectList.IgnoreAllRow() ||
(!selectList.ShouldEvalAllRow() && selectList.Contains(i))) {
if err = rs.Append(0, true); err != nil {
return err
}
continue
}
v1, null1 := p1.GetValue(i)
v2, null2 := p2.GetValue(i)
if null1 || null2 {
if err = rs.Append(0, true); err != nil {
return err
}
} else {
//TODO: Ignoring 4 switch cases:https://github.com/m-schen/matrixone/blob/0c480ca11b6302de26789f916a3e2faca7f79d47/pkg/sql/plan/function/builtin/binary/power.go#L36
res := math.Pow(v1, v2)
if math.IsNaN(res) || math.IsInf(res, 0) {
return moerr.NewOutOfRangeNoCtxf(
"float64", "DOUBLE value is out of range in 'pow(%v,%v)'", v1, v2)
}
if err = rs.Append(res, false); err != nil {
return err
}
Expand Down
62 changes: 62 additions & 0 deletions pkg/sql/plan/function/func_binary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5033,6 +5033,68 @@ func TestPower(t *testing.T) {
}
}

func TestPowerOutOfRange(t *testing.T) {
testCases := []struct {
name string
bases []float64
exponents []float64
}{
{name: "negative base with fractional exponent", bases: []float64{-2}, exponents: []float64{0.5}},
{name: "zero base with negative exponent", bases: []float64{0}, exponents: []float64{-1}},
{name: "invalid value after valid value", bases: []float64{2, -2}, exponents: []float64{3, 0.5}},
}

proc := testutil.NewProcess(t)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
tcc := NewFunctionTestCase(
proc,
[]FunctionTestInput{
NewFunctionTestInput(types.T_float64.ToType(), tc.bases, nil),
NewFunctionTestInput(types.T_float64.ToType(), tc.exponents, nil),
},
NewFunctionTestResult(types.T_float64.ToType(), true, []float64{0}, nil),
Power,
)

require.NoError(t, tcc.result.PreExtendAndReset(tcc.fnLength))
_, err := tcc.DebugRun()
require.Error(t, err)
require.True(t, moerr.IsMoErrCode(err, moerr.ErrOutOfRange))
require.ErrorContains(t, err, "DOUBLE value is out of range")
})
}
}

func TestPowerRespectsSelectList(t *testing.T) {
proc := testutil.NewProcess(t)
inputs := []FunctionTestInput{
NewFunctionTestInput(types.T_float64.ToType(), []float64{-2, 2}, nil),
NewFunctionTestInput(types.T_float64.ToType(), []float64{0.5, 3}, nil),
}
tcc := NewFunctionTestCase(
proc,
inputs,
NewFunctionTestResult(types.T_float64.ToType(), false, []float64{0, 8}, []bool{true, false}),
Power,
)
require.NoError(t, tcc.result.PreExtendAndReset(tcc.fnLength))

selectList := &FunctionSelectList{
AnyNull: true,
SelectList: []bool{false, true},
}
err := Power(tcc.parameters, tcc.result, proc, tcc.fnLength, selectList)
require.NoError(t, err)

resultVec := tcc.result.GetResultVector()
require.True(t, resultVec.GetNulls().Contains(0))
resultParam := vector.GenerateFunctionFixedTypeParameter[float64](resultVec)
value, isNull := resultParam.GetValue(1)
require.False(t, isNull)
require.Equal(t, float64(8), value)
}

// TRUNCATE
func initTruncateTestCase() []tcTemp {
cases := []struct {
Expand Down
10 changes: 10 additions & 0 deletions test/distributed/cases/function/func_math_power.result
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ result5
SELECT POWER(4, 0.5) AS result6;
result6
2.0
SELECT POW(-2, 0.5);
Data truncation: data out of range: data type float64, DOUBLE value is out of range in 'pow(-2,0.5)'
SELECT POWER(0, -1);
Data truncation: data out of range: data type float64, DOUBLE value is out of range in 'pow(0,-1)'
SELECT IF(0, POW(-2, 0.5), 1);
IF(0, POW(-2, 0.5), 1)
1.0
SELECT CASE WHEN 0 THEN POWER(0, -1) ELSE 1 END;
case when 0 then POWER(0, -1) else 1 end
1.0
SELECT POW(2, 3) = POWER(2, 3) AS same_result;
same_result
1
Expand Down
7 changes: 6 additions & 1 deletion test/distributed/cases/function/func_math_power.test
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ SELECT POWER(2, 3) AS result4;
SELECT POWER(2, 0) AS result5;
SELECT POWER(4, 0.5) AS result6;

#SELECT - Out-of-range results
SELECT POW(-2, 0.5);
SELECT POWER(0, -1);
SELECT IF(0, POW(-2, 0.5), 1);
SELECT CASE WHEN 0 THEN POWER(0, -1) ELSE 1 END;

#SELECT - Verify POW and POWER are aliases
SELECT POW(2, 3) = POWER(2, 3) AS same_result;

Expand Down Expand Up @@ -75,4 +81,3 @@ create table t1(a float, b float);
insert into t1 values(14.3, 4.413), (9.123, 9.409);
select b from t1 group by b having power(1,b)>0;
drop table t1;

Loading