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/21 22:47:12 UTC
[incubator-age] branch master updated: Add openCypher function exp()
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 49b5ec8 Add openCypher function exp()
49b5ec8 is described below
commit 49b5ec8a63e22e6ce5109d080ebe0bb21928ef03
Author: John Gemignani <jr...@gmail.com>
AuthorDate: Mon Sep 21 13:33:38 2020 -0700
Add openCypher function exp()
Added the openCypher function exp() aka e^x.
Added regression tests
---
age--0.2.0.sql | 7 ++++++
regress/expected/expr.out | 39 ++++++++++++++++++++++++++++++++
regress/sql/expr.sql | 21 +++++++++++++++++
src/backend/parser/cypher_expr.c | 3 ++-
src/backend/utils/adt/agtype.c | 49 ++++++++++++++++++++++++++++++++++++++++
5 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/age--0.2.0.sql b/age--0.2.0.sql
index f9144e7..aa5bf5a 100644
--- a/age--0.2.0.sql
+++ b/age--0.2.0.sql
@@ -1159,6 +1159,13 @@ STABLE
PARALLEL SAFE
AS 'MODULE_PATHNAME';
+CREATE FUNCTION ag_exp(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 e982c31..74480cc 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -3957,6 +3957,45 @@ $$) as (result agtype);
(1 row)
--
+-- exp() aka e^x
+--
+SELECT * from cypher('expr', $$
+ RETURN exp(1)
+$$) as (result agtype);
+ result
+------------------
+ 2.71828182845905
+(1 row)
+
+SELECT * from cypher('expr', $$
+ RETURN exp(0)
+$$) as (result agtype);
+ result
+--------
+ 1.0
+(1 row)
+
+-- should return null
+SELECT * from cypher('expr', $$
+ RETURN exp(null)
+$$) as (result agtype);
+ result
+--------
+
+(1 row)
+
+-- should fail
+SELECT * from cypher('expr', $$
+ RETURN exp()
+$$) as (result agtype);
+ERROR: invalid number of input parameters for exp()
+LINE 1: SELECT * from cypher('expr', $$
+ ^
+SELECT * from cypher('expr', $$
+ RETURN exp("1")
+$$) as (result agtype);
+ERROR: exp() unsuppoted argument agtype 1
+--
-- Cleanup
--
SELECT * FROM drop_graph('expr', true);
diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql
index fa13865..3c85e22 100644
--- a/regress/sql/expr.sql
+++ b/regress/sql/expr.sql
@@ -1692,6 +1692,27 @@ SELECT * from cypher('expr', $$
$$) as (result agtype);
--
+-- exp() aka e^x
+--
+SELECT * from cypher('expr', $$
+ RETURN exp(1)
+$$) as (result agtype);
+SELECT * from cypher('expr', $$
+ RETURN exp(0)
+$$) as (result agtype);
+-- should return null
+SELECT * from cypher('expr', $$
+ RETURN exp(null)
+$$) as (result agtype);
+-- should fail
+SELECT * from cypher('expr', $$
+ RETURN exp()
+$$) as (result agtype);
+SELECT * from cypher('expr', $$
+ RETURN exp("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 e7c2579..14a5661 100644
--- a/src/backend/parser/cypher_expr.c
+++ b/src/backend/parser/cypher_expr.c
@@ -90,6 +90,7 @@
#define FUNC_LOG {"log", "ag_log", ANYOID, 0, 0, AGTYPEOID, 1, 1, false, false}
#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}
/* supported functions */
#define SUPPORTED_FUNCTIONS {FUNC_TYPE, FUNC_ENDNODE, FUNC_HEAD, FUNC_ID, \
@@ -105,7 +106,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_E, FUNC_EXP}
/* 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 e168c1e..4594223 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -6788,3 +6788,52 @@ Datum ag_e(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(agtype_value_to_agtype(&agtv_result));
}
+
+PG_FUNCTION_INFO_V1(ag_exp);
+
+Datum ag_exp(PG_FUNCTION_ARGS)
+{
+ int nargs;
+ Datum *args;
+ bool *nulls;
+ Oid *types;
+ agtype_value agtv_result;
+ Numeric arg;
+ Numeric numeric_result;
+ float8 float_result;
+ bool is_null = true;
+
+ /* 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("exp() invalid number of arguments")));
+
+ /* check for a null input */
+ if (nargs < 0 || nulls[0])
+ PG_RETURN_NULL();
+
+ /*
+ * exp() 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], "exp", &is_null, NULL);
+
+ /* check for a agtype null input */
+ if (is_null)
+ PG_RETURN_NULL();
+
+ /* We need the input as a numeric so that we can pass it off to PG */
+ numeric_result = DatumGetNumeric(DirectFunctionCall1(numeric_exp,
+ 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));
+}