1657 FuncCallContext *funcctx;
1661 uint64_t covcount = 0;
1662 uint64_t covtotal = 0;
1671 if (SRF_IS_FIRSTCALL()) {
1672 MemoryContext oldcontext;
1674 text *tablenametext = NULL;
1675 char *tablename = NULL;
1676 text *colnametext = NULL;
1677 char *colname = NULL;
1678 int32_t bandindex = 1;
1679 bool exclude_nodata_value =
TRUE;
1680 double *search_values = NULL;
1681 uint32_t search_values_count = 0;
1690 bool isNull =
FALSE;
1712 funcctx = SRF_FIRSTCALL_INIT();
1715 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1718 if (PG_ARGISNULL(0)) {
1719 elog(NOTICE,
"Table name must be provided");
1720 MemoryContextSwitchTo(oldcontext);
1721 SRF_RETURN_DONE(funcctx);
1723 tablenametext = PG_GETARG_TEXT_P(0);
1724 tablename = text_to_cstring(tablenametext);
1725 if (!strlen(tablename)) {
1726 elog(NOTICE,
"Table name must be provided");
1727 MemoryContextSwitchTo(oldcontext);
1728 SRF_RETURN_DONE(funcctx);
1733 if (PG_ARGISNULL(1)) {
1734 elog(NOTICE,
"Column name must be provided");
1735 MemoryContextSwitchTo(oldcontext);
1736 SRF_RETURN_DONE(funcctx);
1738 colnametext = PG_GETARG_TEXT_P(1);
1739 colname = text_to_cstring(colnametext);
1740 if (!strlen(colname)) {
1741 elog(NOTICE,
"Column name must be provided");
1742 MemoryContextSwitchTo(oldcontext);
1743 SRF_RETURN_DONE(funcctx);
1748 if (!PG_ARGISNULL(2))
1749 bandindex = PG_GETARG_INT32(2);
1752 if (!PG_ARGISNULL(3))
1753 exclude_nodata_value = PG_GETARG_BOOL(3);
1756 if (!PG_ARGISNULL(4)) {
1757 array = PG_GETARG_ARRAYTYPE_P(4);
1758 etype = ARR_ELEMTYPE(array);
1759 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1766 MemoryContextSwitchTo(oldcontext);
1767 elog(ERROR,
"RASTER_valueCountCoverage: Invalid data type for values");
1768 SRF_RETURN_DONE(funcctx);
1772 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1775 search_values = palloc(
sizeof(
double) * n);
1776 for (i = 0, j = 0; i < (uint32_t) n; i++) {
1777 if (nulls[i])
continue;
1781 search_values[j] = (double) DatumGetFloat4(e[i]);
1784 search_values[j] = (double) DatumGetFloat8(e[i]);
1791 search_values_count = j;
1794 pfree(search_values);
1795 search_values = NULL;
1800 if (!PG_ARGISNULL(5)) {
1801 roundto = PG_GETARG_FLOAT8(5);
1802 if (roundto < 0.) roundto = 0;
1807 spi_result = SPI_connect();
1808 if (spi_result != SPI_OK_CONNECT) {
1810 if (search_values_count) pfree(search_values);
1812 MemoryContextSwitchTo(oldcontext);
1813 elog(ERROR,
"RASTER_valueCountCoverage: Cannot connect to database using SPI");
1814 SRF_RETURN_DONE(funcctx);
1818 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
1819 sql = (
char *) palloc(len);
1822 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1825 if (search_values_count) pfree(search_values);
1827 MemoryContextSwitchTo(oldcontext);
1828 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for sql");
1829 SRF_RETURN_DONE(funcctx);
1833 snprintf(
sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
1835 portal = SPI_cursor_open_with_args(
1845 SPI_cursor_fetch(portal,
TRUE, 1);
1846 while (SPI_processed == 1 && SPI_tuptable != NULL) {
1847 tupdesc = SPI_tuptable->tupdesc;
1848 tuple = SPI_tuptable->vals[0];
1850 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
1851 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1853 SPI_freetuptable(SPI_tuptable);
1854 SPI_cursor_close(portal);
1857 if (NULL != covvcnts) pfree(covvcnts);
1858 if (search_values_count) pfree(search_values);
1860 MemoryContextSwitchTo(oldcontext);
1861 elog(ERROR,
"RASTER_valueCountCoverage: Cannot get raster of coverage");
1862 SRF_RETURN_DONE(funcctx);
1865 SPI_cursor_fetch(portal,
TRUE, 1);
1869 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
1874 SPI_freetuptable(SPI_tuptable);
1875 SPI_cursor_close(portal);
1878 if (NULL != covvcnts) pfree(covvcnts);
1879 if (search_values_count) pfree(search_values);
1881 MemoryContextSwitchTo(oldcontext);
1882 elog(ERROR,
"RASTER_valueCountCoverage: Cannot deserialize raster");
1883 SRF_RETURN_DONE(funcctx);
1888 if (bandindex < 1 || bandindex > num_bands) {
1889 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1893 SPI_freetuptable(SPI_tuptable);
1894 SPI_cursor_close(portal);
1897 if (NULL != covvcnts) pfree(covvcnts);
1898 if (search_values_count) pfree(search_values);
1900 MemoryContextSwitchTo(oldcontext);
1901 SRF_RETURN_DONE(funcctx);
1907 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1911 SPI_freetuptable(SPI_tuptable);
1912 SPI_cursor_close(portal);
1915 if (NULL != covvcnts) pfree(covvcnts);
1916 if (search_values_count) pfree(search_values);
1918 MemoryContextSwitchTo(oldcontext);
1919 SRF_RETURN_DONE(funcctx);
1926 if (NULL == vcnts || !
count) {
1927 elog(NOTICE,
"Cannot count the values for band at index %d", bandindex);
1929 SPI_freetuptable(SPI_tuptable);
1930 SPI_cursor_close(portal);
1933 if (NULL != covvcnts)
free(covvcnts);
1934 if (search_values_count) pfree(search_values);
1936 MemoryContextSwitchTo(oldcontext);
1937 SRF_RETURN_DONE(funcctx);
1942 if (NULL == covvcnts) {
1944 if (NULL == covvcnts) {
1946 SPI_freetuptable(SPI_tuptable);
1947 SPI_cursor_close(portal);
1950 if (search_values_count) pfree(search_values);
1952 MemoryContextSwitchTo(oldcontext);
1953 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for value counts of coverage");
1954 SRF_RETURN_DONE(funcctx);
1957 for (i = 0; i <
count; i++) {
1966 for (i = 0; i <
count; i++) {
1969 for (j = 0; j < covcount; j++) {
1981 covvcnts = SPI_repalloc(covvcnts,
sizeof(
struct rt_valuecount_t) * covcount);
1983 SPI_freetuptable(SPI_tuptable);
1984 SPI_cursor_close(portal);
1987 if (search_values_count) pfree(search_values);
1989 MemoryContextSwitchTo(oldcontext);
1990 elog(ERROR,
"RASTER_valueCountCoverage: Cannot change allocated memory for value counts of coverage");
1991 SRF_RETURN_DONE(funcctx);
1994 covvcnts[covcount - 1].
value = vcnts[i].
value;
1995 covvcnts[covcount - 1].
count = vcnts[i].
count;
1996 covvcnts[covcount - 1].
percent = -1;
2006 SPI_cursor_fetch(portal,
TRUE, 1);
2009 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
2010 SPI_cursor_close(portal);
2013 if (search_values_count) pfree(search_values);
2016 for (i = 0; i < covcount; i++) {
2017 covvcnts[i].
percent = (double) covvcnts[i].
count / covtotal;
2021 funcctx->user_fctx = covvcnts;
2024 funcctx->max_calls = covcount;
2027 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2029 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2031 "function returning record called in context "
2032 "that cannot accept type record"
2037 BlessTupleDesc(tupdesc);
2038 funcctx->tuple_desc = tupdesc;
2040 MemoryContextSwitchTo(oldcontext);
2044 funcctx = SRF_PERCALL_SETUP();
2046 call_cntr = funcctx->call_cntr;
2047 max_calls = funcctx->max_calls;
2048 tupdesc = funcctx->tuple_desc;
2049 covvcnts2 = funcctx->user_fctx;
2052 if (call_cntr < max_calls) {
2062 values[0] = Float8GetDatum(covvcnts2[call_cntr].
value);
2063 values[1] = UInt32GetDatum(covvcnts2[call_cntr].
count);
2064 values[2] = Float8GetDatum(covvcnts2[call_cntr].percent);
2067 tuple = heap_form_tuple(tupdesc, values, nulls);
2070 result = HeapTupleGetDatum(tuple);
2072 SRF_RETURN_NEXT(funcctx,
result);
2077 SRF_RETURN_DONE(funcctx);
char result[OUT_DOUBLE_BUFFER_SIZE]
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
void rt_band_destroy(rt_band band)
Destroy a raster band.
uint16_t rt_raster_get_num_bands(rt_raster raster)
struct rt_valuecount_t * rt_valuecount
rt_valuecount rt_band_get_value_count(rt_band band, int exclude_nodata_value, double *search_values, uint32_t search_values_count, double roundto, uint32_t *rtn_total, uint32_t *rtn_count)
Count the number of times provided value(s) occur in the band.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)