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)

Reply via email to