You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@age.apache.org by jg...@apache.org on 2020/09/22 20:46:32 UTC

[incubator-age] branch master updated: Add the openCypher function sqrt()

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

jgemignani 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 fc1903f  Add the openCypher function sqrt()
fc1903f is described below

commit fc1903f478de34e6b7d3343d6bd9cc0769f74087
Author: John Gemignani <jr...@gmail.com>
AuthorDate: Mon Sep 21 17:03:03 2020 -0700

    Add the openCypher function sqrt()
    
    Added the openCypher function sqrt().
    
    Added regression tests.
---
 age--0.2.0.sql                   |  7 +++++
 regress/expected/expr.out        | 55 ++++++++++++++++++++++++++++++++++++
 regress/sql/expr.sql             | 27 ++++++++++++++++++
 src/backend/parser/cypher_expr.c |  3 +-
 src/backend/utils/adt/agtype.c   | 61 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 152 insertions(+), 1 deletion(-)

diff --git a/age--0.2.0.sql b/age--0.2.0.sql
index aa5bf5a..a91615d 100644
--- a/age--0.2.0.sql
+++ b/age--0.2.0.sql
@@ -1166,6 +1166,13 @@ STABLE
 PARALLEL SAFE
 AS 'MODULE_PATHNAME';
 
+CREATE FUNCTION ag_sqrt(variadic "any")
+RETURNS agtype
+LANGUAGE c
+STABLE
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
 --
 -- function for typecasting an agtype value to another agtype value
 --
diff --git a/regress/expected/expr.out b/regress/expected/expr.out
index 74480cc..d1e0239 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -3996,6 +3996,61 @@ SELECT * from cypher('expr', $$
 $$) as (result agtype);
 ERROR:  exp() unsuppoted argument agtype 1
 --
+-- sqrt()
+--
+SELECT * from cypher('expr', $$
+    RETURN sqrt(25)
+$$) as (result agtype);
+ result 
+--------
+ 5.0
+(1 row)
+
+SELECT * from cypher('expr', $$
+    RETURN sqrt(1)
+$$) as (result agtype);
+ result 
+--------
+ 1.0
+(1 row)
+
+SELECT * from cypher('expr', $$
+    RETURN sqrt(0)
+$$) as (result agtype);
+ result 
+--------
+ 0.0
+(1 row)
+
+-- should return null
+SELECT * from cypher('expr', $$
+    RETURN sqrt(-1)
+$$) as (result agtype);
+ result 
+--------
+ 
+(1 row)
+
+SELECT * from cypher('expr', $$
+    RETURN sqrt(null)
+$$) as (result agtype);
+ result 
+--------
+ 
+(1 row)
+
+-- should fail
+SELECT * from cypher('expr', $$
+    RETURN sqrt()
+$$) as (result agtype);
+ERROR:  invalid number of input parameters for sqrt()
+LINE 1: SELECT * from cypher('expr', $$
+                                      ^
+SELECT * from cypher('expr', $$
+    RETURN sqrt("1")
+$$) as (result agtype);
+ERROR:  sqrt() unsuppoted argument agtype 1
+--
 -- Cleanup
 --
 SELECT * FROM drop_graph('expr', true);
diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql
index 3c85e22..25b3eb3 100644
--- a/regress/sql/expr.sql
+++ b/regress/sql/expr.sql
@@ -1713,6 +1713,33 @@ SELECT * from cypher('expr', $$
 $$) as (result agtype);
 
 --
+-- sqrt()
+--
+SELECT * from cypher('expr', $$
+    RETURN sqrt(25)
+$$) as (result agtype);
+SELECT * from cypher('expr', $$
+    RETURN sqrt(1)
+$$) as (result agtype);
+SELECT * from cypher('expr', $$
+    RETURN sqrt(0)
+$$) as (result agtype);
+-- should return null
+SELECT * from cypher('expr', $$
+    RETURN sqrt(-1)
+$$) as (result agtype);
+SELECT * from cypher('expr', $$
+    RETURN sqrt(null)
+$$) as (result agtype);
+-- should fail
+SELECT * from cypher('expr', $$
+    RETURN sqrt()
+$$) as (result agtype);
+SELECT * from cypher('expr', $$
+    RETURN sqrt("1")
+$$) as (result agtype);
+
+--
 -- Cleanup
 --
 SELECT * FROM drop_graph('expr', true);
diff --git a/src/backend/parser/cypher_expr.c b/src/backend/parser/cypher_expr.c
index 14a5661..c7c0ad4 100644
--- a/src/backend/parser/cypher_expr.c
+++ b/src/backend/parser/cypher_expr.c
@@ -91,6 +91,7 @@
 #define FUNC_LOG10      {"log10",      "ag_log10",   ANYOID, 0, 0, AGTYPEOID, 1, 1, false, false}
 #define FUNC_E          {"e",          "ag_e",       0,      0, 0, AGTYPEOID, 0, 0, false, false}
 #define FUNC_EXP        {"exp",        "ag_exp",     ANYOID, 0, 0, AGTYPEOID, 1, 1, false, false}
+#define FUNC_SQRT       {"sqrt",       "ag_sqrt",    ANYOID, 0, 0, AGTYPEOID, 1, 1, false, false}
 
 /* supported functions */
 #define SUPPORTED_FUNCTIONS {FUNC_TYPE, FUNC_ENDNODE, FUNC_HEAD, FUNC_ID, \
@@ -106,7 +107,7 @@
                              FUNC_RATAN2, FUNC_PI, FUNC_DEGREES, FUNC_RADIANS, \
                              FUNC_ROUND, FUNC_CEIL, FUNC_FLOOR, FUNC_ABS, \
                              FUNC_SIGN, FUNC_RAND, FUNC_LOG, FUNC_LOG10, \
-                             FUNC_E, FUNC_EXP}
+                             FUNC_E, FUNC_EXP, FUNC_SQRT}
 
 /* structure for supported function signatures */
 typedef struct function_signature
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index 4594223..429b977 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -6837,3 +6837,64 @@ Datum ag_exp(PG_FUNCTION_ARGS)
 
     PG_RETURN_POINTER(agtype_value_to_agtype(&agtv_result));
 }
