int compare_agtype_containers_orderability()

in src/backend/utils/adt/agtype_util.c [260:448]


int compare_agtype_containers_orderability(agtype_container *a,
                                           agtype_container *b)
{
    agtype_iterator *ita;
    agtype_iterator *itb;
    int res = 0;

    ita = agtype_iterator_init(a);
    itb = agtype_iterator_init(b);

    do
    {
        agtype_value va;
        agtype_value vb;
        agtype_iterator_token ra;
        agtype_iterator_token rb;

        ra = agtype_iterator_next(&ita, &va, false);
        rb = agtype_iterator_next(&itb, &vb, false);

        if (ra == rb)
        {
            if (ra == WAGT_DONE)
            {
                /* Decisively equal */

                /* free the agtype_values associated with the tokens */
                pfree_iterator_agtype_value_token(ra, &va);
                pfree_iterator_agtype_value_token(rb, &vb);
                break;
            }

            if (ra == WAGT_END_ARRAY || ra == WAGT_END_OBJECT)
            {
                /*
                 * There is no array or object to compare at this stage of
                 * processing.  AGTV_ARRAY/AGTV_OBJECT values are compared
                 * initially, at the WAGT_BEGIN_ARRAY and WAGT_BEGIN_OBJECT
                 * tokens.
                 */

                /* free the agtype_values associated with the tokens */
                pfree_iterator_agtype_value_token(ra, &va);
                pfree_iterator_agtype_value_token(rb, &vb);
                continue;
            }

            if ((va.type == vb.type) ||
                ((va.type == AGTV_INTEGER || va.type == AGTV_FLOAT ||
                  va.type == AGTV_NUMERIC) &&
                 (vb.type == AGTV_INTEGER || vb.type == AGTV_FLOAT ||
                  vb.type == AGTV_NUMERIC)))
            {
                switch (va.type)
                {
                case AGTV_STRING:
                case AGTV_NULL:
                case AGTV_NUMERIC:
                case AGTV_BOOL:
                case AGTV_INTEGER:
                case AGTV_FLOAT:
                case AGTV_EDGE:
                case AGTV_VERTEX:
                case AGTV_PATH:
                    res = compare_agtype_scalar_values(&va, &vb);
                    break;
                case AGTV_ARRAY:

                    /*
                     * This could be a "raw scalar" pseudo array.  That's
                     * a special case here though, since we still want the
                     * general type-based comparisons to apply, and as far
                     * as we're concerned a pseudo array is just a scalar.
                     */
                    if (va.val.array.raw_scalar != vb.val.array.raw_scalar)
                    {
                        if (va.val.array.raw_scalar)
                        {
                            /* advance iterator ita and get contained type */
                            ra = agtype_iterator_next(&ita, &va, false);
                            res = (get_type_sort_priority(va.type) <
                                   get_type_sort_priority(vb.type)) ?
                                      -1 :
                                      1;
                        }
                        else
                        {
                            /* advance iterator itb and get contained type */
                            rb = agtype_iterator_next(&itb, &vb, false);
                            res = (get_type_sort_priority(va.type) <
                                   get_type_sort_priority(vb.type)) ?
                                      -1 :
                                      1;
                        }
                    }
                    break;
                case AGTV_OBJECT:
                    break;
                case AGTV_BINARY:
                    ereport(ERROR, (errmsg("unexpected AGTV_BINARY value")));
                }
            }
            else
            {
                /* Type-defined order */
                res = (get_type_sort_priority(va.type) <
                       get_type_sort_priority(vb.type)) ?
                          -1 :
                          1;
            }
        }
        else
        {
            /*
             * It's safe to assume that the types differed, and that the va
             * and vb values passed were set.
             *
             * If the two values were of the same container type, then there'd
             * have been a chance to observe the variation in the number of
             * elements/pairs (when processing WAGT_BEGIN_OBJECT, say). They're
             * either two heterogeneously-typed containers, or a container and
             * some scalar type.
             */

            /*
             * Check for the premature array or object end.
             * If left side is shorter, less than.
             */
            if (ra == WAGT_END_ARRAY || ra == WAGT_END_OBJECT)
            {
                res = -1;
                /* free the agtype_values associated with the tokens */
                pfree_iterator_agtype_value_token(ra, &va);
                pfree_iterator_agtype_value_token(rb, &vb);
                break;
            }
            /* If right side is shorter, greater than */
            if (rb == WAGT_END_ARRAY || rb == WAGT_END_OBJECT)
            {
                res = 1;
                /* free the agtype_values associated with the tokens */
                pfree_iterator_agtype_value_token(ra, &va);
                pfree_iterator_agtype_value_token(rb, &vb);
                break;
            }

            /* Correction step because AGTV_ARRAY might be there just because of the container type */
            /* Case 1: left side is assigned to an array, right is an object */
            if(va.type == AGTV_ARRAY && vb.type == AGTV_OBJECT)
            {
                ra = agtype_iterator_next(&ita, &va, false);
            }
            /* Case 2: left side is an object, right side is assigned to an array */
            else if(va.type == AGTV_OBJECT && vb.type == AGTV_ARRAY)
            {
                rb = agtype_iterator_next(&itb, &vb, false);
            }

            Assert(va.type != vb.type);
            Assert(va.type != AGTV_BINARY);
            Assert(vb.type != AGTV_BINARY);
            /* Type-defined order */
            res = (get_type_sort_priority(va.type) <
                   get_type_sort_priority(vb.type)) ?
                      -1 :
                      1;
        }
        /* free the agtype_values associated with the tokens */
        pfree_iterator_agtype_value_token(ra, &va);
        pfree_iterator_agtype_value_token(rb, &vb);
    } while (res == 0);

    while (ita != NULL)
    {
        agtype_iterator *i = ita->parent;

        pfree_if_not_null(ita);
        ita = i;
    }
    while (itb != NULL)
    {
        agtype_iterator *i = itb->parent;

        pfree_if_not_null(itb);
        itb = i;
    }

    return res;
}