1193 FuncCallContext *funcctx;
1205 if (SRF_IS_FIRSTCALL()) {
1206 MemoryContext oldcontext;
1208 text *tablenametext = NULL;
1209 char *tablename = NULL;
1210 text *colnametext = NULL;
1211 char *colname = NULL;
1212 int32_t bandindex = 1;
1213 bool exclude_nodata_value =
TRUE;
1216 double *bin_width = NULL;
1231 bool isNull =
FALSE;
1255 funcctx = SRF_FIRSTCALL_INIT();
1258 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1261 if (PG_ARGISNULL(0)) {
1262 elog(NOTICE,
"Table name must be provided");
1263 MemoryContextSwitchTo(oldcontext);
1264 SRF_RETURN_DONE(funcctx);
1266 tablenametext = PG_GETARG_TEXT_P(0);
1268 if (!strlen(tablename)) {
1269 elog(NOTICE,
"Table name must be provided");
1270 MemoryContextSwitchTo(oldcontext);
1271 SRF_RETURN_DONE(funcctx);
1276 if (PG_ARGISNULL(1)) {
1277 elog(NOTICE,
"Column name must be provided");
1278 MemoryContextSwitchTo(oldcontext);
1279 SRF_RETURN_DONE(funcctx);
1281 colnametext = PG_GETARG_TEXT_P(1);
1283 if (!strlen(colname)) {
1284 elog(NOTICE,
"Column name must be provided");
1285 MemoryContextSwitchTo(oldcontext);
1286 SRF_RETURN_DONE(funcctx);
1291 if (!PG_ARGISNULL(2))
1292 bandindex = PG_GETARG_INT32(2);
1295 if (!PG_ARGISNULL(3))
1296 exclude_nodata_value = PG_GETARG_BOOL(3);
1299 if (!PG_ARGISNULL(4)) {
1300 sample = PG_GETARG_FLOAT8(4);
1301 if (sample < 0 || sample > 1) {
1302 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
1303 MemoryContextSwitchTo(oldcontext);
1304 SRF_RETURN_DONE(funcctx);
1306 else if (
FLT_EQ(sample, 0.0))
1313 if (!PG_ARGISNULL(5)) {
1314 bin_count = PG_GETARG_INT32(5);
1315 if (bin_count < 1) bin_count = 0;
1319 if (!PG_ARGISNULL(6)) {
1320 array = PG_GETARG_ARRAYTYPE_P(6);
1321 etype = ARR_ELEMTYPE(array);
1322 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1329 MemoryContextSwitchTo(oldcontext);
1330 elog(ERROR,
"RASTER_histogramCoverage: Invalid data type for width");
1331 SRF_RETURN_DONE(funcctx);
1335 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1338 bin_width = palloc(
sizeof(
double) * n);
1339 for (i = 0, j = 0; i < (
uint32_t) n; i++) {
1340 if (nulls[i])
continue;
1344 width = (double) DatumGetFloat4(e[i]);
1347 width = (double) DatumGetFloat8(e[i]);
1351 if (width < 0 ||
FLT_EQ(width, 0.0)) {
1352 elog(NOTICE,
"Invalid value for width (must be greater than 0). Returning NULL");
1354 MemoryContextSwitchTo(oldcontext);
1355 SRF_RETURN_DONE(funcctx);
1358 bin_width[j] = width;
1362 bin_width_count = j;
1371 if (!PG_ARGISNULL(7))
1372 right = PG_GETARG_BOOL(7);
1375 spi_result = SPI_connect();
1376 if (spi_result != SPI_OK_CONNECT) {
1378 if (bin_width_count) pfree(bin_width);
1380 MemoryContextSwitchTo(oldcontext);
1381 elog(ERROR,
"RASTER_histogramCoverage: Cannot connect to database using SPI");
1382 SRF_RETURN_DONE(funcctx);
1386 len =
sizeof(char) * (strlen(
"SELECT min, max FROM _st_summarystats('','',,::boolean,)") + strlen(tablename) + strlen(colname) + (
MAX_INT_CHARLEN * 2) +
MAX_DBL_CHARLEN + 1);
1387 sql = (
char *) palloc(len);
1390 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1393 if (bin_width_count) pfree(bin_width);
1395 MemoryContextSwitchTo(oldcontext);
1396 elog(ERROR,
"RASTER_histogramCoverage: Cannot allocate memory for sql");
1397 SRF_RETURN_DONE(funcctx);
1401 snprintf(
sql, len,
"SELECT min, max FROM _st_summarystats('%s','%s',%d,%d::boolean,%f)", tablename, colname, bandindex, (exclude_nodata_value ? 1 : 0), sample);
1403 spi_result = SPI_execute(
sql,
TRUE, 0);
1405 if (spi_result != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
1407 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1410 if (bin_width_count) pfree(bin_width);
1412 MemoryContextSwitchTo(oldcontext);
1413 elog(ERROR,
"RASTER_histogramCoverage: Cannot get summary stats of coverage");
1414 SRF_RETURN_DONE(funcctx);
1417 tupdesc = SPI_tuptable->tupdesc;
1418 tuple = SPI_tuptable->vals[0];
1420 tmp = SPI_getvalue(tuple, tupdesc, 1);
1421 if (NULL == tmp || !strlen(tmp)) {
1423 SPI_freetuptable(SPI_tuptable);
1426 if (bin_width_count) pfree(bin_width);
1428 MemoryContextSwitchTo(oldcontext);
1429 elog(ERROR,
"RASTER_histogramCoverage: Cannot get summary stats of coverage");
1430 SRF_RETURN_DONE(funcctx);
1432 min = strtod(tmp, NULL);
1436 tmp = SPI_getvalue(tuple, tupdesc, 2);
1437 if (NULL == tmp || !strlen(tmp)) {
1439 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1442 if (bin_width_count) pfree(bin_width);
1444 MemoryContextSwitchTo(oldcontext);
1445 elog(ERROR,
"RASTER_histogramCoverage: Cannot get summary stats of coverage");
1446 SRF_RETURN_DONE(funcctx);
1448 max = strtod(tmp, NULL);
1454 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
1455 sql = (
char *) palloc(len);
1458 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1461 if (bin_width_count) pfree(bin_width);
1463 MemoryContextSwitchTo(oldcontext);
1464 elog(ERROR,
"RASTER_histogramCoverage: Cannot allocate memory for sql");
1465 SRF_RETURN_DONE(funcctx);
1469 snprintf(
sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
1471 portal = SPI_cursor_open_with_args(
1481 SPI_cursor_fetch(portal,
TRUE, 1);
1482 while (SPI_processed == 1 && SPI_tuptable != NULL) {
1483 tupdesc = SPI_tuptable->tupdesc;
1484 tuple = SPI_tuptable->vals[0];
1486 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
1487 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1488 SPI_freetuptable(SPI_tuptable);
1489 SPI_cursor_close(portal);
1492 if (NULL != covhist) pfree(covhist);
1493 if (bin_width_count) pfree(bin_width);
1495 MemoryContextSwitchTo(oldcontext);
1496 elog(ERROR,
"RASTER_histogramCoverage: Cannot get raster of coverage");
1497 SRF_RETURN_DONE(funcctx);
1500 SPI_cursor_fetch(portal,
TRUE, 1);
1504 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
1509 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1510 SPI_cursor_close(portal);
1513 if (NULL != covhist) pfree(covhist);
1514 if (bin_width_count) pfree(bin_width);
1516 MemoryContextSwitchTo(oldcontext);
1517 elog(ERROR,
"RASTER_histogramCoverage: Cannot deserialize raster");
1518 SRF_RETURN_DONE(funcctx);
1523 if (bandindex < 1 || bandindex > num_bands) {
1524 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1528 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1529 SPI_cursor_close(portal);
1532 if (NULL != covhist) pfree(covhist);
1533 if (bin_width_count) pfree(bin_width);
1535 MemoryContextSwitchTo(oldcontext);
1536 SRF_RETURN_DONE(funcctx);
1542 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1546 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1547 SPI_cursor_close(portal);
1550 if (NULL != covhist) pfree(covhist);
1551 if (bin_width_count) pfree(bin_width);
1553 MemoryContextSwitchTo(oldcontext);
1554 SRF_RETURN_DONE(funcctx);
1563 if (NULL == stats) {
1564 elog(NOTICE,
"Cannot compute summary statistics for band at index %d. Returning NULL", bandindex);
1566 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1567 SPI_cursor_close(portal);
1570 if (NULL != covhist) pfree(covhist);
1571 if (bin_width_count) pfree(bin_width);
1573 MemoryContextSwitchTo(oldcontext);
1574 SRF_RETURN_DONE(funcctx);
1578 if (stats->
count > 0) {
1581 if (NULL == hist || !
count) {
1582 elog(NOTICE,
"Cannot compute histogram for band at index %d", bandindex);
1584 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1585 SPI_cursor_close(portal);
1588 if (NULL != covhist) pfree(covhist);
1589 if (bin_width_count) pfree(bin_width);
1591 MemoryContextSwitchTo(oldcontext);
1592 SRF_RETURN_DONE(funcctx);
1598 if (NULL == covhist) {
1600 if (NULL == covhist) {
1603 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1604 SPI_cursor_close(portal);
1607 if (bin_width_count) pfree(bin_width);
1609 MemoryContextSwitchTo(oldcontext);
1610 elog(ERROR,
"RASTER_histogramCoverage: Cannot allocate memory for histogram of coverage");
1611 SRF_RETURN_DONE(funcctx);
1614 for (i = 0; i <
count; i++) {
1615 sum += hist[i].
count;
1618 covhist[i].
min = hist[i].
min;
1619 covhist[i].
max = hist[i].
max;
1623 for (i = 0; i <
count; i++) {
1624 sum += hist[i].
count;
1632 if (bin_count <= 0) bin_count =
count;
1636 SPI_cursor_fetch(portal,
TRUE, 1);
1639 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1640 SPI_cursor_close(portal);
1643 if (bin_width_count) pfree(bin_width);
1647 for (i = 0; i <
count; i++)
1648 covhist[i].percent = covhist[i].
count / (
double) sum;
1652 funcctx->user_fctx = covhist;
1655 funcctx->max_calls =
count;
1658 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1660 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1662 "function returning record called in context "
1663 "that cannot accept type record"
1668 BlessTupleDesc(tupdesc);
1669 funcctx->tuple_desc = tupdesc;
1671 MemoryContextSwitchTo(oldcontext);
1675 funcctx = SRF_PERCALL_SETUP();
1677 call_cntr = funcctx->call_cntr;
1678 max_calls = funcctx->max_calls;
1679 tupdesc = funcctx->tuple_desc;
1680 covhist2 = funcctx->user_fctx;
1683 if (call_cntr < max_calls) {
1693 values[0] = Float8GetDatum(covhist2[call_cntr].min);
1694 values[1] = Float8GetDatum(covhist2[call_cntr].max);
1695 values[2] = Int64GetDatum(covhist2[call_cntr].
count);
1696 values[3] = Float8GetDatum(covhist2[call_cntr].percent);
1699 tuple = heap_form_tuple(tupdesc, values, nulls);
1702 result = HeapTupleGetDatum(tuple);
1704 SRF_RETURN_NEXT(funcctx, result);
1709 SRF_RETURN_DONE(funcctx);
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
void rt_band_destroy(rt_band band)
Destroy a raster band.
uint16_t rt_raster_get_num_bands(rt_raster raster)
rt_histogram rt_band_get_histogram(rt_bandstats stats, uint32_t bin_count, double *bin_widths, uint32_t bin_widths_count, int right, double min, double max, uint32_t *rtn_count)
Count the distribution of data.
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_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,...)