1979 FuncCallContext *funcctx;
1991 if (SRF_IS_FIRSTCALL()) {
1992 MemoryContext oldcontext;
1994 text *tablenametext = NULL;
1995 char *tablename = NULL;
1996 text *colnametext = NULL;
1997 char *colname = NULL;
1998 int32_t bandindex = 1;
1999 bool exclude_nodata_value =
TRUE;
2001 double *quantiles = NULL;
2009 uint64_t cov_count = 0;
2012 SPITupleTable *tuptable = NULL;
2015 bool isNull =
FALSE;
2038 funcctx = SRF_FIRSTCALL_INIT();
2041 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2044 if (PG_ARGISNULL(0)) {
2045 elog(NOTICE,
"Table name must be provided");
2046 MemoryContextSwitchTo(oldcontext);
2047 SRF_RETURN_DONE(funcctx);
2049 tablenametext = PG_GETARG_TEXT_P(0);
2050 tablename = text_to_cstring(tablenametext);
2051 if (!strlen(tablename)) {
2052 elog(NOTICE,
"Table name must be provided");
2053 MemoryContextSwitchTo(oldcontext);
2054 SRF_RETURN_DONE(funcctx);
2059 if (PG_ARGISNULL(1)) {
2060 elog(NOTICE,
"Column name must be provided");
2061 MemoryContextSwitchTo(oldcontext);
2062 SRF_RETURN_DONE(funcctx);
2064 colnametext = PG_GETARG_TEXT_P(1);
2065 colname = text_to_cstring(colnametext);
2066 if (!strlen(colname)) {
2067 elog(NOTICE,
"Column name must be provided");
2068 MemoryContextSwitchTo(oldcontext);
2069 SRF_RETURN_DONE(funcctx);
2074 if (!PG_ARGISNULL(2))
2075 bandindex = PG_GETARG_INT32(2);
2078 if (!PG_ARGISNULL(3))
2079 exclude_nodata_value = PG_GETARG_BOOL(3);
2082 if (!PG_ARGISNULL(4)) {
2083 sample = PG_GETARG_FLOAT8(4);
2084 if (sample < 0 || sample > 1) {
2085 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
2086 MemoryContextSwitchTo(oldcontext);
2087 SRF_RETURN_DONE(funcctx);
2089 else if (
FLT_EQ(sample, 0.0))
2096 if (!PG_ARGISNULL(5)) {
2097 array = PG_GETARG_ARRAYTYPE_P(5);
2098 etype = ARR_ELEMTYPE(array);
2099 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2106 MemoryContextSwitchTo(oldcontext);
2107 elog(ERROR,
"RASTER_quantileCoverage: Invalid data type for quantiles");
2108 SRF_RETURN_DONE(funcctx);
2112 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2115 quantiles = palloc(
sizeof(
double) * n);
2116 for (i = 0, j = 0; i < n; i++) {
2117 if (nulls[i])
continue;
2121 quantile = (double) DatumGetFloat4(e[i]);
2124 quantile = (double) DatumGetFloat8(e[i]);
2128 if (quantile < 0 || quantile > 1) {
2129 elog(NOTICE,
"Invalid value for quantile (must be between 0 and 1). Returning NULL");
2131 MemoryContextSwitchTo(oldcontext);
2132 SRF_RETURN_DONE(funcctx);
2139 quantiles_count = j;
2149 spi_result = SPI_connect();
2150 if (spi_result != SPI_OK_CONNECT) {
2151 MemoryContextSwitchTo(oldcontext);
2152 elog(ERROR,
"RASTER_quantileCoverage: Cannot connect to database using SPI");
2153 SRF_RETURN_DONE(funcctx);
2156 len =
sizeof(char) * (strlen(
"SELECT count FROM _st_summarystats('','',,::boolean,)") + strlen(tablename) + strlen(colname) + (
MAX_INT_CHARLEN * 2) +
MAX_DBL_CHARLEN + 1);
2157 sql = (
char *) palloc(len);
2160 if (SPI_tuptable) SPI_freetuptable(tuptable);
2163 MemoryContextSwitchTo(oldcontext);
2164 elog(ERROR,
"RASTER_quantileCoverage: Cannot allocate memory for sql");
2165 SRF_RETURN_DONE(funcctx);
2169 snprintf(sql, len,
"SELECT count FROM _st_summarystats('%s','%s',%d,%d::boolean,%f)", tablename, colname, bandindex, (exclude_nodata_value ? 1 : 0), sample);
2171 spi_result = SPI_execute(sql,
TRUE, 0);
2173 if (spi_result != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
2175 if (SPI_tuptable) SPI_freetuptable(tuptable);
2178 MemoryContextSwitchTo(oldcontext);
2179 elog(ERROR,
"RASTER_quantileCoverage: Cannot get summary stats of coverage");
2180 SRF_RETURN_DONE(funcctx);
2183 tupdesc = SPI_tuptable->tupdesc;
2184 tuptable = SPI_tuptable;
2185 tuple = tuptable->vals[0];
2187 tmp = SPI_getvalue(tuple, tupdesc, 1);
2188 if (NULL == tmp || !strlen(tmp)) {
2190 if (SPI_tuptable) SPI_freetuptable(tuptable);
2193 MemoryContextSwitchTo(oldcontext);
2194 elog(ERROR,
"RASTER_quantileCoverage: Cannot get summary stats of coverage");
2195 SRF_RETURN_DONE(funcctx);
2197 cov_count = strtol(tmp, NULL, 10);
2203 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
2204 sql = (
char *) palloc(len);
2207 if (SPI_tuptable) SPI_freetuptable(tuptable);
2210 MemoryContextSwitchTo(oldcontext);
2211 elog(ERROR,
"RASTER_quantileCoverage: Cannot allocate memory for sql");
2212 SRF_RETURN_DONE(funcctx);
2216 snprintf(sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
2218 portal = SPI_cursor_open_with_args(
2228 SPI_cursor_fetch(portal,
TRUE, 1);
2229 while (SPI_processed == 1 && SPI_tuptable != NULL) {
2230 if (NULL != covquant) pfree(covquant);
2232 tupdesc = SPI_tuptable->tupdesc;
2233 tuptable = SPI_tuptable;
2234 tuple = tuptable->vals[0];
2236 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
2237 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
2239 if (SPI_tuptable) SPI_freetuptable(tuptable);
2240 SPI_cursor_close(portal);
2243 MemoryContextSwitchTo(oldcontext);
2244 elog(ERROR,
"RASTER_quantileCoverage: Cannot get raster of coverage");
2245 SRF_RETURN_DONE(funcctx);
2248 SPI_cursor_fetch(portal,
TRUE, 1);
2252 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
2257 if (SPI_tuptable) SPI_freetuptable(tuptable);
2258 SPI_cursor_close(portal);
2261 MemoryContextSwitchTo(oldcontext);
2262 elog(ERROR,
"RASTER_quantileCoverage: Cannot deserialize raster");
2263 SRF_RETURN_DONE(funcctx);
2268 if (bandindex < 1 || bandindex > num_bands) {
2269 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2273 if (SPI_tuptable) SPI_freetuptable(tuptable);
2274 SPI_cursor_close(portal);
2277 MemoryContextSwitchTo(oldcontext);
2278 SRF_RETURN_DONE(funcctx);
2284 elog(NOTICE,
"Cannot find raster band of index %d. Returning NULL", bandindex);
2288 if (SPI_tuptable) SPI_freetuptable(tuptable);
2289 SPI_cursor_close(portal);
2292 MemoryContextSwitchTo(oldcontext);
2293 SRF_RETURN_DONE(funcctx);
2298 exclude_nodata_value, sample, cov_count,
2300 quantiles, quantiles_count,
2307 if (NULL == covquant || !count) {
2308 elog(NOTICE,
"Cannot compute quantiles for band at index %d", bandindex);
2310 if (SPI_tuptable) SPI_freetuptable(tuptable);
2311 SPI_cursor_close(portal);
2314 MemoryContextSwitchTo(oldcontext);
2315 SRF_RETURN_DONE(funcctx);
2319 SPI_cursor_fetch(portal,
TRUE, 1);
2322 covquant2 = SPI_palloc(
sizeof(
struct rt_quantile_t) * count);
2323 for (i = 0; i <
count; i++) {
2326 if (covquant2[i].has_value)
2330 if (NULL != covquant) pfree(covquant);
2333 if (SPI_tuptable) SPI_freetuptable(tuptable);
2334 SPI_cursor_close(portal);
2337 if (quantiles_count) pfree(quantiles);
2342 funcctx->user_fctx = covquant2;
2345 funcctx->max_calls =
count;
2348 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2350 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2352 "function returning record called in context " 2353 "that cannot accept type record" 2358 BlessTupleDesc(tupdesc);
2359 funcctx->tuple_desc = tupdesc;
2361 MemoryContextSwitchTo(oldcontext);
2365 funcctx = SRF_PERCALL_SETUP();
2367 call_cntr = funcctx->call_cntr;
2368 max_calls = funcctx->max_calls;
2369 tupdesc = funcctx->tuple_desc;
2370 covquant2 = funcctx->user_fctx;
2373 if (call_cntr < max_calls) {
2383 values[0] = Float8GetDatum(covquant2[call_cntr].quantile);
2384 if (covquant2[call_cntr].has_value)
2385 values[1] = Float8GetDatum(covquant2[call_cntr].
value);
2390 tuple = heap_form_tuple(tupdesc, values, nulls);
2393 result = HeapTupleGetDatum(tuple);
2395 SRF_RETURN_NEXT(funcctx, result);
2401 SRF_RETURN_DONE(funcctx);
int quantile_llist_destroy(struct quantile_llist **list, uint32_t list_count)
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.
rt_quantile rt_band_get_quantiles_stream(rt_band band, int exclude_nodata_value, double sample, uint64_t cov_count, struct quantile_llist **qlls, uint32_t *qlls_count, double *quantiles, int quantiles_count, uint32_t *rtn_count)
Compute the default set of or requested quantiles for a coverage.
#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.
#define POSTGIS_RT_DEBUG(level, msg)
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.