1975 FuncCallContext *funcctx;
1987 if (SRF_IS_FIRSTCALL()) {
1988 MemoryContext oldcontext;
1990 text *tablenametext = NULL;
1991 char *tablename = NULL;
1992 text *colnametext = NULL;
1993 char *colname = NULL;
1994 int32_t bandindex = 1;
1995 bool exclude_nodata_value =
TRUE;
1997 double *quantiles = NULL;
1998 uint32_t quantiles_count = 0;
1999 double quantile = 0;
2005 uint64_t cov_count = 0;
2008 SPITupleTable *tuptable = NULL;
2011 bool isNull =
FALSE;
2018 uint32_t qlls_count;
2034 funcctx = SRF_FIRSTCALL_INIT();
2037 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2040 if (PG_ARGISNULL(0)) {
2041 elog(NOTICE,
"Table name must be provided");
2042 MemoryContextSwitchTo(oldcontext);
2043 SRF_RETURN_DONE(funcctx);
2045 tablenametext = PG_GETARG_TEXT_P(0);
2047 if (!strlen(tablename)) {
2048 elog(NOTICE,
"Table name must be provided");
2049 MemoryContextSwitchTo(oldcontext);
2050 SRF_RETURN_DONE(funcctx);
2055 if (PG_ARGISNULL(1)) {
2056 elog(NOTICE,
"Column name must be provided");
2057 MemoryContextSwitchTo(oldcontext);
2058 SRF_RETURN_DONE(funcctx);
2060 colnametext = PG_GETARG_TEXT_P(1);
2062 if (!strlen(colname)) {
2063 elog(NOTICE,
"Column name must be provided");
2064 MemoryContextSwitchTo(oldcontext);
2065 SRF_RETURN_DONE(funcctx);
2070 if (!PG_ARGISNULL(2))
2071 bandindex = PG_GETARG_INT32(2);
2074 if (!PG_ARGISNULL(3))
2075 exclude_nodata_value = PG_GETARG_BOOL(3);
2078 if (!PG_ARGISNULL(4)) {
2079 sample = PG_GETARG_FLOAT8(4);
2080 if (sample < 0 || sample > 1) {
2081 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
2082 MemoryContextSwitchTo(oldcontext);
2083 SRF_RETURN_DONE(funcctx);
2085 else if (
FLT_EQ(sample, 0.0))
2092 if (!PG_ARGISNULL(5)) {
2093 array = PG_GETARG_ARRAYTYPE_P(5);
2094 etype = ARR_ELEMTYPE(array);
2095 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2102 MemoryContextSwitchTo(oldcontext);
2103 elog(ERROR,
"RASTER_quantileCoverage: Invalid data type for quantiles");
2104 SRF_RETURN_DONE(funcctx);
2108 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2111 quantiles = palloc(
sizeof(
double) * n);
2112 for (i = 0, j = 0; i < (uint32_t) n; i++) {
2113 if (nulls[i])
continue;
2117 quantile = (double) DatumGetFloat4(e[i]);
2120 quantile = (double) DatumGetFloat8(e[i]);
2124 if (quantile < 0 || quantile > 1) {
2125 elog(NOTICE,
"Invalid value for quantile (must be between 0 and 1). Returning NULL");
2127 MemoryContextSwitchTo(oldcontext);
2128 SRF_RETURN_DONE(funcctx);
2135 quantiles_count = j;
2145 spi_result = SPI_connect();
2146 if (spi_result != SPI_OK_CONNECT) {
2147 MemoryContextSwitchTo(oldcontext);
2148 elog(ERROR,
"RASTER_quantileCoverage: Cannot connect to database using SPI");
2149 SRF_RETURN_DONE(funcctx);
2152 len =
sizeof(char) * (strlen(
"SELECT count FROM _st_summarystats('','',,::boolean,)") + strlen(tablename) + strlen(colname) + (
MAX_INT_CHARLEN * 2) +
MAX_DBL_CHARLEN + 1);
2153 sql = (
char *) palloc(len);
2156 if (SPI_tuptable) SPI_freetuptable(tuptable);
2159 MemoryContextSwitchTo(oldcontext);
2160 elog(ERROR,
"RASTER_quantileCoverage: Cannot allocate memory for sql");
2161 SRF_RETURN_DONE(funcctx);
2165 snprintf(
sql, len,
"SELECT count FROM _st_summarystats('%s','%s',%d,%d::boolean,%f)", tablename, colname, bandindex, (exclude_nodata_value ? 1 : 0), sample);
2167 spi_result = SPI_execute(
sql,
TRUE, 0);
2169 if (spi_result != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
2171 if (SPI_tuptable) SPI_freetuptable(tuptable);
2174 MemoryContextSwitchTo(oldcontext);
2175 elog(ERROR,
"RASTER_quantileCoverage: Cannot get summary stats of coverage");
2176 SRF_RETURN_DONE(funcctx);
2179 tupdesc = SPI_tuptable->tupdesc;
2180 tuptable = SPI_tuptable;
2181 tuple = tuptable->vals[0];
2183 tmp = SPI_getvalue(tuple, tupdesc, 1);
2184 if (NULL == tmp || !strlen(tmp)) {
2186 if (SPI_tuptable) SPI_freetuptable(tuptable);
2189 MemoryContextSwitchTo(oldcontext);
2190 elog(ERROR,
"RASTER_quantileCoverage: Cannot get summary stats of coverage");
2191 SRF_RETURN_DONE(funcctx);
2193 cov_count = strtol(tmp, NULL, 10);
2199 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
2200 sql = (
char *) palloc(len);
2203 if (SPI_tuptable) SPI_freetuptable(tuptable);
2206 MemoryContextSwitchTo(oldcontext);
2207 elog(ERROR,
"RASTER_quantileCoverage: Cannot allocate memory for sql");
2208 SRF_RETURN_DONE(funcctx);
2212 snprintf(
sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
2214 portal = SPI_cursor_open_with_args(
2224 SPI_cursor_fetch(portal,
TRUE, 1);
2225 while (SPI_processed == 1 && SPI_tuptable != NULL) {
2226 if (NULL != covquant) pfree(covquant);
2228 tupdesc = SPI_tuptable->tupdesc;
2229 tuple = SPI_tuptable->vals[0];
2231 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
2232 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
2233 SPI_freetuptable(SPI_tuptable);
2234 SPI_cursor_close(portal);
2237 MemoryContextSwitchTo(oldcontext);
2238 elog(ERROR,
"RASTER_quantileCoverage: Cannot get raster of coverage");
2239 SRF_RETURN_DONE(funcctx);
2242 SPI_cursor_fetch(portal,
TRUE, 1);
2246 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
2251 SPI_freetuptable(SPI_tuptable);
2252 SPI_cursor_close(portal);
2255 MemoryContextSwitchTo(oldcontext);
2256 elog(ERROR,
"RASTER_quantileCoverage: Cannot deserialize raster");
2257 SRF_RETURN_DONE(funcctx);
2262 if (bandindex < 1 || bandindex > num_bands) {
2263 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2267 SPI_freetuptable(SPI_tuptable);
2268 SPI_cursor_close(portal);
2271 MemoryContextSwitchTo(oldcontext);
2272 SRF_RETURN_DONE(funcctx);
2278 elog(NOTICE,
"Cannot find raster band of index %d. Returning NULL", bandindex);
2282 SPI_freetuptable(SPI_tuptable);
2283 SPI_cursor_close(portal);
2286 MemoryContextSwitchTo(oldcontext);
2287 SRF_RETURN_DONE(funcctx);
2292 exclude_nodata_value, sample, cov_count,
2294 quantiles, quantiles_count,
2301 if (!covquant || !
count) {
2302 elog(NOTICE,
"Cannot compute quantiles for band at index %d", bandindex);
2304 SPI_freetuptable(SPI_tuptable);
2305 SPI_cursor_close(portal);
2308 MemoryContextSwitchTo(oldcontext);
2309 SRF_RETURN_DONE(funcctx);
2313 SPI_cursor_fetch(portal,
TRUE, 1);
2317 for (i = 0; i <
count; i++) {
2320 if (covquant2[i].has_value)
2327 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
2328 SPI_cursor_close(portal);
2331 if (quantiles_count) pfree(quantiles);
2336 funcctx->user_fctx = covquant2;
2339 funcctx->max_calls =
count;
2342 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2344 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2346 "function returning record called in context "
2347 "that cannot accept type record"
2352 BlessTupleDesc(tupdesc);
2353 funcctx->tuple_desc = tupdesc;
2355 MemoryContextSwitchTo(oldcontext);
2359 funcctx = SRF_PERCALL_SETUP();
2361 call_cntr = funcctx->call_cntr;
2362 max_calls = funcctx->max_calls;
2363 tupdesc = funcctx->tuple_desc;
2364 covquant2 = funcctx->user_fctx;
2367 if (call_cntr < max_calls) {
2377 values[0] = Float8GetDatum(covquant2[call_cntr].
quantile);
2378 if (covquant2[call_cntr].has_value)
2379 values[1] = Float8GetDatum(covquant2[call_cntr].
value);
2384 tuple = heap_form_tuple(tupdesc, values, nulls);
2387 result = HeapTupleGetDatum(tuple);
2389 SRF_RETURN_NEXT(funcctx, result);
2395 SRF_RETURN_DONE(funcctx);
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
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, uint32_t quantiles_count, uint32_t *rtn_count)
Compute the default set of or requested quantiles for a coverage.
int quantile_llist_destroy(struct quantile_llist **list, uint32_t list_count)
void rt_band_destroy(rt_band band)
Destroy a raster band.
uint16_t rt_raster_get_num_bands(rt_raster raster)
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,...)