This is an automated email from the ASF dual-hosted git repository.
dehowef pushed a commit to branch PG11
in repository https://gitbox.apache.org/repos/asf/age.git
The following commit(s) were added to refs/heads/PG11 by this push:
new 091e6afa added toFloatList() function (#1060)
091e6afa is described below
commit 091e6afa653f87c9022ad7bd8951410fcbbb9cb0
Author: Marcos Silva <[email protected]>
AuthorDate: Thu Jul 20 19:23:44 2023 -0300
added toFloatList() function (#1060)
- Basically the same function of OpenCypher toFloatList()
https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-tofloatlist
- toFloatList() converts a list of values and returns a list of floating
point values. If any values are not convertible to floating point they will be
null in the list returned.
- Returns a list containing the converted elements; depending on the input
value a converted value is either a floating point value or null.
---
age--1.3.0.sql | 8 ++++
regress/expected/expr.out | 73 +++++++++++++++++++++++++++++++++
regress/sql/expr.sql | 33 +++++++++++++++
src/backend/utils/adt/agtype.c | 93 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 207 insertions(+)
diff --git a/age--1.3.0.sql b/age--1.3.0.sql
index 1294ccbe..c68d5815 100644
--- a/age--1.3.0.sql
+++ b/age--1.3.0.sql
@@ -3511,6 +3511,14 @@ RETURNS NULL ON NULL INPUT
PARALLEL SAFE
AS 'MODULE_PATHNAME';
+CREATE FUNCTION ag_catalog.age_tofloatlist(variadic "any")
+RETURNS agtype
+LANGUAGE c
+IMMUTABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
CREATE FUNCTION ag_catalog.age_tointeger(variadic "any")
RETURNS agtype
LANGUAGE c
diff --git a/regress/expected/expr.out b/regress/expected/expr.out
index 98133f4c..c29dd6ce 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -2888,6 +2888,79 @@ ERROR: function ag_catalog.age_tofloat() does not exist
LINE 2: RETURN toFloat()
^
HINT: No function matches the given name and argument types. You might need
to add explicit type casts.
+-- toFloatList()
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([1.3])
+$$) AS (toFloatList agtype);
+ tofloatlist
+-------------
+ [1.3]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([1.2, '4.654'])
+$$) AS (toFloatList agtype);
+ tofloatlist
+--------------
+ [1.2, 4.654]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList(['1.9432', 8.6222, '9.4111212', 344.22])
+$$) AS (toFloatList agtype);
+ tofloatlist
+-----------------------------------------
+ [1.9432, 8.6222, 9.4111212, 344.220001]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList(['999.2'])
+$$) AS (toFloatList agtype);
+ tofloatlist
+-------------
+ [999.2]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([1.20002])
+$$) AS (toFloatList agtype);
+ tofloatlist
+-------------
+ [1.20002]
+(1 row)
+
+-- should return null
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList(['true'])
+$$) AS (toFloatList agtype);
+ tofloatlist
+-------------
+ [null]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([null])
+$$) AS (toFloatList agtype);
+ tofloatlist
+-------------
+ [null]
+(1 row)
+
+-- should fail
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([failed])
+$$) AS (toFloatList agtype);
+ERROR: could not find rte for failed
+LINE 2: RETURN toFloatList([failed])
+ ^
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList("failed")
+$$) AS (toFloatList agtype);
+ERROR: toFloatList() argument must resolve to a list or null
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList(555)
+$$) AS (toFloatList agtype);
+ERROR: toFloatList() argument must resolve to a list or null
-- toInteger()
SELECT * FROM cypher('expr', $$
RETURN toInteger(1)
diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql
index d67e4b91..7b6aef64 100644
--- a/regress/sql/expr.sql
+++ b/regress/sql/expr.sql
@@ -1298,6 +1298,39 @@ $$) AS (toFloat agtype);
SELECT * FROM cypher('expr', $$
RETURN toFloat()
$$) AS (toFloat agtype);
+-- toFloatList()
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([1.3])
+$$) AS (toFloatList agtype);
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([1.2, '4.654'])
+$$) AS (toFloatList agtype);
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList(['1.9432', 8.6222, '9.4111212', 344.22])
+$$) AS (toFloatList agtype);
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList(['999.2'])
+$$) AS (toFloatList agtype);
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([1.20002])
+$$) AS (toFloatList agtype);
+-- should return null
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList(['true'])
+$$) AS (toFloatList agtype);
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([null])
+$$) AS (toFloatList agtype);
+-- should fail
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList([failed])
+$$) AS (toFloatList agtype);
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList("failed")
+$$) AS (toFloatList agtype);
+SELECT * FROM cypher('expr', $$
+ RETURN toFloatList(555)
+$$) AS (toFloatList agtype);
-- toInteger()
SELECT * FROM cypher('expr', $$
RETURN toInteger(1)
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index b53840d3..f7a54708 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -5302,6 +5302,99 @@ Datum age_tofloat(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(agtype_value_to_agtype(&agtv_result));
}
+PG_FUNCTION_INFO_V1(age_tofloatlist);
+/*
+ * toFloatList() converts a list of values and returns a list of floating
point values.
+ * If any values are not convertible to floating point they will be null in
the list returned.
+ */
+Datum age_tofloatlist(PG_FUNCTION_ARGS)
+{
+ agtype *agt_arg = NULL;
+ agtype_in_state agis_result;
+ agtype_value *elem;
+ agtype_value float_elem;
+ char *string = NULL;
+ int count;
+ int i;
+ bool is_valid = false;
+ float float_num;
+ char buffer[64];
+
+ /* check for null */
+ if (PG_ARGISNULL(0))
+ {
+ PG_RETURN_NULL();
+ }
+ agt_arg = AG_GET_ARG_AGTYPE_P(0);
+ /* check for an array */
+ if (!AGT_ROOT_IS_ARRAY(agt_arg) || AGT_ROOT_IS_SCALAR(agt_arg))
+ ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("toFloatList() argument must resolve to a list
or null")));
+
+ count = AGT_ROOT_COUNT(agt_arg);
+
+ /* if we have an empty list or only one element in the list, return null */
+ if (count == 0)
+ PG_RETURN_NULL();
+
+ /* clear the result structure */
+ MemSet(&agis_result, 0, sizeof(agtype_in_state));
+
+ /* push the beginning of the array */
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
+ WAGT_BEGIN_ARRAY, NULL);
+
+ /* iterate through the list */
+ for (i = 0; i < count; i++)
+ {
+ // TODO: check element's type, it's value, and convert it to float if
possible.
+ elem = get_ith_agtype_value_from_container(&agt_arg->root, i);
+ float_elem.type = AGTV_FLOAT;
+
+ switch (elem->type)
+ {
+ case AGTV_STRING:
+
+ string = elem->val.string.val;
+ if (atof(string))
+ {
+ float_elem.type = AGTV_FLOAT;
+ float_elem.val.float_value = float8in_internal_null(string,
NULL, "double precision",
+ string, &is_valid);
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_ELEM, &float_elem);
+ }
+ else
+ {
+ float_elem.type = AGTV_NULL;
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_ELEM, &float_elem);
+ }
+
+ break;
+
+ case AGTV_FLOAT:
+
+ float_elem.type = AGTV_FLOAT;
+ float_num = elem->val.float_value;
+ sprintf(buffer, "%f", float_num);
+ string = buffer;
+ float_elem.val.float_value = float8in_internal_null(string, NULL,
"double precision", string, &is_valid);
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_ELEM, &float_elem);
+
+ break;
+
+ default:
+
+ float_elem.type = AGTV_NULL;
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_ELEM, &float_elem);
+
+ break;
+ }
+ }
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_END_ARRAY, NULL);
+
+ PG_RETURN_POINTER(agtype_value_to_agtype(agis_result.res));
+}
+
PG_FUNCTION_INFO_V1(age_tointeger);
Datum age_tointeger(PG_FUNCTION_ARGS)