2621 FuncCallContext *funcctx;
2625 uint64_t covcount = 0;
2626 uint64_t covtotal = 0;
2635 if (SRF_IS_FIRSTCALL()) {
2636 MemoryContext oldcontext;
2638 text *tablenametext = NULL;
2639 char *tablename = NULL;
2640 text *colnametext = NULL;
2641 char *colname = NULL;
2642 int32_t bandindex = 1;
2643 bool exclude_nodata_value =
TRUE;
2644 double *search_values = NULL;
2652 SPITupleTable *tuptable = NULL;
2655 bool isNull =
FALSE;
2677 funcctx = SRF_FIRSTCALL_INIT();
2680 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2683 if (PG_ARGISNULL(0)) {
2684 elog(NOTICE,
"Table name must be provided");
2685 MemoryContextSwitchTo(oldcontext);
2686 SRF_RETURN_DONE(funcctx);
2688 tablenametext = PG_GETARG_TEXT_P(0);
2689 tablename = text_to_cstring(tablenametext);
2690 if (!strlen(tablename)) {
2691 elog(NOTICE,
"Table name must be provided");
2692 MemoryContextSwitchTo(oldcontext);
2693 SRF_RETURN_DONE(funcctx);
2698 if (PG_ARGISNULL(1)) {
2699 elog(NOTICE,
"Column name must be provided");
2700 MemoryContextSwitchTo(oldcontext);
2701 SRF_RETURN_DONE(funcctx);
2703 colnametext = PG_GETARG_TEXT_P(1);
2704 colname = text_to_cstring(colnametext);
2705 if (!strlen(colname)) {
2706 elog(NOTICE,
"Column name must be provided");
2707 MemoryContextSwitchTo(oldcontext);
2708 SRF_RETURN_DONE(funcctx);
2713 if (!PG_ARGISNULL(2))
2714 bandindex = PG_GETARG_INT32(2);
2717 if (!PG_ARGISNULL(3))
2718 exclude_nodata_value = PG_GETARG_BOOL(3);
2721 if (!PG_ARGISNULL(4)) {
2722 array = PG_GETARG_ARRAYTYPE_P(4);
2723 etype = ARR_ELEMTYPE(array);
2724 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2731 MemoryContextSwitchTo(oldcontext);
2732 elog(ERROR,
"RASTER_valueCountCoverage: Invalid data type for values");
2733 SRF_RETURN_DONE(funcctx);
2737 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2740 search_values = palloc(
sizeof(
double) * n);
2741 for (i = 0, j = 0; i < n; i++) {
2742 if (nulls[i])
continue;
2746 search_values[j] = (double) DatumGetFloat4(e[i]);
2749 search_values[j] = (double) DatumGetFloat8(e[i]);
2756 search_values_count = j;
2759 pfree(search_values);
2760 search_values = NULL;
2765 if (!PG_ARGISNULL(5)) {
2766 roundto = PG_GETARG_FLOAT8(5);
2767 if (roundto < 0.) roundto = 0;
2772 spi_result = SPI_connect();
2773 if (spi_result != SPI_OK_CONNECT) {
2775 if (search_values_count) pfree(search_values);
2777 MemoryContextSwitchTo(oldcontext);
2778 elog(ERROR,
"RASTER_valueCountCoverage: Cannot connect to database using SPI");
2779 SRF_RETURN_DONE(funcctx);
2783 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
2784 sql = (
char *) palloc(len);
2787 if (SPI_tuptable) SPI_freetuptable(tuptable);
2790 if (search_values_count) pfree(search_values);
2792 MemoryContextSwitchTo(oldcontext);
2793 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for sql");
2794 SRF_RETURN_DONE(funcctx);
2798 snprintf(sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
2800 portal = SPI_cursor_open_with_args(
2810 SPI_cursor_fetch(portal,
TRUE, 1);
2811 while (SPI_processed == 1 && SPI_tuptable != NULL) {
2812 tupdesc = SPI_tuptable->tupdesc;
2813 tuptable = SPI_tuptable;
2814 tuple = tuptable->vals[0];
2816 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
2817 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
2819 if (SPI_tuptable) SPI_freetuptable(tuptable);
2820 SPI_cursor_close(portal);
2823 if (NULL != covvcnts) pfree(covvcnts);
2824 if (search_values_count) pfree(search_values);
2826 MemoryContextSwitchTo(oldcontext);
2827 elog(ERROR,
"RASTER_valueCountCoverage: Cannot get raster of coverage");
2828 SRF_RETURN_DONE(funcctx);
2831 SPI_cursor_fetch(portal,
TRUE, 1);
2835 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
2840 if (SPI_tuptable) SPI_freetuptable(tuptable);
2841 SPI_cursor_close(portal);
2844 if (NULL != covvcnts) pfree(covvcnts);
2845 if (search_values_count) pfree(search_values);
2847 MemoryContextSwitchTo(oldcontext);
2848 elog(ERROR,
"RASTER_valueCountCoverage: Cannot deserialize raster");
2849 SRF_RETURN_DONE(funcctx);
2854 if (bandindex < 1 || bandindex > num_bands) {
2855 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2859 if (SPI_tuptable) SPI_freetuptable(tuptable);
2860 SPI_cursor_close(portal);
2863 if (NULL != covvcnts) pfree(covvcnts);
2864 if (search_values_count) pfree(search_values);
2866 MemoryContextSwitchTo(oldcontext);
2867 SRF_RETURN_DONE(funcctx);
2873 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
2877 if (SPI_tuptable) SPI_freetuptable(tuptable);
2878 SPI_cursor_close(portal);
2881 if (NULL != covvcnts) pfree(covvcnts);
2882 if (search_values_count) pfree(search_values);
2884 MemoryContextSwitchTo(oldcontext);
2885 SRF_RETURN_DONE(funcctx);
2889 vcnts =
rt_band_get_value_count(band, (
int) exclude_nodata_value, search_values, search_values_count, roundto, &total, &count);
2892 if (NULL == vcnts || !count) {
2893 elog(NOTICE,
"Cannot count the values for band at index %d", bandindex);
2895 if (SPI_tuptable) SPI_freetuptable(tuptable);
2896 SPI_cursor_close(portal);
2899 if (NULL != covvcnts)
free(covvcnts);
2900 if (search_values_count) pfree(search_values);
2902 MemoryContextSwitchTo(oldcontext);
2903 SRF_RETURN_DONE(funcctx);
2908 if (NULL == covvcnts) {
2910 if (NULL == covvcnts) {
2912 if (SPI_tuptable) SPI_freetuptable(tuptable);
2913 SPI_cursor_close(portal);
2916 if (search_values_count) pfree(search_values);
2918 MemoryContextSwitchTo(oldcontext);
2919 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for value counts of coverage");
2920 SRF_RETURN_DONE(funcctx);
2923 for (i = 0; i <
count; i++) {
2932 for (i = 0; i <
count; i++) {
2935 for (j = 0; j < covcount; j++) {
2947 covvcnts = SPI_repalloc(covvcnts,
sizeof(
struct rt_valuecount_t) * covcount);
2948 if (NULL == covvcnts) {
2950 if (SPI_tuptable) SPI_freetuptable(tuptable);
2951 SPI_cursor_close(portal);
2954 if (search_values_count) pfree(search_values);
2955 if (NULL != covvcnts)
free(covvcnts);
2957 MemoryContextSwitchTo(oldcontext);
2958 elog(ERROR,
"RASTER_valueCountCoverage: Cannot change allocated memory for value counts of coverage");
2959 SRF_RETURN_DONE(funcctx);
2962 covvcnts[covcount - 1].
value = vcnts[i].
value;
2963 covvcnts[covcount - 1].
count = vcnts[i].
count;
2964 covvcnts[covcount - 1].
percent = -1;
2974 SPI_cursor_fetch(portal,
TRUE, 1);
2977 if (SPI_tuptable) SPI_freetuptable(tuptable);
2978 SPI_cursor_close(portal);
2981 if (search_values_count) pfree(search_values);
2984 for (i = 0; i < covcount; i++) {
2985 covvcnts[i].
percent = (double) covvcnts[i].count / covtotal;
2989 funcctx->user_fctx = covvcnts;
2992 funcctx->max_calls = covcount;
2995 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2997 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2999 "function returning record called in context " 3000 "that cannot accept type record" 3005 BlessTupleDesc(tupdesc);
3006 funcctx->tuple_desc = tupdesc;
3008 MemoryContextSwitchTo(oldcontext);
3012 funcctx = SRF_PERCALL_SETUP();
3014 call_cntr = funcctx->call_cntr;
3015 max_calls = funcctx->max_calls;
3016 tupdesc = funcctx->tuple_desc;
3017 covvcnts2 = funcctx->user_fctx;
3020 if (call_cntr < max_calls) {
3030 values[0] = Float8GetDatum(covvcnts2[call_cntr].
value);
3031 values[1] = UInt32GetDatum(covvcnts2[call_cntr].count);
3032 values[2] = Float8GetDatum(covvcnts2[call_cntr].percent);
3035 tuple = heap_form_tuple(tupdesc, values, nulls);
3038 result = HeapTupleGetDatum(tuple);
3040 SRF_RETURN_NEXT(funcctx, result);
3045 SRF_RETURN_DONE(funcctx);
int rt_raster_get_num_bands(rt_raster raster)
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
void rt_band_destroy(rt_band band)
Destroy a raster band.
#define POSTGIS_RT_DEBUGF(level, msg,...)
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a 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.
#define POSTGIS_RT_DEBUG(level, msg)
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.