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;
}