1197 FuncCallContext *funcctx;
1209 if (SRF_IS_FIRSTCALL()) {
1210 MemoryContext oldcontext;
1212 text *tablenametext = NULL;
1213 char *tablename = NULL;
1214 text *colnametext = NULL;
1215 char *colname = NULL;
1216 int32_t bandindex = 1;
1217 bool exclude_nodata_value =
TRUE;
1220 double *bin_width = NULL;
1233 SPITupleTable *tuptable = NULL;
1236 bool isNull =
FALSE;
1260 funcctx = SRF_FIRSTCALL_INIT();
1263 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1266 if (PG_ARGISNULL(0)) {
1267 elog(NOTICE,
"Table name must be provided");
1268 MemoryContextSwitchTo(oldcontext);
1269 SRF_RETURN_DONE(funcctx);
1271 tablenametext = PG_GETARG_TEXT_P(0);
1272 tablename = text_to_cstring(tablenametext);
1273 if (!strlen(tablename)) {
1274 elog(NOTICE,
"Table name must be provided");
1275 MemoryContextSwitchTo(oldcontext);
1276 SRF_RETURN_DONE(funcctx);
1281 if (PG_ARGISNULL(1)) {
1282 elog(NOTICE,
"Column name must be provided");
1283 MemoryContextSwitchTo(oldcontext);
1284 SRF_RETURN_DONE(funcctx);
1286 colnametext = PG_GETARG_TEXT_P(1);
1287 colname = text_to_cstring(colnametext);
1288 if (!strlen(colname)) {
1289 elog(NOTICE,
"Column name must be provided");
1290 MemoryContextSwitchTo(oldcontext);
1291 SRF_RETURN_DONE(funcctx);
1296 if (!PG_ARGISNULL(2))
1297 bandindex = PG_GETARG_INT32(2);
1300 if (!PG_ARGISNULL(3))
1301 exclude_nodata_value = PG_GETARG_BOOL(3);
1304 if (!PG_ARGISNULL(4)) {
1305 sample = PG_GETARG_FLOAT8(4);
1306 if (sample < 0 || sample > 1) {
1307 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
1308 MemoryContextSwitchTo(oldcontext);
1309 SRF_RETURN_DONE(funcctx);
1311 else if (
FLT_EQ(sample, 0.0))
1318 if (!PG_ARGISNULL(5)) {
1319 bin_count = PG_GETARG_INT32(5);
1320 if (bin_count < 1) bin_count = 0;
1324 if (!PG_ARGISNULL(6)) {
1325 array = PG_GETARG_ARRAYTYPE_P(6);
1326 etype = ARR_ELEMTYPE(array);
1327 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1334 MemoryContextSwitchTo(oldcontext);
1335 elog(ERROR,
"RASTER_histogramCoverage: Invalid data type for width");
1336 SRF_RETURN_DONE(funcctx);
1340 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1343 bin_width = palloc(
sizeof(
double) * n);
1344 for (i = 0, j = 0; i < n; i++) {
1345 if (nulls[i])
continue;
1349 width = (double) DatumGetFloat4(e[i]);
1352 width = (double) DatumGetFloat8(e[i]);
1356 if (width < 0 ||
FLT_EQ(width, 0.0)) {
1357 elog(NOTICE,
"Invalid value for width (must be greater than 0). Returning NULL");
1359 MemoryContextSwitchTo(oldcontext);
1360 SRF_RETURN_DONE(funcctx);
1363 bin_width[j] = width;
1367 bin_width_count = j;
1376 if (!PG_ARGISNULL(7))
1377 right = PG_GETARG_BOOL(7);
1380 spi_result = SPI_connect();
1381 if (spi_result != SPI_OK_CONNECT) {
1383 if (bin_width_count) pfree(bin_width);
1385 MemoryContextSwitchTo(oldcontext);
1386 elog(ERROR,
"RASTER_histogramCoverage: Cannot connect to database using SPI");
1387 SRF_RETURN_DONE(funcctx);
1391 len =
sizeof(char) * (strlen(
"SELECT min, max FROM _st_summarystats('','',,::boolean,)") + strlen(tablename) + strlen(colname) + (
MAX_INT_CHARLEN * 2) +
MAX_DBL_CHARLEN + 1);
1392 sql = (
char *) palloc(len);
1395 if (SPI_tuptable) SPI_freetuptable(tuptable);
1398 if (bin_width_count) pfree(bin_width);
1400 MemoryContextSwitchTo(oldcontext);
1401 elog(ERROR,
"RASTER_histogramCoverage: Cannot allocate memory for sql");
1402 SRF_RETURN_DONE(funcctx);
1406 snprintf(sql, len,
"SELECT min, max FROM _st_summarystats('%s','%s',%d,%d::boolean,%f)", tablename, colname, bandindex, (exclude_nodata_value ? 1 : 0), sample);
1408 spi_result = SPI_execute(sql,
TRUE, 0);
1410 if (spi_result != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
1412 if (SPI_tuptable) SPI_freetuptable(tuptable);
1415 if (bin_width_count) pfree(bin_width);
1417 MemoryContextSwitchTo(oldcontext);
1418 elog(ERROR,
"RASTER_histogramCoverage: Cannot get summary stats of coverage");
1419 SRF_RETURN_DONE(funcctx);
1422 tupdesc = SPI_tuptable->tupdesc;
1423 tuptable = SPI_tuptable;
1424 tuple = tuptable->vals[0];
1426 tmp = SPI_getvalue(tuple, tupdesc, 1);
1427 if (NULL == tmp || !strlen(tmp)) {
1429 if (SPI_tuptable) SPI_freetuptable(tuptable);
1432 if (bin_width_count) pfree(bin_width);
1434 MemoryContextSwitchTo(oldcontext);
1435 elog(ERROR,
"RASTER_histogramCoverage: Cannot get summary stats of coverage");
1436 SRF_RETURN_DONE(funcctx);
1438 min = strtod(tmp, NULL);
1442 tmp = SPI_getvalue(tuple, tupdesc, 2);
1443 if (NULL == tmp || !strlen(tmp)) {
1445 if (SPI_tuptable) SPI_freetuptable(tuptable);
1448 if (bin_width_count) pfree(bin_width);
1450 MemoryContextSwitchTo(oldcontext);
1451 elog(ERROR,
"RASTER_histogramCoverage: Cannot get summary stats of coverage");
1452 SRF_RETURN_DONE(funcctx);
1454 max = strtod(tmp, NULL);
1460 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
1461 sql = (
char *) palloc(len);
1464 if (SPI_tuptable) SPI_freetuptable(tuptable);
1467 if (bin_width_count) pfree(bin_width);
1469 MemoryContextSwitchTo(oldcontext);
1470 elog(ERROR,
"RASTER_histogramCoverage: Cannot allocate memory for sql");
1471 SRF_RETURN_DONE(funcctx);
1475 snprintf(sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
1477 portal = SPI_cursor_open_with_args(
1487 SPI_cursor_fetch(portal,
TRUE, 1);
1488 while (SPI_processed == 1 && SPI_tuptable != NULL) {
1489 tupdesc = SPI_tuptable->tupdesc;
1490 tuptable = SPI_tuptable;
1491 tuple = tuptable->vals[0];
1493 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
1494 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1496 if (SPI_tuptable) SPI_freetuptable(tuptable);
1497 SPI_cursor_close(portal);
1500 if (NULL != covhist) pfree(covhist);
1501 if (bin_width_count) pfree(bin_width);
1503 MemoryContextSwitchTo(oldcontext);
1504 elog(ERROR,
"RASTER_histogramCoverage: Cannot get raster of coverage");
1505 SRF_RETURN_DONE(funcctx);
1508 SPI_cursor_fetch(portal,
TRUE, 1);
1512 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
1517 if (SPI_tuptable) SPI_freetuptable(tuptable);
1518 SPI_cursor_close(portal);
1521 if (NULL != covhist) pfree(covhist);
1522 if (bin_width_count) pfree(bin_width);
1524 MemoryContextSwitchTo(oldcontext);
1525 elog(ERROR,
"RASTER_histogramCoverage: Cannot deserialize raster");
1526 SRF_RETURN_DONE(funcctx);
1531 if (bandindex < 1 || bandindex > num_bands) {
1532 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1536 if (SPI_tuptable) SPI_freetuptable(tuptable);
1537 SPI_cursor_close(portal);
1540 if (NULL != covhist) pfree(covhist);
1541 if (bin_width_count) pfree(bin_width);
1543 MemoryContextSwitchTo(oldcontext);
1544 SRF_RETURN_DONE(funcctx);
1550 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1554 if (SPI_tuptable) SPI_freetuptable(tuptable);
1555 SPI_cursor_close(portal);
1558 if (NULL != covhist) pfree(covhist);
1559 if (bin_width_count) pfree(bin_width);
1561 MemoryContextSwitchTo(oldcontext);
1562 SRF_RETURN_DONE(funcctx);
1571 if (NULL == stats) {
1572 elog(NOTICE,
"Cannot compute summary statistics for band at index %d. Returning NULL", bandindex);
1574 if (SPI_tuptable) SPI_freetuptable(tuptable);
1575 SPI_cursor_close(portal);
1578 if (NULL != covhist) pfree(covhist);
1579 if (bin_width_count) pfree(bin_width);
1581 MemoryContextSwitchTo(oldcontext);
1582 SRF_RETURN_DONE(funcctx);
1586 if (stats->
count > 0) {
1587 hist =
rt_band_get_histogram(stats, bin_count, bin_width, bin_width_count, right, min, max, &count);
1589 if (NULL == hist || !count) {
1590 elog(NOTICE,
"Cannot compute histogram for band at index %d", bandindex);
1592 if (SPI_tuptable) SPI_freetuptable(tuptable);
1593 SPI_cursor_close(portal);
1596 if (NULL != covhist) pfree(covhist);
1597 if (bin_width_count) pfree(bin_width);
1599 MemoryContextSwitchTo(oldcontext);
1600 SRF_RETURN_DONE(funcctx);
1606 if (NULL == covhist) {
1608 if (NULL == covhist) {
1611 if (SPI_tuptable) SPI_freetuptable(tuptable);
1612 SPI_cursor_close(portal);
1615 if (bin_width_count) pfree(bin_width);
1617 MemoryContextSwitchTo(oldcontext);
1618 elog(ERROR,
"RASTER_histogramCoverage: Cannot allocate memory for histogram of coverage");
1619 SRF_RETURN_DONE(funcctx);
1622 for (i = 0; i <
count; i++) {
1623 sum += hist[i].
count;
1626 covhist[i].
min = hist[i].
min;
1627 covhist[i].
max = hist[i].
max;
1631 for (i = 0; i <
count; i++) {
1632 sum += hist[i].
count;
1640 if (bin_count <= 0) bin_count =
count;
1644 SPI_cursor_fetch(portal,
TRUE, 1);
1647 if (SPI_tuptable) SPI_freetuptable(tuptable);
1648 SPI_cursor_close(portal);
1651 if (bin_width_count) pfree(bin_width);
1655 for (i = 0; i <
count; i++)
1656 covhist[i].percent = covhist[i].count / (
double) sum;
1660 funcctx->user_fctx = covhist;
1663 funcctx->max_calls =
count;
1666 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1668 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1670 "function returning record called in context " 1671 "that cannot accept type record" 1676 BlessTupleDesc(tupdesc);
1677 funcctx->tuple_desc = tupdesc;
1679 MemoryContextSwitchTo(oldcontext);
1683 funcctx = SRF_PERCALL_SETUP();
1685 call_cntr = funcctx->call_cntr;
1686 max_calls = funcctx->max_calls;
1687 tupdesc = funcctx->tuple_desc;
1688 covhist2 = funcctx->user_fctx;
1691 if (call_cntr < max_calls) {
1701 values[0] = Float8GetDatum(covhist2[call_cntr].min);
1702 values[1] = Float8GetDatum(covhist2[call_cntr].max);
1703 values[2] = Int64GetDatum(covhist2[call_cntr].count);
1704 values[3] = Float8GetDatum(covhist2[call_cntr].percent);
1707 tuple = heap_form_tuple(tupdesc, values, nulls);
1710 result = HeapTupleGetDatum(tuple);
1712 SRF_RETURN_NEXT(funcctx, result);
1717 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.
rt_bandstats rt_band_get_summary_stats(rt_band band, int exclude_nodata_value, double sample, int inc_vals, uint64_t *cK, double *cM, double *cQ)
Compute summary statistics for a band.
struct rt_histogram_t * rt_histogram
rt_histogram rt_band_get_histogram(rt_bandstats stats, int bin_count, double *bin_widths, int bin_widths_count, int right, double min, double max, uint32_t *rtn_count)
Count the distribution of data.
#define POSTGIS_RT_DEBUG(level, msg)
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.