in src/backend/utils/adt/agtype_ops.c [148:241]
Datum agtype_add(PG_FUNCTION_ARGS)
{
agtype *lhs = AG_GET_ARG_AGTYPE_P(0);
agtype *rhs = AG_GET_ARG_AGTYPE_P(1);
agtype_value *agtv_lhs;
agtype_value *agtv_rhs;
agtype_value agtv_result;
/* If both are not scalars */
if (!(AGT_ROOT_IS_SCALAR(lhs) && AGT_ROOT_IS_SCALAR(rhs)))
{
Datum agt = AGTYPE_P_GET_DATUM(agtype_concat_impl(lhs, rhs));
PG_RETURN_DATUM(agt);
}
/* Both are scalar */
agtv_lhs = get_ith_agtype_value_from_container(&lhs->root, 0);
agtv_rhs = get_ith_agtype_value_from_container(&rhs->root, 0);
/*
* One or both values is a string OR one is a string and the other is
* either an integer, float, or numeric. If so, concatenate them.
*/
if ((agtv_lhs->type == AGTV_STRING || agtv_rhs->type == AGTV_STRING) &&
(agtv_lhs->type == AGTV_INTEGER || agtv_lhs->type == AGTV_FLOAT ||
agtv_lhs->type == AGTV_NUMERIC || agtv_lhs->type == AGTV_STRING ||
agtv_rhs->type == AGTV_INTEGER || agtv_rhs->type == AGTV_FLOAT ||
agtv_rhs->type == AGTV_NUMERIC || agtv_rhs->type == AGTV_STRING))
{
int llen = 0;
char *lhs = get_string_from_agtype_value(agtv_lhs, &llen);
int rlen = 0;
char *rhs = get_string_from_agtype_value(agtv_rhs, &rlen);
concat_to_agtype_string(&agtv_result, lhs, llen, rhs, rlen);
}
/* Both are integers - regular addition */
else if (agtv_lhs->type == AGTV_INTEGER && agtv_rhs->type == AGTV_INTEGER)
{
agtv_result.type = AGTV_INTEGER;
agtv_result.val.int_value = agtv_lhs->val.int_value +
agtv_rhs->val.int_value;
}
/* Both are floats - regular addition */
else if (agtv_lhs->type == AGTV_FLOAT && agtv_rhs->type == AGTV_FLOAT)
{
agtv_result.type = AGTV_FLOAT;
agtv_result.val.float_value = agtv_lhs->val.float_value +
agtv_rhs->val.float_value;
}
/* The left is a float, the right is an integer - regular addition */
else if (agtv_lhs->type == AGTV_FLOAT && agtv_rhs->type == AGTV_INTEGER)
{
agtv_result.type = AGTV_FLOAT;
agtv_result.val.float_value = agtv_lhs->val.float_value +
agtv_rhs->val.int_value;
}
/* The right is a float, the left is an integer - regular addition */
else if (agtv_lhs->type == AGTV_INTEGER && agtv_rhs->type == AGTV_FLOAT)
{
agtv_result.type = AGTV_FLOAT;
agtv_result.val.float_value = agtv_lhs->val.int_value +
agtv_rhs->val.float_value;
}
/* Is this a numeric result */
else if (is_numeric_result(agtv_lhs, agtv_rhs))
{
Datum numd, lhsd, rhsd;
lhsd = get_numeric_datum_from_agtype_value(agtv_lhs);
rhsd = get_numeric_datum_from_agtype_value(agtv_rhs);
numd = DirectFunctionCall2(numeric_add, lhsd, rhsd);
agtv_result.type = AGTV_NUMERIC;
agtv_result.val.numeric = DatumGetNumeric(numd);
}
/* if both operands are scalar(vertex/edge/path), concat the two */
else if (AGT_ROOT_IS_SCALAR(lhs) && AGT_ROOT_IS_SCALAR(rhs))
{
Datum agt = AGTYPE_P_GET_DATUM(agtype_concat_impl(lhs, rhs));
PG_RETURN_DATUM(agt);
}
else
{
/* Not a covered case, error out */
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Invalid input parameter types for agtype_add")));
}
AG_RETURN_AGTYPE_P(agtype_value_to_agtype(&agtv_result));
}