1971 FuncCallContext *funcctx;
1983 if (SRF_IS_FIRSTCALL()) {
1984 MemoryContext oldcontext;
1986 text *tablenametext = NULL;
1987 char *tablename = NULL;
1988 text *colnametext = NULL;
1989 char *colname = NULL;
1990 int32_t bandindex = 1;
1991 bool exclude_nodata_value =
TRUE;
1993 double *quantiles = NULL;
1995 double quantile = 0;
2001 uint64_t cov_count = 0;
2004 SPITupleTable *tuptable = NULL;
2007 bool isNull =
FALSE;
2030 funcctx = SRF_FIRSTCALL_INIT();
2033 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2036 if (PG_ARGISNULL(0)) {
2037 elog(NOTICE,
"Table name must be provided");
2038 MemoryContextSwitchTo(oldcontext);
2039 SRF_RETURN_DONE(funcctx);
2041 tablenametext = PG_GETARG_TEXT_P(0);
2043 if (!strlen(tablename)) {
2044 elog(NOTICE,
"Table name must be provided");
2045 MemoryContextSwitchTo(oldcontext);
2046 SRF_RETURN_DONE(funcctx);
2051 if (PG_ARGISNULL(1)) {
2052 elog(NOTICE,
"Column name must be provided");
2053 MemoryContextSwitchTo(oldcontext);
2054 SRF_RETURN_DONE(funcctx);
2056 colnametext = PG_GETARG_TEXT_P(1);
2058 if (!strlen(colname)) {
2059 elog(NOTICE,
"Column name must be provided");
2060 MemoryContextSwitchTo(oldcontext);
2061 SRF_RETURN_DONE(funcctx);
2066 if (!PG_ARGISNULL(2))
2067 bandindex = PG_GETARG_INT32(2);
2070 if (!PG_ARGISNULL(3))
2071 exclude_nodata_value = PG_GETARG_BOOL(3);
2074 if (!PG_ARGISNULL(4)) {
2075 sample = PG_GETARG_FLOAT8(4);
2076 if (sample < 0 || sample > 1) {
2077 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
2078 MemoryContextSwitchTo(oldcontext);
2079 SRF_RETURN_DONE(funcctx);
2081 else if (
FLT_EQ(sample, 0.0))
2088 if (!PG_ARGISNULL(5)) {
2089 array = PG_GETARG_ARRAYTYPE_P(5);
2090 etype = ARR_ELEMTYPE(array);
2091 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2098 MemoryContextSwitchTo(oldcontext);
2099 elog(ERROR,
"RASTER_quantileCoverage: Invalid data type for quantiles");
2100 SRF_RETURN_DONE(funcctx);
2104 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2107 quantiles = palloc(
sizeof(
double) * n);
2108 for (i = 0, j = 0; i < (
uint32_t) n; i++) {
2109 if (nulls[i])
continue;
2113 quantile = (double) DatumGetFloat4(e[i]);
2116 quantile = (double) DatumGetFloat8(e[i]);
2120 if (quantile < 0 || quantile > 1) {
2121 elog(NOTICE,
"Invalid value for quantile (must be between 0 and 1). Returning NULL");
2123 MemoryContextSwitchTo(oldcontext);
2124 SRF_RETURN_DONE(funcctx);
2131 quantiles_count = j;
2141 spi_result = SPI_connect();
2142 if (spi_result != SPI_OK_CONNECT) {
2143 MemoryContextSwitchTo(oldcontext);
2144 elog(ERROR,
"RASTER_quantileCoverage: Cannot connect to database using SPI");
2145 SRF_RETURN_DONE(funcctx);
2148 len =
sizeof(char) * (strlen(
"SELECT count FROM _st_summarystats('','',,::boolean,)") + strlen(tablename) + strlen(colname) + (
MAX_INT_CHARLEN * 2) +
MAX_DBL_CHARLEN + 1);
2149 sql = (
char *) palloc(len);
2152 if (SPI_tuptable) SPI_freetuptable(tuptable);
2155 MemoryContextSwitchTo(oldcontext);
2156 elog(ERROR,
"RASTER_quantileCoverage: Cannot allocate memory for sql");
2157 SRF_RETURN_DONE(funcctx);
2161 snprintf(
sql, len,
"SELECT count FROM _st_summarystats('%s','%s',%d,%d::boolean,%f)", tablename, colname, bandindex, (exclude_nodata_value ? 1 : 0), sample);
2163 spi_result = SPI_execute(
sql,
TRUE, 0);
2165 if (spi_result != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
2167 if (SPI_tuptable) SPI_freetuptable(tuptable);
2170 MemoryContextSwitchTo(oldcontext);
2171 elog(ERROR,
"RASTER_quantileCoverage: Cannot get summary stats of coverage");
2172 SRF_RETURN_DONE(funcctx);
2175 tupdesc = SPI_tuptable->tupdesc;
2176 tuptable = SPI_tuptable;
2177 tuple = tuptable->vals[0];
2179 tmp = SPI_getvalue(tuple, tupdesc, 1);
2180 if (NULL == tmp || !strlen(tmp)) {
2182 if (SPI_tuptable) SPI_freetuptable(tuptable);
2185 MemoryContextSwitchTo(oldcontext);
2186 elog(ERROR,
"RASTER_quantileCoverage: Cannot get summary stats of coverage");
2187 SRF_RETURN_DONE(funcctx);
2189 cov_count = strtol(tmp, NULL, 10);
2195 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
2196 sql = (
char *) palloc(len);
2199 if (SPI_tuptable) SPI_freetuptable(tuptable);
2202 MemoryContextSwitchTo(oldcontext);
2203 elog(ERROR,
"RASTER_quantileCoverage: Cannot allocate memory for sql");
2204 SRF_RETURN_DONE(funcctx);
2208 snprintf(
sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
2210 portal = SPI_cursor_open_with_args(
2220 SPI_cursor_fetch(portal,
TRUE, 1);
2221 while (SPI_processed == 1 && SPI_tuptable != NULL) {
2222 if (NULL != covquant) pfree(covquant);
2224 tupdesc = SPI_tuptable->tupdesc;
2225 tuple = SPI_tuptable->vals[0];
2227 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
2228 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
2229 SPI_freetuptable(SPI_tuptable);
2230 SPI_cursor_close(portal);
2233 MemoryContextSwitchTo(oldcontext);
2234 elog(ERROR,
"RASTER_quantileCoverage: Cannot get raster of coverage");
2235 SRF_RETURN_DONE(funcctx);
2238 SPI_cursor_fetch(portal,
TRUE, 1);
2242 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
2247 SPI_freetuptable(SPI_tuptable);
2248 SPI_cursor_close(portal);
2251 MemoryContextSwitchTo(oldcontext);
2252 elog(ERROR,
"RASTER_quantileCoverage: Cannot deserialize raster");
2253 SRF_RETURN_DONE(funcctx);
2258 if (bandindex < 1 || bandindex > num_bands) {
2259 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2263 SPI_freetuptable(SPI_tuptable);
2264 SPI_cursor_close(portal);
2267 MemoryContextSwitchTo(oldcontext);
2268 SRF_RETURN_DONE(funcctx);
2274 elog(NOTICE,
"Cannot find raster band of index %d. Returning NULL", bandindex);
2278 SPI_freetuptable(SPI_tuptable);
2279 SPI_cursor_close(portal);
2282 MemoryContextSwitchTo(oldcontext);
2283 SRF_RETURN_DONE(funcctx);
2288 exclude_nodata_value, sample, cov_count,
2290 quantiles, quantiles_count,
2297 if (!covquant || !
count) {
2298 elog(NOTICE,
"Cannot compute quantiles for band at index %d", bandindex);
2300 SPI_freetuptable(SPI_tuptable);
2301 SPI_cursor_close(portal);
2304 MemoryContextSwitchTo(oldcontext);
2305 SRF_RETURN_DONE(funcctx);
2309 SPI_cursor_fetch(portal,
TRUE, 1);
2313 for (i = 0; i <
count; i++) {
2316 if (covquant2[i].has_value)
2323 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
2324 SPI_cursor_close(portal);
2327 if (quantiles_count) pfree(quantiles);
2332 funcctx->user_fctx = covquant2;
2335 funcctx->max_calls =
count;
2338 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2340 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2342 "function returning record called in context "
2343 "that cannot accept type record"
2348 BlessTupleDesc(tupdesc);
2349 funcctx->tuple_desc = tupdesc;
2351 MemoryContextSwitchTo(oldcontext);
2355 funcctx = SRF_PERCALL_SETUP();
2357 call_cntr = funcctx->call_cntr;
2358 max_calls = funcctx->max_calls;
2359 tupdesc = funcctx->tuple_desc;
2360 covquant2 = funcctx->user_fctx;
2363 if (call_cntr < max_calls) {
2373 values[0] = Float8GetDatum(covquant2[call_cntr].
quantile);
2374 if (covquant2[call_cntr].has_value)
2375 values[1] = Float8GetDatum(covquant2[call_cntr].
value);
2380 tuple = heap_form_tuple(tupdesc, values, nulls);
2383 result = HeapTupleGetDatum(tuple);
2385 SRF_RETURN_NEXT(funcctx, result);
2391 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,...)