* @brief Aggregates two arrays to a scalar. * * @param v1 Array. * @param v2 Array. * @param element_function Transition function. * @param finalize_function Final function. * @returns Whatever finalize_function returns. */
| 1710 | * @returns Whatever finalize_function returns. |
| 1711 | */ |
| 1712 | Datum |
| 1713 | General_2Array_to_Element( |
| 1714 | ArrayType *v1, |
| 1715 | ArrayType *v2, |
| 1716 | Datum(*element_function)(Datum,Oid,Datum,Oid,Datum,Oid), |
| 1717 | Datum(*finalize_function)(Datum,int,Oid)) { |
| 1718 | |
| 1719 | // dimensions |
| 1720 | int ndims1 = ARR_NDIM(v1); |
| 1721 | int ndims2 = ARR_NDIM(v2); |
| 1722 | if (ndims1 != ndims2) { |
| 1723 | ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), |
| 1724 | errmsg("cannot perform operation arrays of different number of dimensions"), |
| 1725 | errdetail("Arrays with %d and %d dimensions are not compatible for this opertation.", |
| 1726 | ndims1, ndims2))); |
| 1727 | } |
| 1728 | if (ndims2 == 0) { |
| 1729 | elog(WARNING, "input are empty arrays."); |
| 1730 | return Float8GetDatum(0); |
| 1731 | } |
| 1732 | int *lbs1 = ARR_LBOUND(v1); |
| 1733 | int *lbs2 = ARR_LBOUND(v2); |
| 1734 | int *dims1 = ARR_DIMS(v1); |
| 1735 | int *dims2 = ARR_DIMS(v2); |
| 1736 | int i = 0; |
| 1737 | for (i = 0; i < ndims1; i++) { |
| 1738 | if (dims1[i] != dims2[i] || lbs1[i] != lbs2[i]) { |
| 1739 | ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), |
| 1740 | errmsg("cannot operate on arrays of different ranges of dimensions"), |
| 1741 | errdetail("Arrays with range [%d,%d] and [%d,%d] for dimension %d are not compatible for operations.", |
| 1742 | lbs1[i], lbs1[i] + dims1[i], lbs2[i], lbs2[i] + dims2[i], i))); |
| 1743 | } |
| 1744 | } |
| 1745 | int nitems = ArrayGetNItems(ndims1, dims1); |
| 1746 | |
| 1747 | // nulls |
| 1748 | if (ARR_HASNULL(v1) || ARR_HASNULL(v2)) { |
| 1749 | ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), |
| 1750 | errmsg("arrays cannot contain nulls"), |
| 1751 | errdetail("Arrays with element value NULL are not allowed."))); |
| 1752 | } |
| 1753 | |
| 1754 | // type |
| 1755 | // the function signature guarantees v1 and v2 are of same type |
| 1756 | Oid element_type = ARR_ELEMTYPE(v1); |
| 1757 | TypeCacheEntry *typentry = lookup_type_cache(element_type,TYPECACHE_CMP_PROC_FINFO); |
| 1758 | int type_size = typentry->typlen; |
| 1759 | bool typbyval = typentry->typbyval; |
| 1760 | char typalign = typentry->typalign; |
| 1761 | |
| 1762 | // iterate |
| 1763 | Datum result = Float8GetDatum(0); |
| 1764 | char *dat1 = ARR_DATA_PTR(v1); |
| 1765 | char *dat2 = ARR_DATA_PTR(v2); |
| 1766 | for (i = 0; i < nitems; ++i) { |
| 1767 | Datum elt1 = fetch_att(dat1, typbyval, type_size); |
| 1768 | dat1 = att_addlength_pointer(dat1, type_size, dat1); |
| 1769 | dat1 = (char *) att_align_nominal(dat1, typalign); |
no outgoing calls
no test coverage detected