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
35 changes: 35 additions & 0 deletions regress/expected/agtype.out
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,41 @@ SELECT agtype_any_div('-1::numeric', 0);
ERROR: division by zero
SELECT agtype_any_div('-1.0::numeric', 0);
ERROR: division by zero
SELECT agtype_mod('1', '0');
ERROR: division by zero
SELECT agtype_mod('1', '0.0');
ERROR: division by zero
SELECT agtype_mod('1.0', '0');
ERROR: division by zero
SELECT agtype_mod('1.0', '0.0');
ERROR: division by zero
SELECT agtype_mod('1', '0::numeric');
ERROR: division by zero
SELECT agtype_mod('1.0', '0::numeric');
ERROR: division by zero
SELECT agtype_mod('1::numeric', '0');
ERROR: division by zero
SELECT agtype_mod('1::numeric', '0.0');
ERROR: division by zero
SELECT agtype_mod('1::numeric', '0::numeric');
ERROR: division by zero
SELECT agtype_any_mod('1', 0);
ERROR: division by zero
SELECT agtype_any_mod('1.0', 0);
ERROR: division by zero
SELECT agtype_any_mod('-1::numeric', 0);
ERROR: division by zero
SELECT agtype_any_mod('-1.0::numeric', 0);
ERROR: division by zero
--
-- Should get 0 - INT64_MIN % -1 is well defined
--
SELECT agtype_mod('-9223372036854775808', '-1');
agtype_mod
------------
0
(1 row)

--
-- Should get Infinity
--
Expand Down
20 changes: 20 additions & 0 deletions regress/sql/agtype.sql
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,26 @@ SELECT agtype_any_div('1.0', 0);
SELECT agtype_any_div('-1::numeric', 0);
SELECT agtype_any_div('-1.0::numeric', 0);

SELECT agtype_mod('1', '0');
SELECT agtype_mod('1', '0.0');
SELECT agtype_mod('1.0', '0');
SELECT agtype_mod('1.0', '0.0');
SELECT agtype_mod('1', '0::numeric');
SELECT agtype_mod('1.0', '0::numeric');
SELECT agtype_mod('1::numeric', '0');
SELECT agtype_mod('1::numeric', '0.0');
SELECT agtype_mod('1::numeric', '0::numeric');

SELECT agtype_any_mod('1', 0);
SELECT agtype_any_mod('1.0', 0);
SELECT agtype_any_mod('-1::numeric', 0);
SELECT agtype_any_mod('-1.0::numeric', 0);

--
-- Should get 0 - INT64_MIN % -1 is well defined
--
SELECT agtype_mod('-9223372036854775808', '-1');

--
-- Should get Infinity
--
Expand Down
44 changes: 42 additions & 2 deletions src/backend/utils/adt/agtype_ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -912,24 +912,64 @@ Datum agtype_mod(PG_FUNCTION_ARGS)

if (agtv_lhs->type == AGTV_INTEGER && agtv_rhs->type == AGTV_INTEGER)
{
if (agtv_rhs->val.int_value == 0)
{
ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
PG_RETURN_NULL();
}

agtv_result.type = AGTV_INTEGER;
agtv_result.val.int_value = agtv_lhs->val.int_value %
agtv_rhs->val.int_value;

/*
* INT64_MIN % -1 is zero but overflows the quotient, which traps on
* some platforms. int8mod special cases it the same way.
*/
if (agtv_rhs->val.int_value == -1)
{
agtv_result.val.int_value = 0;
}
else
{
agtv_result.val.int_value = agtv_lhs->val.int_value %
agtv_rhs->val.int_value;
}
}
else if (agtv_lhs->type == AGTV_FLOAT && agtv_rhs->type == AGTV_FLOAT)
{
if (agtv_rhs->val.float_value == 0)
{
ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
PG_RETURN_NULL();
}

agtv_result.type = AGTV_FLOAT;
agtv_result.val.float_value = fmod(agtv_lhs->val.float_value,
agtv_rhs->val.float_value);
}
else if (agtv_lhs->type == AGTV_FLOAT && agtv_rhs->type == AGTV_INTEGER)
{
if (agtv_rhs->val.int_value == 0)
{
ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
PG_RETURN_NULL();
}

agtv_result.type = AGTV_FLOAT;
agtv_result.val.float_value = fmod(agtv_lhs->val.float_value,
agtv_rhs->val.int_value);
}
else if (agtv_lhs->type == AGTV_INTEGER && agtv_rhs->type == AGTV_FLOAT)
{
if (agtv_rhs->val.float_value == 0)
{
ereport(ERROR, (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
PG_RETURN_NULL();
}

agtv_result.type = AGTV_FLOAT;
agtv_result.val.float_value = fmod(agtv_lhs->val.int_value,
agtv_rhs->val.float_value);
Expand Down
Loading