diff --git a/sql3/errors.go b/sql3/errors.go index 3e2e2983f..620abcf47 100644 --- a/sql3/errors.go +++ b/sql3/errors.go @@ -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), + ) +} diff --git a/sql3/planner/expression.go b/sql3/planner/expression.go index b884f5935..bb945a9d5 100644 --- a/sql3/planner/expression.go +++ b/sql3/planner/expression.go @@ -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 diff --git a/sql3/test/defs/defs_binops.go b/sql3/test/defs/defs_binops.go index 83d9a4232..b2889b65a 100644 --- a/sql3/test/defs/defs_binops.go +++ b/sql3/test/defs/defs_binops.go @@ -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;",