Gracefully handle divide by zero (#2306)

Divide by zero in SQL expressions will be reported as SQL errors.
This commit is contained in:
Vengata Krishnan 2023-03-08 16:51:28 -05:00 committed by GitHub
parent ecda941aac
commit 4d484641f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 2 deletions

View file

@ -139,6 +139,9 @@ const (
ErrQRangeFromAndToTimeCannotBeBothNull errors.Code = "ErrQRangeFromAndToTimeCannotBeBothNull"
ErrQRangeInvalidUse errors.Code = "ErrQRangeInvalidUse"
ErrYearOutOfRange errors.Code = "ErrYearOutOfRange"
//evaluate errors
ErrDivideByZero errors.Code = "ErrDivideByZero"
)
func NewErrDuplicateColumn(line int, col int, column string) error {
@ -860,3 +863,10 @@ func NewErrYearOutOfRange(line, col int, year int) error {
fmt.Sprintf("[%d:%d] year '%d' out of range [0,9999]", line, col, year),
)
}
func NewErrDivideByZero(line, col int) error {
return errors.New(
ErrDivideByZero,
fmt.Sprintf("[%d:%d] divisor is equal to zero", line, col),
)
}

View file

@ -419,11 +419,15 @@ func (n *binOpPlanExpression) Evaluate(currentRow []interface{}) (interface{}, e
case parser.STAR:
return nl * nr, nil
case parser.SLASH:
if nr == 0 {
return nil, sql3.NewErrDivideByZero(0, 0)
}
return nl / nr, nil
case parser.REM:
if nr == 0 {
return nil, sql3.NewErrDivideByZero(0, 0)
}
return nl % nr, nil
default:
return nil, sql3.NewErrInternalf("unhandled operator %d", n.op)
}
@ -2747,10 +2751,16 @@ func (p *ExecutionPlanner) compileBinaryExpr(expr *parser.BinaryExpr) (_ types.P
return newIntLiteralPlanExpression(value), nil
case parser.SLASH:
if numy == 0 {
return nil, sql3.NewErrDivideByZero(expr.OpPos.Line, expr.OpPos.Column)
}
value := numx / numy
return newIntLiteralPlanExpression(value), nil
case parser.REM:
if numy == 0 {
return nil, sql3.NewErrDivideByZero(expr.OpPos.Line, expr.OpPos.Column)
}
value := numx % numy
return newIntLiteralPlanExpression(value), nil

View file

@ -20,6 +20,34 @@ var binOpExprWithIntInt = TableTest{
),
),
SQLTests: []SQLTest{
{
name: "DivisionDivideByZeroLiteral",
SQLs: sqls(
"select 1/0",
),
ExpErr: "divisor is equal to zero",
},
{
name: "DivisionDivideByZeroRow",
SQLs: sqls(
"select a/0 from binoptesti_i;",
),
ExpErr: "divisor is equal to zero",
},
{
name: "ModuloDivideByZeroLiteral",
SQLs: sqls(
"select 1%0",
),
ExpErr: "divisor is equal to zero",
},
{
name: "ModuloDivideByZeroRow",
SQLs: sqls(
"select a%0 from binoptesti_i;",
),
ExpErr: "divisor is equal to zero",
},
{
SQLs: sqls(
"select a != b from binoptesti_i;",