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/age.git
The following commit(s) were added to refs/heads/master by this push:
new eb29e002 Implemented the toBooleanList() function (#1014)
eb29e002 is described below
commit eb29e002d2141a37db9d1c4777e04e1454db3aa4
Author: Matheus Farias de Oliveira Matsumoto
<[email protected]>
AuthorDate: Fri Aug 18 19:38:53 2023 -0300
Implemented the toBooleanList() function (#1014)
- Essentially the same as openCypher's toBooleanList() function:
https://neo4j.com/docs/cypher-manual/current/functions/list/#functions-tobooleanlist
- The toBooleanList() function converts a list of values and returns a list
of boolean values.
- If any values are not convertible to boolean they will be null in the
list returned.
- Also created the regression tests for it.
---
age--1.3.0.sql | 8 ++++
regress/expected/expr.out | 81 +++++++++++++++++++++++++++++++++++++
regress/sql/expr.sql | 48 ++++++++++++++++++++++
src/backend/utils/adt/agtype.c | 92 ++++++++++++++++++++++++++++++++++++++++++
4 files changed, 229 insertions(+)
diff --git a/age--1.3.0.sql b/age--1.3.0.sql
index 90097a7e..3a911627 100644
--- a/age--1.3.0.sql
+++ b/age--1.3.0.sql
@@ -3507,6 +3507,14 @@ RETURNS NULL ON NULL INPUT
PARALLEL SAFE
AS 'MODULE_PATHNAME';
+CREATE FUNCTION ag_catalog.age_tobooleanlist(variadic "any")
+RETURNS agtype
+LANGUAGE c
+IMMUTABLE
+RETURNS NULL ON NULL INPUT
+PARALLEL SAFE
+AS 'MODULE_PATHNAME';
+
CREATE FUNCTION ag_catalog.age_tofloat(variadic "any")
RETURNS agtype
LANGUAGE c
diff --git a/regress/expected/expr.out b/regress/expected/expr.out
index c4c16506..52bf0b6c 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -2827,6 +2827,87 @@ ERROR: function ag_catalog.age_toboolean() does not
exist
LINE 2: RETURN toBoolean()
^
HINT: No function matches the given name and argument types. You might need
to add explicit type casts.
+-- toBooleanList()
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([true, false, true])
+$$) AS (toBooleanList agtype);
+ tobooleanlist
+---------------------
+ [true, false, true]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(["true", "false", "true"])
+$$) AS (toBooleanList agtype);
+ tobooleanlist
+---------------------
+ [true, false, true]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(["True", "False", "True"])
+$$) AS (toBooleanList agtype);
+ tobooleanlist
+---------------------
+ [true, false, true]
+(1 row)
+
+-- should return null
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([])
+$$) AS (toBooleanList agtype);
+ tobooleanlist
+---------------
+
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([null, null, null])
+$$) AS (toBooleanList agtype);
+ tobooleanlist
+--------------------
+ [null, null, null]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(["Hello", "world!"])
+$$) AS (toBooleanList agtype);
+ tobooleanlist
+---------------
+ [null, null]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([["A", "B"], ["C", "D"]])
+$$) AS (toBooleanList agtype);
+ tobooleanlist
+---------------
+ [null, null]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([0,1,2,3,4])
+$$) AS (toBooleanList agtype);
+ tobooleanlist
+--------------------------------
+ [null, null, null, null, null]
+(1 row)
+
+-- should fail
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(fail)
+$$) AS (toBooleanList agtype);
+ERROR: could not find rte for fail
+LINE 2: RETURN toBooleanList(fail)
+ ^
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList("fail")
+$$) AS (toBooleanList agtype);
+ERROR: toBooleanList() argument must resolve to a list or null
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(123)
+$$) AS (toBooleanList agtype);
+ERROR: toBooleanList() argument must resolve to a list or null
-- toFloat()
SELECT * FROM cypher('expr', $$
RETURN toFloat(1)
diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql
index 82421d9d..4788fe25 100644
--- a/regress/sql/expr.sql
+++ b/regress/sql/expr.sql
@@ -1269,6 +1269,54 @@ $$) AS (toBoolean agtype);
SELECT * FROM cypher('expr', $$
RETURN toBoolean()
$$) AS (toBoolean agtype);
+
+-- toBooleanList()
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([true, false, true])
+$$) AS (toBooleanList agtype);
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(["true", "false", "true"])
+$$) AS (toBooleanList agtype);
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(["True", "False", "True"])
+$$) AS (toBooleanList agtype);
+
+-- should return null
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([])
+$$) AS (toBooleanList agtype);
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([null, null, null])
+$$) AS (toBooleanList agtype);
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(["Hello", "world!"])
+$$) AS (toBooleanList agtype);
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([["A", "B"], ["C", "D"]])
+$$) AS (toBooleanList agtype);
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList([0,1,2,3,4])
+$$) AS (toBooleanList agtype);
+
+-- should fail
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(fail)
+$$) AS (toBooleanList agtype);
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList("fail")
+$$) AS (toBooleanList agtype);
+
+SELECT * FROM cypher('expr', $$
+ RETURN toBooleanList(123)
+$$) AS (toBooleanList agtype);
+
-- toFloat()
SELECT * FROM cypher('expr', $$
RETURN toFloat(1)
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index fbfae7bb..70e5f3b9 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -5199,6 +5199,98 @@ Datum age_toboolean(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(agtype_value_to_agtype(&agtv_result));
}
+PG_FUNCTION_INFO_V1(age_tobooleanlist);
+/*
+ * Converts a list of values and returns a list of boolean values.
+ * If any values are not convertible to boolean they will be null in the list
returned.
+ */
+Datum age_tobooleanlist(PG_FUNCTION_ARGS)
+{
+ agtype *agt_arg = NULL;
+ agtype_in_state agis_result;
+ agtype_value *elem;
+ agtype_value bool_elem;
+ char *string = NULL;
+ int count;
+ int i;
+
+ /* 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("toBooleanList() 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 boolean
if possible.
+ elem = get_ith_agtype_value_from_container(&agt_arg->root, i);
+ bool_elem.type = AGTV_BOOL;
+
+ switch (elem->type)
+ {
+ case AGTV_STRING:
+
+ string = elem->val.string.val;
+
+ if (pg_strcasecmp(string, "true") == 0)
+ {
+ bool_elem.val.boolean = true;
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_ELEM, &bool_elem);
+ }
+ else if (pg_strcasecmp(string, "false") == 0)
+ {
+ bool_elem.val.boolean = false;
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_ELEM, &bool_elem);
+ }
+ else
+ {
+ bool_elem.type = AGTV_NULL;
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_ELEM, &bool_elem);
+ }
+
+ break;
+
+ case AGTV_BOOL:
+
+ bool_elem.val.boolean = elem->val.boolean;
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_ELEM, &bool_elem);
+
+ break;
+
+ default:
+
+ bool_elem.type = AGTV_NULL;
+ agis_result.res = push_agtype_value(&agis_result.parse_state,
WAGT_ELEM, &bool_elem);
+
+ break;
+ }
+ }
+
+ /* push the end of the array */
+ 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_tofloat);
Datum age_tofloat(PG_FUNCTION_ARGS)