2611 FuncCallContext *funcctx;
2615 uint64_t covcount = 0;
2616 uint64_t covtotal = 0;
2625 if (SRF_IS_FIRSTCALL()) {
2626 MemoryContext oldcontext;
2628 text *tablenametext = NULL;
2629 char *tablename = NULL;
2630 text *colnametext = NULL;
2631 char *colname = NULL;
2632 int32_t bandindex = 1;
2633 bool exclude_nodata_value =
TRUE;
2634 double *search_values = NULL;
2644 bool isNull =
FALSE;
2666 funcctx = SRF_FIRSTCALL_INIT();
2669 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2672 if (PG_ARGISNULL(0)) {
2673 elog(NOTICE,
"Table name must be provided");
2674 MemoryContextSwitchTo(oldcontext);
2675 SRF_RETURN_DONE(funcctx);
2677 tablenametext = PG_GETARG_TEXT_P(0);
2679 if (!strlen(tablename)) {
2680 elog(NOTICE,
"Table name must be provided");
2681 MemoryContextSwitchTo(oldcontext);
2682 SRF_RETURN_DONE(funcctx);
2687 if (PG_ARGISNULL(1)) {
2688 elog(NOTICE,
"Column name must be provided");
2689 MemoryContextSwitchTo(oldcontext);
2690 SRF_RETURN_DONE(funcctx);
2692 colnametext = PG_GETARG_TEXT_P(1);
2694 if (!strlen(colname)) {
2695 elog(NOTICE,
"Column name must be provided");
2696 MemoryContextSwitchTo(oldcontext);
2697 SRF_RETURN_DONE(funcctx);
2702 if (!PG_ARGISNULL(2))
2703 bandindex = PG_GETARG_INT32(2);
2706 if (!PG_ARGISNULL(3))
2707 exclude_nodata_value = PG_GETARG_BOOL(3);
2710 if (!PG_ARGISNULL(4)) {
2711 array = PG_GETARG_ARRAYTYPE_P(4);
2712 etype = ARR_ELEMTYPE(array);
2713 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2720 MemoryContextSwitchTo(oldcontext);
2721 elog(ERROR,
"RASTER_valueCountCoverage: Invalid data type for values");
2722 SRF_RETURN_DONE(funcctx);
2726 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2729 search_values = palloc(
sizeof(
double) * n);
2730 for (i = 0, j = 0; i < (
uint32_t) n; i++) {
2731 if (nulls[i])
continue;
2735 search_values[j] = (double) DatumGetFloat4(e[i]);
2738 search_values[j] = (double) DatumGetFloat8(e[i]);
2745 search_values_count = j;
2748 pfree(search_values);
2749 search_values = NULL;
2754 if (!PG_ARGISNULL(5)) {
2755 roundto = PG_GETARG_FLOAT8(5);
2756 if (roundto < 0.) roundto = 0;
2761 spi_result = SPI_connect();
2762 if (spi_result != SPI_OK_CONNECT) {
2764 if (search_values_count) pfree(search_values);
2766 MemoryContextSwitchTo(oldcontext);
2767 elog(ERROR,
"RASTER_valueCountCoverage: Cannot connect to database using SPI");
2768 SRF_RETURN_DONE(funcctx);
2772 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
2773 sql = (
char *) palloc(len);
2776 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
2779 if (search_values_count) pfree(search_values);
2781 MemoryContextSwitchTo(oldcontext);
2782 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for sql");
2783 SRF_RETURN_DONE(funcctx);
2787 snprintf(
sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
2789 portal = SPI_cursor_open_with_args(
2799 SPI_cursor_fetch(portal,
TRUE, 1);
2800 while (SPI_processed == 1 && SPI_tuptable != NULL) {
2801 tupdesc = SPI_tuptable->tupdesc;
2802 tuple = SPI_tuptable->vals[0];
2804 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
2805 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
2807 SPI_freetuptable(SPI_tuptable);
2808 SPI_cursor_close(portal);
2811 if (NULL != covvcnts) pfree(covvcnts);
2812 if (search_values_count) pfree(search_values);
2814 MemoryContextSwitchTo(oldcontext);
2815 elog(ERROR,
"RASTER_valueCountCoverage: Cannot get raster of coverage");
2816 SRF_RETURN_DONE(funcctx);
2819 SPI_cursor_fetch(portal,
TRUE, 1);
2823 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
2828 SPI_freetuptable(SPI_tuptable);
2829 SPI_cursor_close(portal);
2832 if (NULL != covvcnts) pfree(covvcnts);
2833 if (search_values_count) pfree(search_values);
2835 MemoryContextSwitchTo(oldcontext);
2836 elog(ERROR,
"RASTER_valueCountCoverage: Cannot deserialize raster");
2837 SRF_RETURN_DONE(funcctx);
2842 if (bandindex < 1 || bandindex > num_bands) {
2843 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2847 SPI_freetuptable(SPI_tuptable);
2848 SPI_cursor_close(portal);
2851 if (NULL != covvcnts) pfree(covvcnts);
2852 if (search_values_count) pfree(search_values);
2854 MemoryContextSwitchTo(oldcontext);
2855 SRF_RETURN_DONE(funcctx);
2861 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
2865 SPI_freetuptable(SPI_tuptable);
2866 SPI_cursor_close(portal);
2869 if (NULL != covvcnts) pfree(covvcnts);
2870 if (search_values_count) pfree(search_values);
2872 MemoryContextSwitchTo(oldcontext);
2873 SRF_RETURN_DONE(funcctx);
2880 if (NULL == vcnts || !
count) {
2881 elog(NOTICE,
"Cannot count the values for band at index %d", bandindex);
2883 SPI_freetuptable(SPI_tuptable);
2884 SPI_cursor_close(portal);
2887 if (NULL != covvcnts)
free(covvcnts);
2888 if (search_values_count) pfree(search_values);
2890 MemoryContextSwitchTo(oldcontext);
2891 SRF_RETURN_DONE(funcctx);
2896 if (NULL == covvcnts) {
2898 if (NULL == covvcnts) {
2900 SPI_freetuptable(SPI_tuptable);
2901 SPI_cursor_close(portal);
2904 if (search_values_count) pfree(search_values);
2906 MemoryContextSwitchTo(oldcontext);
2907 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for value counts of coverage");
2908 SRF_RETURN_DONE(funcctx);
2911 for (i = 0; i <
count; i++) {
2920 for (i = 0; i <
count; i++) {
2923 for (j = 0; j < covcount; j++) {
2935 covvcnts = SPI_repalloc(covvcnts,
sizeof(
struct rt_valuecount_t) * covcount);
2937 SPI_freetuptable(SPI_tuptable);
2938 SPI_cursor_close(portal);
2941 if (search_values_count) pfree(search_values);
2943 MemoryContextSwitchTo(oldcontext);
2944 elog(ERROR,
"RASTER_valueCountCoverage: Cannot change allocated memory for value counts of coverage");
2945 SRF_RETURN_DONE(funcctx);
2948 covvcnts[covcount - 1].
value = vcnts[i].
value;
2949 covvcnts[covcount - 1].
count = vcnts[i].
count;
2950 covvcnts[covcount - 1].
percent = -1;
2960 SPI_cursor_fetch(portal,
TRUE, 1);
2963 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
2964 SPI_cursor_close(portal);
2967 if (search_values_count) pfree(search_values);
2970 for (i = 0; i < covcount; i++) {
2971 covvcnts[i].
percent = (double) covvcnts[i].
count / covtotal;
2975 funcctx->user_fctx = covvcnts;
2978 funcctx->max_calls = covcount;
2981 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2983 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2985 "function returning record called in context "
2986 "that cannot accept type record"
2991 BlessTupleDesc(tupdesc);
2992 funcctx->tuple_desc = tupdesc;
2994 MemoryContextSwitchTo(oldcontext);
2998 funcctx = SRF_PERCALL_SETUP();
3000 call_cntr = funcctx->call_cntr;
3001 max_calls = funcctx->max_calls;
3002 tupdesc = funcctx->tuple_desc;
3003 covvcnts2 = funcctx->user_fctx;
3006 if (call_cntr < max_calls) {
3016 values[0] = Float8GetDatum(covvcnts2[call_cntr].
value);
3017 values[1] = UInt32GetDatum(covvcnts2[call_cntr].
count);
3018 values[2] = Float8GetDatum(covvcnts2[call_cntr].percent);
3021 tuple = heap_form_tuple(tupdesc, values, nulls);
3024 result = HeapTupleGetDatum(tuple);
3026 SRF_RETURN_NEXT(funcctx, result);
3031 SRF_RETURN_DONE(funcctx);
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): ...
char * text_to_cstring(const text *textptr)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)