+
+PG_FUNCTION_INFO_V1(ag_sqrt);
+
+Datum ag_sqrt(PG_FUNCTION_ARGS)
+{
+    int nargs;
+    Datum *args;
+    bool *nulls;
+    Oid *types;
+    agtype_value agtv_result;
+    Numeric arg;
+    Numeric zero;
+    Numeric numeric_result;
+    float8 float_result;
+    bool is_null = true;
+    int test;
+
+    /* extract argument values */
+    nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
+
+    /* check number of args */
+    if (nargs != 1)
+        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                        errmsg("sqrt() invalid number of arguments")));
+
+    /* check for a null input */
+    if (nargs < 0 || nulls[0])
+        PG_RETURN_NULL();
+
+    /*
+     * sqrt() supports integer, float, and numeric or the agtype integer,
+     * float, and numeric for the input expression.
+     */
+    arg = get_numeric_compatible_arg(args[0], types[0], "sqrt", &is_null, NULL);
+
+    /* check for a agtype null input */
+    if (is_null)
+        PG_RETURN_NULL();
+
+    /* get a numeric 0 as a datum to test < 0 sqrt args */
+    zero = DatumGetNumeric(DirectFunctionCall1(int8_numeric, Int64GetDatum(0)));
+
+    test = DatumGetInt32(DirectFunctionCall2(numeric_cmp, NumericGetDatum(arg),
+                                             NumericGetDatum(zero)));
+
+    /* return null if the argument is < 0; these are invalid args for sqrt */
+    if (test < 0)
+        PG_RETURN_NULL();
+
+    /* We need the input as a numeric so that we can pass it off to PG */
+    numeric_result = DatumGetNumeric(DirectFunctionCall1(numeric_sqrt,
+                                                         NumericGetDatum(arg)));
+
+    float_result = DatumGetFloat8(DirectFunctionCall1(numeric_float8_no_overflow,
+                                                      NumericGetDatum(numeric_result)));
+    /* build the result */
+    agtv_result.type = AGTV_FLOAT;
+    agtv_result.val.float_value = float_result;
+
+    PG_RETURN_POINTER(agtype_value_to_agtype(&agtv_result));
+}