You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@age.apache.org by de...@apache.org on 2021/04/14 23:27:22 UTC

[incubator-age] branch master updated: Add operator overload for agtype to numeric

This is an automated email from the ASF dual-hosted git repository.

dehowef pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-age.git


The following commit(s) were added to refs/heads/master by this push:
     new 10734a4  Add operator overload for agtype to numeric
10734a4 is described below

commit 10734a461e5a945745bf64c6217265c6b4432f6e
Author: Dehowe Feng <de...@gmail.com>
AuthorDate: Tue Apr 13 17:45:45 2021 -0700

    Add operator overload for agtype to numeric
    
    Overloaded comparison and arithmetic operators to handle numerics.
    
    Added logic to handle agtype null input for any_functions.
    
    Added regression tests for mod cases, which were previously missing.
    
    Added regression tests to handle agtype null input.
---
 age--0.4.0.sql                     | 415 +++++++++++++++++++++++++++++++++++++
 regress/expected/agtype.out        | 232 +++++++++++++++++++++
 regress/sql/agtype.sql             |  50 ++++-
 src/backend/utils/adt/agtype_ops.c |  55 +++++
 4 files changed, 750 insertions(+), 2 deletions(-)

diff --git a/age--0.4.0.sql b/age--0.4.0.sql
index fe50462..1280d8c 100644
--- a/age--0.4.0.sql
+++ b/age--0.4.0.sql
@@ -514,6 +514,36 @@ CREATE OPERATOR + (
   COMMUTATOR = +
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_add(agtype, numeric)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR + (
+  FUNCTION = ag_catalog.agtype_any_add,
+  LEFTARG = agtype,
+  RIGHTARG =  numeric,
+  COMMUTATOR = +
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_add(numeric, agtype)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR + (
+  FUNCTION = ag_catalog.agtype_any_add,
+  LEFTARG = numeric,
+  RIGHTARG =  agtype,
+  COMMUTATOR = +
+);
+
 CREATE FUNCTION ag_catalog.agtype_sub(agtype, agtype)
 RETURNS agtype
 LANGUAGE c
@@ -668,6 +698,34 @@ CREATE OPERATOR - (
   RIGHTARG =  agtype
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_sub(agtype, numeric)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR - (
+  FUNCTION = ag_catalog.agtype_any_sub,
+  LEFTARG = agtype,
+  RIGHTARG =  numeric
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_sub(numeric, agtype)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR - (
+  FUNCTION = ag_catalog.agtype_any_sub,
+  LEFTARG = numeric,
+  RIGHTARG =  agtype
+);
+
 CREATE FUNCTION ag_catalog.agtype_neg(agtype)
 RETURNS agtype
 LANGUAGE c
@@ -846,6 +904,36 @@ CREATE OPERATOR * (
   COMMUTATOR = *
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_mul(agtype, numeric)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR * (
+  FUNCTION = ag_catalog.agtype_any_mul,
+  LEFTARG = agtype,
+  RIGHTARG =  numeric,
+  COMMUTATOR = *
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_mul(numeric, agtype)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR * (
+  FUNCTION = ag_catalog.agtype_any_mul,
+  LEFTARG = numeric,
+  RIGHTARG =  agtype,
+  COMMUTATOR = *
+);
+
 CREATE FUNCTION ag_catalog.agtype_div(agtype, agtype)
 RETURNS agtype
 LANGUAGE c
@@ -1000,6 +1088,34 @@ CREATE OPERATOR / (
   RIGHTARG =  agtype
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_div(agtype, numeric)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR / (
+  FUNCTION = ag_catalog.agtype_any_div,
+  LEFTARG = agtype,
+  RIGHTARG =  numeric
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_div(numeric, agtype)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR / (
+  FUNCTION = ag_catalog.agtype_any_div,
+  LEFTARG = numeric,
+  RIGHTARG =  agtype
+);
+
 CREATE FUNCTION ag_catalog.agtype_mod(agtype, agtype)
 RETURNS agtype
 LANGUAGE c
@@ -1098,6 +1214,89 @@ CREATE OPERATOR % (
   RIGHTARG =  agtype
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_mod(agtype, real)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR % (
+  FUNCTION = ag_catalog.agtype_any_mod,
+  LEFTARG = agtype,
+  RIGHTARG =  real
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_mod(real, agtype)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR % (
+  FUNCTION = ag_catalog.agtype_any_mod,
+  LEFTARG = real,
+  RIGHTARG =  agtype
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_mod(agtype, double precision)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR % (
+  FUNCTION = ag_catalog.agtype_any_mod,
+  LEFTARG = agtype,
+  RIGHTARG =  double precision
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_mod(double precision, agtype)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR % (
+  FUNCTION = ag_catalog.agtype_any_mod,
+  LEFTARG = double precision,
+  RIGHTARG =  agtype
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_mod(agtype, numeric)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR % (
+  FUNCTION = ag_catalog.agtype_any_mod,
+  LEFTARG = agtype,
+  RIGHTARG =  numeric
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_mod(numeric, agtype)
+RETURNS agtype
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR % (
+  FUNCTION = ag_catalog.agtype_any_mod,
+  LEFTARG = numeric,
+  RIGHTARG =  agtype
+);
 
 CREATE FUNCTION ag_catalog.agtype_pow(agtype, agtype)
 RETURNS agtype
@@ -1315,6 +1514,42 @@ CREATE OPERATOR = (
   JOIN = eqjoinsel
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_eq(agtype, numeric)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR = (
+  FUNCTION = ag_catalog.agtype_any_eq,
+  LEFTARG = agtype,
+  RIGHTARG = numeric,
+  COMMUTATOR = =,
+  NEGATOR = <>,
+  RESTRICT = eqsel,
+  JOIN = eqjoinsel
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_eq(numeric, agtype)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR = (
+  FUNCTION = ag_catalog.agtype_any_eq,
+  LEFTARG = numeric,
+  RIGHTARG = agtype,
+  COMMUTATOR = =,
+  NEGATOR = <>,
+  RESTRICT = eqsel,
+  JOIN = eqjoinsel
+);
+
 CREATE FUNCTION ag_catalog.agtype_ne(agtype, agtype)
 RETURNS boolean
 LANGUAGE c
@@ -1513,6 +1748,42 @@ CREATE OPERATOR <> (
   JOIN = neqjoinsel
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_ne(agtype, numeric)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR <> (
+  FUNCTION = ag_catalog.agtype_any_ne,
+  LEFTARG = agtype,
+  RIGHTARG = numeric,
+  COMMUTATOR = <>,
+  NEGATOR = =,
+  RESTRICT = neqsel,
+  JOIN = neqjoinsel
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_ne(numeric, agtype)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR <> (
+  FUNCTION = ag_catalog.agtype_any_ne,
+  LEFTARG = numeric,
+  RIGHTARG = agtype,
+  COMMUTATOR = <>,
+  NEGATOR = =,
+  RESTRICT = neqsel,
+  JOIN = neqjoinsel
+);
+
 CREATE FUNCTION ag_catalog.agtype_lt(agtype, agtype)
 RETURNS boolean
 LANGUAGE c
@@ -1711,6 +1982,42 @@ CREATE OPERATOR < (
   JOIN = scalarltjoinsel
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_lt(agtype, numeric)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR < (
+  FUNCTION = ag_catalog.agtype_any_lt,
+  LEFTARG = agtype,
+  RIGHTARG = numeric,
+  COMMUTATOR = >,
+  NEGATOR = >=,
+  RESTRICT = scalarltsel,
+  JOIN = scalarltjoinsel
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_lt(numeric, agtype)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR < (
+  FUNCTION = ag_catalog.agtype_any_lt,
+  LEFTARG = numeric,
+  RIGHTARG = agtype,
+  COMMUTATOR = >,
+  NEGATOR = >=,
+  RESTRICT = scalarltsel,
+  JOIN = scalarltjoinsel
+);
+
 CREATE FUNCTION ag_catalog.agtype_gt(agtype, agtype)
 RETURNS boolean
 LANGUAGE c
@@ -1909,6 +2216,42 @@ CREATE OPERATOR > (
   JOIN = scalargtjoinsel
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_gt(agtype, numeric)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR > (
+  FUNCTION = ag_catalog.agtype_any_gt,
+  LEFTARG = agtype,
+  RIGHTARG = numeric,
+  COMMUTATOR = <,
+  NEGATOR = <=,
+  RESTRICT = scalargtsel,
+  JOIN = scalargtjoinsel
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_gt(numeric, agtype)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR > (
+  FUNCTION = ag_catalog.agtype_any_gt,
+  LEFTARG = numeric,
+  RIGHTARG = agtype,
+  COMMUTATOR = <,
+  NEGATOR = <=,
+  RESTRICT = scalargtsel,
+  JOIN = scalargtjoinsel
+);
+
 CREATE FUNCTION ag_catalog.agtype_le(agtype, agtype)
 RETURNS boolean
 LANGUAGE c
@@ -2107,6 +2450,42 @@ CREATE OPERATOR <= (
   JOIN = scalarlejoinsel
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_le(agtype, numeric)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR <= (
+  FUNCTION = ag_catalog.agtype_any_le,
+  LEFTARG = agtype,
+  RIGHTARG = numeric,
+  COMMUTATOR = >=,
+  NEGATOR = >,
+  RESTRICT = scalarlesel,
+  JOIN = scalarlejoinsel
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_le(numeric, agtype)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR <= (
+  FUNCTION = ag_catalog.agtype_any_le,
+  LEFTARG = numeric,
+  RIGHTARG = agtype,
+  COMMUTATOR = >=,
+  NEGATOR = >,
+  RESTRICT = scalarlesel,
+  JOIN = scalarlejoinsel
+);
+
 CREATE FUNCTION ag_catalog.agtype_ge(agtype, agtype)
 RETURNS boolean
 LANGUAGE c
@@ -2305,6 +2684,42 @@ CREATE OPERATOR >= (
   JOIN = scalargejoinsel
 );
 
+CREATE FUNCTION ag_catalog.agtype_any_ge(agtype, numeric)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR >= (
+  FUNCTION = ag_catalog.agtype_any_ge,
+  LEFTARG = agtype,
+  RIGHTARG = numeric,
+  COMMUTATOR = <=,
+  NEGATOR = <,
+  RESTRICT = scalargesel,
+  JOIN = scalargejoinsel
+);
+
+CREATE FUNCTION ag_catalog.agtype_any_ge(numeric, agtype)
+RETURNS boolean
+LANGUAGE c
+STABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
+CREATE OPERATOR >= (
+  FUNCTION = ag_catalog.agtype_any_ge,
+  LEFTARG = numeric,
+  RIGHTARG = agtype,
+  COMMUTATOR = <=,
+  NEGATOR = <,
+  RESTRICT = scalargesel,
+  JOIN = scalargejoinsel
+);
+
 CREATE FUNCTION ag_catalog.agtype_btree_cmp(agtype, agtype)
 RETURNS INTEGER
 LANGUAGE c
diff --git a/regress/expected/agtype.out b/regress/expected/agtype.out
index 4701d64..1022e95 100644
--- a/regress/expected/agtype.out
+++ b/regress/expected/agtype.out
@@ -339,6 +339,48 @@ SELECT agtype_div('4.0::numeric', '-3::numeric');
  -1.3333333333333333::numeric
 (1 row)
 
+SELECT agtype_mod('-11', '3');
+ agtype_mod 
+------------
+ -2
+(1 row)
+
+SELECT agtype_mod('11', '-3.0');
+ agtype_mod 
+------------
+ 2.0
+(1 row)
+
+SELECT agtype_mod('-11.0', '3');
+ agtype_mod 
+------------
+ -2.0
+(1 row)
+
+SELECT agtype_mod('11.0', '-3.0');
+ agtype_mod 
+------------
+ 2.0
+(1 row)
+
+SELECT agtype_mod('11', '-3.0::numeric');
+  agtype_mod  
+--------------
+ 2.0::numeric
+(1 row)
+
+SELECT agtype_mod('-11.0', '3::numeric');
+ agtype_mod  
+-------------
+ -2::numeric
+(1 row)
+
+SELECT agtype_mod('11.0::numeric', '-3::numeric');
+  agtype_mod  
+--------------
+ 2.0::numeric
+(1 row)
+
 SELECT agtype_pow('-2', '3');
  agtype_pow 
 ------------
@@ -493,6 +535,30 @@ SELECT agtype_any_div('-4.0::numeric', 3);
  -1.3333333333333333::numeric
 (1 row)
 
+SELECT agtype_any_mod('-11', 3);
+ agtype_any_mod 
+----------------
+ -2
+(1 row)
+
+SELECT agtype_any_mod('11.0', -3);
+ agtype_any_mod 
+----------------
+ 2.0
+(1 row)
+
+SELECT agtype_any_mod('-11::numeric', 3);
+ agtype_any_mod 
+----------------
+ -2::numeric
+(1 row)
+
+SELECT agtype_any_mod('-11.0::numeric', 3);
+ agtype_any_mod 
+----------------
+ -2.0::numeric
+(1 row)
+
 --
 -- Should fail with divide by zero
 --
@@ -809,6 +875,172 @@ SELECT 3 % '3.14::numeric'::agtype;
 (1 row)
 
 --
+-- Test overloaded agytype any functions and operators for NULL input 
+-- +, -, *, /, %, =, <>, <, >, <=, >=
+-- These should all return null
+SELECT agtype_any_add('null'::agtype, 1);
+ agtype_any_add 
+----------------
+ 
+(1 row)
+
+SELECT agtype_any_sub('null'::agtype, 1);
+ agtype_any_sub 
+----------------
+ 
+(1 row)
+
+SELECT agtype_any_mul('null'::agtype, 1);
+ agtype_any_mul 
+----------------
+ 
+(1 row)
+
+SELECT agtype_any_div('null'::agtype, 1);
+ agtype_any_div 
+----------------
+ 
+(1 row)
+
+SELECT agtype_any_mod('null'::agtype, 1);
+ agtype_any_mod 
+----------------
+ 
+(1 row)
+
+SELECT 1 + 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT 1 - 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT 1 * 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT 1 / 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT 1 % 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT agtype_any_add('null'::agtype, 1);
+ agtype_any_add 
+----------------
+ 
+(1 row)
+
+SELECT agtype_any_sub('null'::agtype, 1);
+ agtype_any_sub 
+----------------
+ 
+(1 row)
+
+SELECT agtype_any_mul('null'::agtype, 1);
+ agtype_any_mul 
+----------------
+ 
+(1 row)
+
+SELECT agtype_any_div('null'::agtype, 1);
+ agtype_any_div 
+----------------
+ 
+(1 row)
+
+SELECT agtype_any_mod('null'::agtype, 1);
+ agtype_any_mod 
+----------------
+ 
+(1 row)
+
+SELECT 1 = 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT 1 <> 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT 1 < 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT 1 > 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT 1 <= 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT 1 >= 'null'::agtype;
+ ?column? 
+----------
+ 
+(1 row)
+
+SELECT agtype_any_eq('null'::agtype, 1);
+ agtype_any_eq 
+---------------
+ 
+(1 row)
+
+SELECT agtype_any_ne('null'::agtype, 1);
+ agtype_any_ne 
+---------------
+ 
+(1 row)
+
+SELECT agtype_any_lt('null'::agtype, 1);
+ agtype_any_lt 
+---------------
+ 
+(1 row)
+
+SELECT agtype_any_gt('null'::agtype, 1);
+ agtype_any_gt 
+---------------
+ 
+(1 row)
+
+SELECT agtype_any_le('null'::agtype, 1);
+ agtype_any_le 
+---------------
+ 
+(1 row)
+
+SELECT agtype_any_ge('null'::agtype, 1);
+ agtype_any_ge 
+---------------
+ 
+(1 row)
+
+--
 -- Test orderability of comparison operators =, <>, <, >, <=, >=
 -- These should all return true
 -- Integer
diff --git a/regress/sql/agtype.sql b/regress/sql/agtype.sql
index fd9c194..f6ee3f3 100644
--- a/regress/sql/agtype.sql
+++ b/regress/sql/agtype.sql
@@ -133,6 +133,13 @@ SELECT agtype_div('4', '-3.0::numeric');
 SELECT agtype_div('-4.0', '3::numeric');
 SELECT agtype_div('4.0::numeric', '-3::numeric');
 
+SELECT agtype_mod('-11', '3');
+SELECT agtype_mod('11', '-3.0');
+SELECT agtype_mod('-11.0', '3');
+SELECT agtype_mod('11.0', '-3.0');
+SELECT agtype_mod('11', '-3.0::numeric');
+SELECT agtype_mod('-11.0', '3::numeric');
+SELECT agtype_mod('11.0::numeric', '-3::numeric');
 
 SELECT agtype_pow('-2', '3');
 SELECT agtype_pow('2', '-1.0');
@@ -148,7 +155,6 @@ SELECT agtype_pow('2.0::numeric', '-1.0::numeric');
 -- Test overloaded agtype any mathematical operator functions
 -- +, -, *, /, and %
 --
-
 SELECT agtype_any_add('1', -1);
 SELECT agtype_any_add('1.0', -1);
 SELECT agtype_any_add('1::numeric', 1);
@@ -168,6 +174,11 @@ SELECT agtype_any_div('-4', 3);
 SELECT agtype_any_div('4.0', -3);
 SELECT agtype_any_div('-4::numeric', 3);
 SELECT agtype_any_div('-4.0::numeric', 3);
+
+SELECT agtype_any_mod('-11', 3);
+SELECT agtype_any_mod('11.0', -3);
+SELECT agtype_any_mod('-11::numeric', 3);
+SELECT agtype_any_mod('-11.0::numeric', 3);
 --
 -- Should fail with divide by zero
 --
@@ -220,7 +231,6 @@ SELECT '3.14::numeric'::agtype + '3.14::numeric'::agtype;
 --
 -- Test overloaded agytype any operators +, -, *, /, %
 --
-
 SELECT '3'::agtype + 3;
 SELECT '3.14'::agtype + 3;
 SELECT '3.14::numeric'::agtype + 3;
@@ -257,6 +267,42 @@ SELECT 3 % '3.14'::agtype;
 SELECT 3 % '3.14::numeric'::agtype;
 
 --
+-- Test overloaded agytype any functions and operators for NULL input 
+-- +, -, *, /, %, =, <>, <, >, <=, >=
+-- These should all return null
+SELECT agtype_any_add('null'::agtype, 1);
+SELECT agtype_any_sub('null'::agtype, 1);
+SELECT agtype_any_mul('null'::agtype, 1);
+SELECT agtype_any_div('null'::agtype, 1);
+SELECT agtype_any_mod('null'::agtype, 1);
+
+SELECT 1 + 'null'::agtype;
+SELECT 1 - 'null'::agtype;
+SELECT 1 * 'null'::agtype;
+SELECT 1 / 'null'::agtype;
+SELECT 1 % 'null'::agtype;
+
+SELECT agtype_any_add('null'::agtype, 1);
+SELECT agtype_any_sub('null'::agtype, 1);
+SELECT agtype_any_mul('null'::agtype, 1);
+SELECT agtype_any_div('null'::agtype, 1);
+SELECT agtype_any_mod('null'::agtype, 1);
+
+SELECT 1 = 'null'::agtype;
+SELECT 1 <> 'null'::agtype;
+SELECT 1 < 'null'::agtype;
+SELECT 1 > 'null'::agtype;
+SELECT 1 <= 'null'::agtype;
+SELECT 1 >= 'null'::agtype;
+
+SELECT agtype_any_eq('null'::agtype, 1);
+SELECT agtype_any_ne('null'::agtype, 1);
+SELECT agtype_any_lt('null'::agtype, 1);
+SELECT agtype_any_gt('null'::agtype, 1);
+SELECT agtype_any_le('null'::agtype, 1);
+SELECT agtype_any_ge('null'::agtype, 1);
+
+--
 -- Test orderability of comparison operators =, <>, <, >, <=, >=
 -- These should all return true
 -- Integer
diff --git a/src/backend/utils/adt/agtype_ops.c b/src/backend/utils/adt/agtype_ops.c
index 21e8e3b..7cf0541 100644
--- a/src/backend/utils/adt/agtype_ops.c
+++ b/src/backend/utils/adt/agtype_ops.c
@@ -247,6 +247,11 @@ Datum agtype_any_add(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_add, AGTYPE_P_GET_DATUM(lhs),
                                              AGTYPE_P_GET_DATUM(rhs));
 
@@ -332,6 +337,11 @@ Datum agtype_any_sub(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_sub, AGTYPE_P_GET_DATUM(lhs),
                                              AGTYPE_P_GET_DATUM(rhs));
 
@@ -465,6 +475,11 @@ Datum agtype_any_mul(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_mul, AGTYPE_P_GET_DATUM(lhs),
                                              AGTYPE_P_GET_DATUM(rhs));
 
@@ -578,6 +593,11 @@ Datum agtype_any_div(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_div, AGTYPE_P_GET_DATUM(lhs),
                                              AGTYPE_P_GET_DATUM(rhs));
 
@@ -663,6 +683,11 @@ Datum agtype_any_mod(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_mod, AGTYPE_P_GET_DATUM(lhs),
                                              AGTYPE_P_GET_DATUM(rhs));
 
@@ -764,6 +789,11 @@ Datum agtype_any_eq(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_eq, AGTYPE_P_GET_DATUM(lhs),
                                             AGTYPE_P_GET_DATUM(rhs));
 
@@ -798,6 +828,11 @@ Datum agtype_any_ne(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_ne, AGTYPE_P_GET_DATUM(lhs),
                                             AGTYPE_P_GET_DATUM(rhs));
 
@@ -832,6 +867,11 @@ Datum agtype_any_lt(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_lt, AGTYPE_P_GET_DATUM(lhs),
                                             AGTYPE_P_GET_DATUM(rhs));
 
@@ -866,6 +906,11 @@ Datum agtype_any_gt(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_gt, AGTYPE_P_GET_DATUM(lhs),
                                             AGTYPE_P_GET_DATUM(rhs));
 
@@ -900,6 +945,11 @@ Datum agtype_any_le(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_le, AGTYPE_P_GET_DATUM(lhs),
                                             AGTYPE_P_GET_DATUM(rhs));
 
@@ -934,6 +984,11 @@ Datum agtype_any_ge(PG_FUNCTION_ARGS)
     lhs = get_one_agtype_from_variadic_args(fcinfo, 0, 2);
     rhs = get_one_agtype_from_variadic_args(fcinfo, 1, 1);
 
+    if (lhs == NULL || rhs == NULL)
+    {
+        PG_RETURN_NULL();
+    }
+
     result = DirectFunctionCall2(agtype_ge, AGTYPE_P_GET_DATUM(lhs),
                                             AGTYPE_P_GET_DATUM(rhs));