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

joshinnis 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 6b89697  Add to age_reverse function so that it can reverse an agtype 
list (#146)
6b89697 is described below

commit 6b89697351aab8806136503d9806026b3cb927db
Author: Quoc Viet Vuong <[email protected]>
AuthorDate: Wed Dec 1 03:27:30 2021 +0700

    Add to age_reverse function so that it can reverse an agtype list (#146)
---
 regress/expected/expr.out      | 85 +++++++++++++++++++++++++++++++++++++++
 regress/sql/expr.sql           | 34 ++++++++++++++++
 src/backend/utils/adt/agtype.c | 90 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 205 insertions(+), 4 deletions(-)

diff --git a/regress/expected/expr.out b/regress/expected/expr.out
index b90d4eb..e24367f 100644
--- a/regress/expected/expr.out
+++ b/regress/expected/expr.out
@@ -2597,6 +2597,91 @@ SELECT * FROM age_reverse(null);
  
 (1 row)
 
+-- should return error
+SELECT * FROM age_reverse([4923, 'abc', 521, NULL, 487]);
+ERROR:  syntax error at or near "["
+LINE 1: SELECT * FROM age_reverse([4923, 'abc', 521, NULL, 487]);
+                                  ^
+-- Should return the reversed list
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 'abc', 521, NULL, 487])
+$$) AS (u agtype);
+               u               
+-------------------------------
+ [487, null, 521, "abc", 4923]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923])
+$$) AS (u agtype);
+   u    
+--------
+ [4923]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257])
+$$) as (u agtype);
+      u      
+-------------
+ [257, 4923]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257, null])
+$$) as (u agtype);
+         u         
+-------------------
+ [null, 257, 4923]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257, 'tea'])
+$$) as (u agtype);
+         u          
+--------------------
+ ["tea", 257, 4923]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([[1, 4, 7], 4923, [1, 2, 3], 'abc', 521, NULL, 487, ['fgt', 
7, 10]])
+$$) as (u agtype);
+                                  u                                  
+---------------------------------------------------------------------
+ [["fgt", 7, 10], 487, null, 521, "abc", [1, 2, 3], 4923, [1, 4, 7]]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257, {test1: "key"}])
+$$) as (u agtype);
+               u               
+-------------------------------
+ [{"test1": "key"}, 257, 4923]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257, {test2: [1, 2, 3]}])
+$$) as (u agtype);
+                 u                 
+-----------------------------------
+ [{"test2": [1, 2, 3]}, 257, 4923]
+(1 row)
+
+SELECT * FROM cypher('expr', $$
+    CREATE ({test: [1, 2, 3]})
+$$) as (u agtype);
+ u 
+---
+(0 rows)
+
+SELECT * FROM cypher('expr', $$
+    MATCH (v) WHERE exists(v.test) RETURN reverse(v.test)
+$$) as (u agtype);
+     u     
+-----------
+ [3, 2, 1]
+(1 row)
+
 -- should fail
 SELECT * FROM cypher('expr', $$
     RETURN reverse(true)
diff --git a/regress/sql/expr.sql b/regress/sql/expr.sql
index f2f5b8e..49df516 100644
--- a/regress/sql/expr.sql
+++ b/regress/sql/expr.sql
@@ -1160,6 +1160,40 @@ SELECT * FROM cypher('expr', $$
     RETURN reverse(null)
 $$) AS (results agtype);
 SELECT * FROM age_reverse(null);
+-- should return error
+SELECT * FROM age_reverse([4923, 'abc', 521, NULL, 487]);
+-- Should return the reversed list
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 'abc', 521, NULL, 487])
+$$) AS (u agtype);
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923])
+$$) AS (u agtype);
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257])
+$$) as (u agtype);
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257, null])
+$$) as (u agtype);
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257, 'tea'])
+$$) as (u agtype);
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([[1, 4, 7], 4923, [1, 2, 3], 'abc', 521, NULL, 487, ['fgt', 
7, 10]])
+$$) as (u agtype);
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257, {test1: "key"}])
+$$) as (u agtype);
+SELECT * FROM cypher('expr', $$
+    RETURN reverse([4923, 257, {test2: [1, 2, 3]}])
+$$) as (u agtype);
+SELECT * FROM cypher('expr', $$
+    CREATE ({test: [1, 2, 3]})
+$$) as (u agtype);
+SELECT * FROM cypher('expr', $$
+    MATCH (v) WHERE exists(v.test) RETURN reverse(v.test)
+$$) as (u agtype);
+
 -- should fail
 SELECT * FROM cypher('expr', $$
     RETURN reverse(true)
diff --git a/src/backend/utils/adt/agtype.c b/src/backend/utils/adt/agtype.c
index 329cd34..4e33456 100644
--- a/src/backend/utils/adt/agtype.c
+++ b/src/backend/utils/adt/agtype.c
@@ -159,6 +159,9 @@ static int64 get_int64_from_int_datums(Datum d, Oid type, 
char *funcname,
 static agtype_iterator *get_next_object_key(agtype_iterator *it,
                                              agtype_container *agtc,
                                              agtype_value *key);
+static agtype_iterator *get_next_list_element(agtype_iterator *it,
+                                             agtype_container *agtc,
+                                             agtype_value *elem);
 
 PG_FUNCTION_INFO_V1(agtype_in);
 
@@ -4860,6 +4863,50 @@ Datum age_tostring(PG_FUNCTION_ARGS)
     PG_RETURN_POINTER(agtype_value_to_agtype(&agtv_result));
 }
 
+static agtype_iterator *get_next_list_element(agtype_iterator *it,
+                           agtype_container *agtc, agtype_value *elem)
+{
+    agtype_iterator_token itok;
+    agtype_value tmp;
+
+    /* verify input params */
+    Assert(agtc != NULL);
+    Assert(elem != NULL);
+
+    /* check to see if the container is empty */
+    if (AGTYPE_CONTAINER_SIZE(agtc) == 0)
+    {
+       return NULL;
+    }
+
+    /* if the passed iterator is NULL, this is the first time, create it */
+    if (it == NULL)
+    {
+        /* initial the iterator */
+        it = agtype_iterator_init(agtc);
+        /* get the first token */
+        itok = agtype_iterator_next(&it, &tmp, true);
+        /* it should be WAGT_BEGIN_ARRAY */
+        Assert(itok == WAGT_BEGIN_ARRAY);
+    }
+
+    /* the next token should be an element or the end of the array */
+    itok = agtype_iterator_next(&it, &tmp, true);
+    Assert(itok == WAGT_ELEM || WAGT_END_ARRAY);
+
+    /* if this is the end of the array return NULL */
+    if (itok == WAGT_END_ARRAY) {
+        return NULL;
+    }
+
+    /* this should be the element, copy it */
+    if (itok == WAGT_ELEM) {
+        memcpy(elem, &tmp, sizeof(agtype_value));
+    }
+
+    return it;
+}
+
 PG_FUNCTION_INFO_V1(age_reverse);
 
 Datum age_reverse(PG_FUNCTION_ARGS)
@@ -4904,15 +4951,50 @@ Datum age_reverse(PG_FUNCTION_ARGS)
     }
     else
     {
-        agtype *agt_arg;
-        agtype_value *agtv_value;
+        agtype *agt_arg = NULL;
+        agtype_value *agtv_value = NULL;
+        agtype_parse_state *parse_state = NULL;
+        agtype_value elem = {0};
+        agtype_iterator *it = NULL;
+        agtype_value tmp;
+        agtype_value *elems = NULL;
+        int num_elems;
+        int i;
 
         /* get the agtype argument */
         agt_arg = DATUM_GET_AGTYPE_P(arg);
 
         if (!AGT_ROOT_IS_SCALAR(agt_arg))
-            ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
-                            errmsg("reverse() only supports scalar 
arguments")));
+        {
+            agtv_value = push_agtype_value(&parse_state, WAGT_BEGIN_ARRAY, 
NULL);
+
+            while ((it = get_next_list_element(it, &agt_arg->root, &elem)))
+            {
+                agtv_value = push_agtype_value(&parse_state, WAGT_ELEM, &elem);
+            }
+
+            /* now reverse the list */
+            elems = parse_state->cont_val.val.array.elems;
+            num_elems = parse_state->cont_val.val.array.num_elems;
+
+            for(i = 0; i < num_elems/2; i++)
+            {
+                tmp = elems[i];
+                elems[i] = elems[num_elems - 1 - i];
+                elems[num_elems - 1 - i] = tmp;
+            }
+            /* reverse done*/
+
+            elems = NULL;
+
+            agtv_value = push_agtype_value(&parse_state, WAGT_END_ARRAY, NULL);
+
+            Assert(agtv_value != NULL);
+            Assert(agtv_value->type = AGTV_ARRAY);
+
+            PG_RETURN_POINTER(agtype_value_to_agtype(agtv_value));
+
+        }
 
         agtv_value = get_ith_agtype_value_from_container(&agt_arg->root, 0);
 

Reply via email to