33 #include <utils/builtins.h>
34 #include "utils/lsyscache.h"
35 #include "utils/array.h"
36 #include "catalog/pg_type.h"
37 #include <executor/spi.h>
40 #include "../../postgis_config.h"
43 #include "access/htup_details.h"
67 #define VALUES_LENGTH 6
78 int32_t bandindex = 1;
79 bool exclude_nodata_value =
TRUE;
93 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
97 PG_FREE_IF_COPY(pgraster, 0);
98 elog(ERROR,
"RASTER_summaryStats: Cannot deserialize raster");
103 if (!PG_ARGISNULL(1))
104 bandindex = PG_GETARG_INT32(1);
106 if (bandindex < 1 || bandindex > num_bands) {
107 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
109 PG_FREE_IF_COPY(pgraster, 0);
114 if (!PG_ARGISNULL(2))
115 exclude_nodata_value = PG_GETARG_BOOL(2);
118 if (!PG_ARGISNULL(3)) {
119 sample = PG_GETARG_FLOAT8(3);
120 if (sample < 0 || sample > 1) {
121 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
123 PG_FREE_IF_COPY(pgraster, 0);
126 else if (
FLT_EQ(sample, 0.0))
135 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
137 PG_FREE_IF_COPY(pgraster, 0);
145 PG_FREE_IF_COPY(pgraster, 0);
147 elog(NOTICE,
"Cannot compute summary statistics for band at index %d. Returning NULL", bandindex);
152 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
154 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
156 "function returning record called in context "
157 "that cannot accept type record"
162 BlessTupleDesc(tupdesc);
166 values[0] = Int64GetDatum(stats->
count);
167 if (stats->
count > 0) {
168 values[1] = Float8GetDatum(stats->
sum);
169 values[2] = Float8GetDatum(stats->
mean);
170 values[3] = Float8GetDatum(stats->
stddev);
171 values[4] = Float8GetDatum(stats->
min);
172 values[5] = Float8GetDatum(stats->
max);
183 tuple = heap_form_tuple(tupdesc, values, nulls);
186 result = HeapTupleGetDatum(tuple);
191 PG_RETURN_DATUM(result);
200 text *tablenametext = NULL;
201 char *tablename = NULL;
202 text *colnametext = NULL;
203 char *colname = NULL;
204 int32_t bandindex = 1;
205 bool exclude_nodata_value =
TRUE;
213 SPITupleTable *tuptable = NULL;
233 if (PG_ARGISNULL(0)) {
234 elog(NOTICE,
"Table name must be provided");
237 tablenametext = PG_GETARG_TEXT_P(0);
239 if (!strlen(tablename)) {
240 elog(NOTICE,
"Table name must be provided");
245 if (PG_ARGISNULL(1)) {
246 elog(NOTICE,
"Column name must be provided");
249 colnametext = PG_GETARG_TEXT_P(1);
251 if (!strlen(colname)) {
252 elog(NOTICE,
"Column name must be provided");
257 if (!PG_ARGISNULL(2))
258 bandindex = PG_GETARG_INT32(2);
261 if (!PG_ARGISNULL(3))
262 exclude_nodata_value = PG_GETARG_BOOL(3);
265 if (!PG_ARGISNULL(4)) {
266 sample = PG_GETARG_FLOAT8(4);
267 if (sample < 0 || sample > 1) {
268 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
272 else if (
FLT_EQ(sample, 0.0))
280 spi_result = SPI_connect();
281 if (spi_result != SPI_OK_CONNECT) {
283 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot connect to database using SPI");
288 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
289 sql = (
char *) palloc(len);
291 if (SPI_tuptable) SPI_freetuptable(tuptable);
293 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot allocate memory for sql");
298 snprintf(
sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
299 portal = SPI_cursor_open_with_args(
309 SPI_cursor_fetch(portal,
TRUE, 1);
310 while (SPI_processed == 1 && SPI_tuptable != NULL) {
311 tupdesc = SPI_tuptable->tupdesc;
312 tuple = SPI_tuptable->vals[0];
314 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
315 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
316 SPI_freetuptable(SPI_tuptable);
317 SPI_cursor_close(portal);
320 if (NULL != rtn) pfree(rtn);
321 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot get raster of coverage");
325 SPI_cursor_fetch(portal,
TRUE, 1);
329 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
333 SPI_freetuptable(SPI_tuptable);
334 SPI_cursor_close(portal);
337 if (NULL != rtn) pfree(rtn);
338 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot deserialize raster");
344 if (bandindex < 1 || bandindex > num_bands) {
345 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
349 SPI_freetuptable(SPI_tuptable);
350 SPI_cursor_close(portal);
353 if (NULL != rtn) pfree(rtn);
360 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
364 SPI_freetuptable(SPI_tuptable);
365 SPI_cursor_close(portal);
368 if (NULL != rtn) pfree(rtn);
379 elog(NOTICE,
"Cannot compute summary statistics for band at index %d. Returning NULL", bandindex);
381 SPI_freetuptable(SPI_tuptable);
382 SPI_cursor_close(portal);
385 if (NULL != rtn) pfree(rtn);
390 if (stats->
count > 0) {
394 SPI_freetuptable(SPI_tuptable);
395 SPI_cursor_close(portal);
398 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot allocate memory for summary stats of coverage");
417 if (stats->
min < rtn->
min)
419 if (stats->
max > rtn->
max)
427 SPI_cursor_fetch(portal,
TRUE, 1);
430 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
431 SPI_cursor_close(portal);
435 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot compute coverage summary stats");
449 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
451 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
453 "function returning record called in context "
454 "that cannot accept type record"
459 BlessTupleDesc(tupdesc);
463 values[0] = Int64GetDatum(rtn->
count);
464 if (rtn->
count > 0) {
465 values[1] = Float8GetDatum(rtn->
sum);
466 values[2] = Float8GetDatum(rtn->
mean);
467 values[3] = Float8GetDatum(rtn->
stddev);
468 values[4] = Float8GetDatum(rtn->
min);
469 values[5] = Float8GetDatum(rtn->
max);
480 tuple = heap_form_tuple(tupdesc, values, nulls);
483 result = HeapTupleGetDatum(tuple);
488 PG_RETURN_DATUM(result);
511 if (arg->
stats != NULL)
525 "rtpg_summarystats_arg_init: Cannot allocate memory for function arguments"
531 if (arg->
stats == NULL) {
535 "rtpg_summarystats_arg_init: Cannot allocate memory for stats function argument"
564 MemoryContext aggcontext;
565 MemoryContext oldcontext;
567 bool skiparg =
FALSE;
580 if (!AggCheckCallContext(fcinfo, &aggcontext)) {
583 "RASTER_summaryStats_transfn: Cannot be called in a non-aggregate context"
589 oldcontext = MemoryContextSwitchTo(aggcontext);
591 if (PG_ARGISNULL(0)) {
596 MemoryContextSwitchTo(oldcontext);
599 "RASTER_summaryStats_transfn: Cannot allocate memory for state variable"
613 if (!PG_ARGISNULL(1)) {
615 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
622 PG_FREE_IF_COPY(pgraster, 1);
624 MemoryContextSwitchTo(oldcontext);
625 elog(ERROR,
"RASTER_summaryStats_transfn: Cannot deserialize raster");
641 for (i = 2; i < nargs; i++) {
645 calltype = get_fn_expr_argtype(fcinfo->flinfo, i);
649 (calltype == INT2OID || calltype == INT4OID) &&
652 if (calltype == INT2OID)
663 PG_FREE_IF_COPY(pgraster, 1);
666 MemoryContextSwitchTo(oldcontext);
669 "RASTER_summaryStats_transfn: Invalid band index (must use 1-based). Returning NULL"
676 calltype == BOOLOID && (
684 (calltype == FLOAT4OID || calltype == FLOAT8OID) &&
687 if (calltype == FLOAT4OID)
688 state->
sample = PG_GETARG_FLOAT4(i);
690 state->
sample = PG_GETARG_FLOAT8(i);
698 PG_FREE_IF_COPY(pgraster, 1);
701 MemoryContextSwitchTo(oldcontext);
704 "Invalid sample percentage (must be between 0 and 1). Returning NULL"
717 PG_FREE_IF_COPY(pgraster, 1);
720 MemoryContextSwitchTo(oldcontext);
723 "RASTER_summaryStats_transfn: Unknown function parameter at index %d",
733 if (PG_ARGISNULL(1)) {
735 MemoryContextSwitchTo(oldcontext);
736 PG_RETURN_POINTER(state);
744 "Raster does not have band at index %d. Skipping raster",
749 PG_FREE_IF_COPY(pgraster, 1);
751 MemoryContextSwitchTo(oldcontext);
752 PG_RETURN_POINTER(state);
759 NOTICE,
"Cannot find band at index %d. Skipping raster",
764 PG_FREE_IF_COPY(pgraster, 1);
766 MemoryContextSwitchTo(oldcontext);
767 PG_RETURN_POINTER(state);
774 &(state->
cK), &(state->
cM), &(state->
cQ)
779 PG_FREE_IF_COPY(pgraster, 1);
784 "Cannot compute summary statistics for band at index %d. Returning NULL",
790 MemoryContextSwitchTo(oldcontext);
794 if (stats->
count > 0) {
818 MemoryContextSwitchTo(oldcontext);
822 PG_RETURN_POINTER(state);
839 if (!AggCheckCallContext(fcinfo, NULL)) {
840 elog(ERROR,
"RASTER_summaryStats_finalfn: Cannot be called in a non-aggregate context");
851 elog(ERROR,
"RASTER_summaryStats_finalfn: Cannot compute coverage summary stats");
867 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
870 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
872 "function returning record called in context "
873 "that cannot accept type record"
878 BlessTupleDesc(tupdesc);
882 values[0] = Int64GetDatum(state->
stats->
count);
884 values[1] = Float8GetDatum(state->
stats->
sum);
885 values[2] = Float8GetDatum(state->
stats->
mean);
887 values[4] = Float8GetDatum(state->
stats->
min);
888 values[5] = Float8GetDatum(state->
stats->
max);
899 tuple = heap_form_tuple(tupdesc, values, nulls);
902 result = HeapTupleGetDatum(tuple);
907 PG_RETURN_DATUM(result);
911 #define VALUES_LENGTH 4
919 FuncCallContext *funcctx;
929 if (SRF_IS_FIRSTCALL()) {
930 MemoryContext oldcontext;
935 int32_t bandindex = 1;
937 bool exclude_nodata_value =
TRUE;
940 double *bin_width = NULL;
963 funcctx = SRF_FIRSTCALL_INIT();
966 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
969 if (PG_ARGISNULL(0)) {
970 MemoryContextSwitchTo(oldcontext);
971 SRF_RETURN_DONE(funcctx);
973 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
977 PG_FREE_IF_COPY(pgraster, 0);
978 MemoryContextSwitchTo(oldcontext);
979 elog(ERROR,
"RASTER_histogram: Cannot deserialize raster");
980 SRF_RETURN_DONE(funcctx);
984 if (!PG_ARGISNULL(1))
985 bandindex = PG_GETARG_INT32(1);
987 if (bandindex < 1 || bandindex > num_bands) {
988 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
990 PG_FREE_IF_COPY(pgraster, 0);
991 MemoryContextSwitchTo(oldcontext);
992 SRF_RETURN_DONE(funcctx);
996 if (!PG_ARGISNULL(2))
997 exclude_nodata_value = PG_GETARG_BOOL(2);
1000 if (!PG_ARGISNULL(3)) {
1001 sample = PG_GETARG_FLOAT8(3);
1002 if (sample < 0 || sample > 1) {
1003 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
1005 PG_FREE_IF_COPY(pgraster, 0);
1006 MemoryContextSwitchTo(oldcontext);
1007 SRF_RETURN_DONE(funcctx);
1009 else if (
FLT_EQ(sample, 0.0))
1016 if (!PG_ARGISNULL(4)) {
1017 bin_count = PG_GETARG_INT32(4);
1018 if (bin_count < 1) bin_count = 0;
1022 if (!PG_ARGISNULL(5)) {
1023 array = PG_GETARG_ARRAYTYPE_P(5);
1024 etype = ARR_ELEMTYPE(array);
1025 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1033 PG_FREE_IF_COPY(pgraster, 0);
1034 MemoryContextSwitchTo(oldcontext);
1035 elog(ERROR,
"RASTER_histogram: Invalid data type for width");
1036 SRF_RETURN_DONE(funcctx);
1040 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1043 bin_width = palloc(
sizeof(
double) * n);
1044 for (i = 0, j = 0; i < n; i++) {
1045 if (nulls[i])
continue;
1049 width = (double) DatumGetFloat4(e[i]);
1052 width = (double) DatumGetFloat8(e[i]);
1056 if (width < 0 ||
FLT_EQ(width, 0.0)) {
1057 elog(NOTICE,
"Invalid value for width (must be greater than 0). Returning NULL");
1060 PG_FREE_IF_COPY(pgraster, 0);
1061 MemoryContextSwitchTo(oldcontext);
1062 SRF_RETURN_DONE(funcctx);
1065 bin_width[j] = width;
1069 bin_width_count = j;
1078 if (!PG_ARGISNULL(6))
1079 right = PG_GETARG_BOOL(6);
1082 if (!PG_ARGISNULL(7)) min = PG_GETARG_FLOAT8(7);
1085 if (!PG_ARGISNULL(8)) max = PG_GETARG_FLOAT8(8);
1090 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1092 PG_FREE_IF_COPY(pgraster, 0);
1093 MemoryContextSwitchTo(oldcontext);
1094 SRF_RETURN_DONE(funcctx);
1101 PG_FREE_IF_COPY(pgraster, 0);
1102 if (NULL == stats || NULL == stats->
values) {
1103 elog(NOTICE,
"Cannot compute summary statistics for band at index %d", bandindex);
1104 MemoryContextSwitchTo(oldcontext);
1105 SRF_RETURN_DONE(funcctx);
1107 else if (stats->
count < 1) {
1108 elog(NOTICE,
"Cannot compute histogram for band at index %d as the band has no values", bandindex);
1109 MemoryContextSwitchTo(oldcontext);
1110 SRF_RETURN_DONE(funcctx);
1115 if (bin_width_count) pfree(bin_width);
1117 if (NULL == hist || !
count) {
1118 elog(NOTICE,
"Cannot compute histogram for band at index %d", bandindex);
1119 MemoryContextSwitchTo(oldcontext);
1120 SRF_RETURN_DONE(funcctx);
1126 funcctx->user_fctx = hist;
1129 funcctx->max_calls =
count;
1132 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1134 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1136 "function returning record called in context "
1137 "that cannot accept type record"
1142 BlessTupleDesc(tupdesc);
1143 funcctx->tuple_desc = tupdesc;
1145 MemoryContextSwitchTo(oldcontext);
1149 funcctx = SRF_PERCALL_SETUP();
1151 call_cntr = funcctx->call_cntr;
1152 max_calls = funcctx->max_calls;
1153 tupdesc = funcctx->tuple_desc;
1154 hist2 = funcctx->user_fctx;
1157 if (call_cntr < max_calls) {
1167 values[0] = Float8GetDatum(hist2[call_cntr].min);
1168 values[1] = Float8GetDatum(hist2[call_cntr].max);
1169 values[2] = Int64GetDatum(hist2[call_cntr].
count);
1170 values[3] = Float8GetDatum(hist2[call_cntr].percent);
1173 tuple = heap_form_tuple(tupdesc, values, nulls);
1176 result = HeapTupleGetDatum(tuple);
1178 SRF_RETURN_NEXT(funcctx, result);
1183 SRF_RETURN_DONE(funcctx);
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);
1713 #undef VALUES_LENGTH
1714 #define VALUES_LENGTH 2
1722 FuncCallContext *funcctx;
1732 if (SRF_IS_FIRSTCALL()) {
1733 MemoryContext oldcontext;
1738 int32_t bandindex = 0;
1740 bool exclude_nodata_value =
TRUE;
1742 double *quantiles = NULL;
1744 double quantile = 0;
1760 funcctx = SRF_FIRSTCALL_INIT();
1763 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1766 if (PG_ARGISNULL(0)) {
1767 MemoryContextSwitchTo(oldcontext);
1768 SRF_RETURN_DONE(funcctx);
1770 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1774 PG_FREE_IF_COPY(pgraster, 0);
1775 MemoryContextSwitchTo(oldcontext);
1776 elog(ERROR,
"RASTER_quantile: Cannot deserialize raster");
1777 SRF_RETURN_DONE(funcctx);
1781 bandindex = PG_GETARG_INT32(1);
1783 if (bandindex < 1 || bandindex > num_bands) {
1784 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1786 PG_FREE_IF_COPY(pgraster, 0);
1787 MemoryContextSwitchTo(oldcontext);
1788 SRF_RETURN_DONE(funcctx);
1792 if (!PG_ARGISNULL(2))
1793 exclude_nodata_value = PG_GETARG_BOOL(2);
1796 if (!PG_ARGISNULL(3)) {
1797 sample = PG_GETARG_FLOAT8(3);
1798 if (sample < 0 || sample > 1) {
1799 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
1801 PG_FREE_IF_COPY(pgraster, 0);
1802 MemoryContextSwitchTo(oldcontext);
1803 SRF_RETURN_DONE(funcctx);
1805 else if (
FLT_EQ(sample, 0.0))
1812 if (!PG_ARGISNULL(4)) {
1813 array = PG_GETARG_ARRAYTYPE_P(4);
1814 etype = ARR_ELEMTYPE(array);
1815 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1823 PG_FREE_IF_COPY(pgraster, 0);
1824 MemoryContextSwitchTo(oldcontext);
1825 elog(ERROR,
"RASTER_quantile: Invalid data type for quantiles");
1826 SRF_RETURN_DONE(funcctx);
1830 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1833 quantiles = palloc(
sizeof(
double) * n);
1834 for (i = 0, j = 0; i < n; i++) {
1835 if (nulls[i])
continue;
1839 quantile = (double) DatumGetFloat4(e[i]);
1842 quantile = (double) DatumGetFloat8(e[i]);
1846 if (quantile < 0 || quantile > 1) {
1847 elog(NOTICE,
"Invalid value for quantile (must be between 0 and 1). Returning NULL");
1850 PG_FREE_IF_COPY(pgraster, 0);
1851 MemoryContextSwitchTo(oldcontext);
1852 SRF_RETURN_DONE(funcctx);
1855 quantiles[j] = quantile;
1859 quantiles_count = j;
1870 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1872 PG_FREE_IF_COPY(pgraster, 0);
1873 MemoryContextSwitchTo(oldcontext);
1874 SRF_RETURN_DONE(funcctx);
1881 PG_FREE_IF_COPY(pgraster, 0);
1882 if (NULL == stats || NULL == stats->
values) {
1883 elog(NOTICE,
"Cannot retrieve summary statistics for band at index %d", bandindex);
1884 MemoryContextSwitchTo(oldcontext);
1885 SRF_RETURN_DONE(funcctx);
1887 else if (stats->
count < 1) {
1888 elog(NOTICE,
"Cannot compute quantiles for band at index %d as the band has no values", bandindex);
1889 MemoryContextSwitchTo(oldcontext);
1890 SRF_RETURN_DONE(funcctx);
1895 if (quantiles_count) pfree(quantiles);
1897 if (NULL == quant || !
count) {
1898 elog(NOTICE,
"Cannot compute quantiles for band at index %d", bandindex);
1899 MemoryContextSwitchTo(oldcontext);
1900 SRF_RETURN_DONE(funcctx);
1906 funcctx->user_fctx = quant;
1909 funcctx->max_calls =
count;
1912 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1914 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1916 "function returning record called in context "
1917 "that cannot accept type record"
1922 BlessTupleDesc(tupdesc);
1923 funcctx->tuple_desc = tupdesc;
1925 MemoryContextSwitchTo(oldcontext);
1929 funcctx = SRF_PERCALL_SETUP();
1931 call_cntr = funcctx->call_cntr;
1932 max_calls = funcctx->max_calls;
1933 tupdesc = funcctx->tuple_desc;
1934 quant2 = funcctx->user_fctx;
1937 if (call_cntr < max_calls) {
1947 values[0] = Float8GetDatum(quant2[call_cntr].quantile);
1948 values[1] = Float8GetDatum(quant2[call_cntr].
value);
1951 tuple = heap_form_tuple(tupdesc, values, nulls);
1954 result = HeapTupleGetDatum(tuple);
1956 SRF_RETURN_NEXT(funcctx, result);
1961 SRF_RETURN_DONE(funcctx);
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);
2395 #undef VALUES_LENGTH
2396 #define VALUES_LENGTH 3
2401 FuncCallContext *funcctx;
2411 if (SRF_IS_FIRSTCALL()) {
2412 MemoryContext oldcontext;
2417 int32_t bandindex = 0;
2419 bool exclude_nodata_value =
TRUE;
2420 double *search_values = NULL;
2437 funcctx = SRF_FIRSTCALL_INIT();
2440 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2443 if (PG_ARGISNULL(0)) {
2444 MemoryContextSwitchTo(oldcontext);
2445 SRF_RETURN_DONE(funcctx);
2447 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
2451 PG_FREE_IF_COPY(pgraster, 0);
2452 MemoryContextSwitchTo(oldcontext);
2453 elog(ERROR,
"RASTER_valueCount: Cannot deserialize raster");
2454 SRF_RETURN_DONE(funcctx);
2458 bandindex = PG_GETARG_INT32(1);
2460 if (bandindex < 1 || bandindex > num_bands) {
2461 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2463 PG_FREE_IF_COPY(pgraster, 0);
2464 MemoryContextSwitchTo(oldcontext);
2465 SRF_RETURN_DONE(funcctx);
2469 if (!PG_ARGISNULL(2))
2470 exclude_nodata_value = PG_GETARG_BOOL(2);
2473 if (!PG_ARGISNULL(3)) {
2474 array = PG_GETARG_ARRAYTYPE_P(3);
2475 etype = ARR_ELEMTYPE(array);
2476 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2484 PG_FREE_IF_COPY(pgraster, 0);
2485 MemoryContextSwitchTo(oldcontext);
2486 elog(ERROR,
"RASTER_valueCount: Invalid data type for values");
2487 SRF_RETURN_DONE(funcctx);
2491 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2494 search_values = palloc(
sizeof(
double) * n);
2495 for (i = 0, j = 0; i < n; i++) {
2496 if (nulls[i])
continue;
2500 search_values[j] = (double) DatumGetFloat4(e[i]);
2503 search_values[j] = (double) DatumGetFloat8(e[i]);
2510 search_values_count = j;
2513 pfree(search_values);
2514 search_values = NULL;
2519 if (!PG_ARGISNULL(4)) {
2520 roundto = PG_GETARG_FLOAT8(4);
2521 if (roundto < 0.) roundto = 0;
2527 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
2529 PG_FREE_IF_COPY(pgraster, 0);
2530 MemoryContextSwitchTo(oldcontext);
2531 SRF_RETURN_DONE(funcctx);
2538 PG_FREE_IF_COPY(pgraster, 0);
2539 if (NULL == vcnts || !
count) {
2540 elog(NOTICE,
"Cannot count the values for band at index %d", bandindex);
2541 MemoryContextSwitchTo(oldcontext);
2542 SRF_RETURN_DONE(funcctx);
2548 funcctx->user_fctx = vcnts;
2551 funcctx->max_calls =
count;
2554 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2556 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2558 "function returning record called in context "
2559 "that cannot accept type record"
2564 BlessTupleDesc(tupdesc);
2565 funcctx->tuple_desc = tupdesc;
2567 MemoryContextSwitchTo(oldcontext);
2571 funcctx = SRF_PERCALL_SETUP();
2573 call_cntr = funcctx->call_cntr;
2574 max_calls = funcctx->max_calls;
2575 tupdesc = funcctx->tuple_desc;
2576 vcnts2 = funcctx->user_fctx;
2579 if (call_cntr < max_calls) {
2589 values[0] = Float8GetDatum(vcnts2[call_cntr].
value);
2590 values[1] = UInt32GetDatum(vcnts2[call_cntr].
count);
2591 values[2] = Float8GetDatum(vcnts2[call_cntr].percent);
2594 tuple = heap_form_tuple(tupdesc, values, nulls);
2597 result = HeapTupleGetDatum(tuple);
2599 SRF_RETURN_NEXT(funcctx, result);
2604 SRF_RETURN_DONE(funcctx);
2611 FuncCallContext *funcctx;
2615 uint64_t covcount = 0;
2616 uint64_t covtotal = 0;
2625 if (SRF_IS_FIRSTCALL()) {
2626 MemoryContext oldcontext;
2628 text *tablenametext = NULL;
2629 char *tablename = NULL;
2630 text *colnametext = NULL;
2631 char *colname = NULL;
2632 int32_t bandindex = 1;
2633 bool exclude_nodata_value =
TRUE;
2634 double *search_values = NULL;
2644 bool isNull =
FALSE;
2666 funcctx = SRF_FIRSTCALL_INIT();
2669 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2672 if (PG_ARGISNULL(0)) {
2673 elog(NOTICE,
"Table name must be provided");
2674 MemoryContextSwitchTo(oldcontext);
2675 SRF_RETURN_DONE(funcctx);
2677 tablenametext = PG_GETARG_TEXT_P(0);
2679 if (!strlen(tablename)) {
2680 elog(NOTICE,
"Table name must be provided");
2681 MemoryContextSwitchTo(oldcontext);
2682 SRF_RETURN_DONE(funcctx);
2687 if (PG_ARGISNULL(1)) {
2688 elog(NOTICE,
"Column name must be provided");
2689 MemoryContextSwitchTo(oldcontext);
2690 SRF_RETURN_DONE(funcctx);
2692 colnametext = PG_GETARG_TEXT_P(1);
2694 if (!strlen(colname)) {
2695 elog(NOTICE,
"Column name must be provided");
2696 MemoryContextSwitchTo(oldcontext);
2697 SRF_RETURN_DONE(funcctx);
2702 if (!PG_ARGISNULL(2))
2703 bandindex = PG_GETARG_INT32(2);
2706 if (!PG_ARGISNULL(3))
2707 exclude_nodata_value = PG_GETARG_BOOL(3);
2710 if (!PG_ARGISNULL(4)) {
2711 array = PG_GETARG_ARRAYTYPE_P(4);
2712 etype = ARR_ELEMTYPE(array);
2713 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2720 MemoryContextSwitchTo(oldcontext);
2721 elog(ERROR,
"RASTER_valueCountCoverage: Invalid data type for values");
2722 SRF_RETURN_DONE(funcctx);
2726 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2729 search_values = palloc(
sizeof(
double) * n);
2730 for (i = 0, j = 0; i < (
uint32_t) n; i++) {
2731 if (nulls[i])
continue;
2735 search_values[j] = (double) DatumGetFloat4(e[i]);
2738 search_values[j] = (double) DatumGetFloat8(e[i]);
2745 search_values_count = j;
2748 pfree(search_values);
2749 search_values = NULL;
2754 if (!PG_ARGISNULL(5)) {
2755 roundto = PG_GETARG_FLOAT8(5);
2756 if (roundto < 0.) roundto = 0;
2761 spi_result = SPI_connect();
2762 if (spi_result != SPI_OK_CONNECT) {
2764 if (search_values_count) pfree(search_values);
2766 MemoryContextSwitchTo(oldcontext);
2767 elog(ERROR,
"RASTER_valueCountCoverage: Cannot connect to database using SPI");
2768 SRF_RETURN_DONE(funcctx);
2772 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
2773 sql = (
char *) palloc(len);
2776 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
2779 if (search_values_count) pfree(search_values);
2781 MemoryContextSwitchTo(oldcontext);
2782 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for sql");
2783 SRF_RETURN_DONE(funcctx);
2787 snprintf(
sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
2789 portal = SPI_cursor_open_with_args(
2799 SPI_cursor_fetch(portal,
TRUE, 1);
2800 while (SPI_processed == 1 && SPI_tuptable != NULL) {
2801 tupdesc = SPI_tuptable->tupdesc;
2802 tuple = SPI_tuptable->vals[0];
2804 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
2805 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
2807 SPI_freetuptable(SPI_tuptable);
2808 SPI_cursor_close(portal);
2811 if (NULL != covvcnts) pfree(covvcnts);
2812 if (search_values_count) pfree(search_values);
2814 MemoryContextSwitchTo(oldcontext);
2815 elog(ERROR,
"RASTER_valueCountCoverage: Cannot get raster of coverage");
2816 SRF_RETURN_DONE(funcctx);
2819 SPI_cursor_fetch(portal,
TRUE, 1);
2823 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
2828 SPI_freetuptable(SPI_tuptable);
2829 SPI_cursor_close(portal);
2832 if (NULL != covvcnts) pfree(covvcnts);
2833 if (search_values_count) pfree(search_values);
2835 MemoryContextSwitchTo(oldcontext);
2836 elog(ERROR,
"RASTER_valueCountCoverage: Cannot deserialize raster");
2837 SRF_RETURN_DONE(funcctx);
2842 if (bandindex < 1 || bandindex > num_bands) {
2843 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2847 SPI_freetuptable(SPI_tuptable);
2848 SPI_cursor_close(portal);
2851 if (NULL != covvcnts) pfree(covvcnts);
2852 if (search_values_count) pfree(search_values);
2854 MemoryContextSwitchTo(oldcontext);
2855 SRF_RETURN_DONE(funcctx);
2861 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
2865 SPI_freetuptable(SPI_tuptable);
2866 SPI_cursor_close(portal);
2869 if (NULL != covvcnts) pfree(covvcnts);
2870 if (search_values_count) pfree(search_values);
2872 MemoryContextSwitchTo(oldcontext);
2873 SRF_RETURN_DONE(funcctx);
2880 if (NULL == vcnts || !
count) {
2881 elog(NOTICE,
"Cannot count the values for band at index %d", bandindex);
2883 SPI_freetuptable(SPI_tuptable);
2884 SPI_cursor_close(portal);
2887 if (NULL != covvcnts)
free(covvcnts);
2888 if (search_values_count) pfree(search_values);
2890 MemoryContextSwitchTo(oldcontext);
2891 SRF_RETURN_DONE(funcctx);
2896 if (NULL == covvcnts) {
2898 if (NULL == covvcnts) {
2900 SPI_freetuptable(SPI_tuptable);
2901 SPI_cursor_close(portal);
2904 if (search_values_count) pfree(search_values);
2906 MemoryContextSwitchTo(oldcontext);
2907 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for value counts of coverage");
2908 SRF_RETURN_DONE(funcctx);
2911 for (i = 0; i <
count; i++) {
2920 for (i = 0; i <
count; i++) {
2923 for (j = 0; j < covcount; j++) {
2935 covvcnts = SPI_repalloc(covvcnts,
sizeof(
struct rt_valuecount_t) * covcount);
2937 SPI_freetuptable(SPI_tuptable);
2938 SPI_cursor_close(portal);
2941 if (search_values_count) pfree(search_values);
2943 MemoryContextSwitchTo(oldcontext);
2944 elog(ERROR,
"RASTER_valueCountCoverage: Cannot change allocated memory for value counts of coverage");
2945 SRF_RETURN_DONE(funcctx);
2948 covvcnts[covcount - 1].
value = vcnts[i].
value;
2949 covvcnts[covcount - 1].
count = vcnts[i].
count;
2950 covvcnts[covcount - 1].
percent = -1;
2960 SPI_cursor_fetch(portal,
TRUE, 1);
2963 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
2964 SPI_cursor_close(portal);
2967 if (search_values_count) pfree(search_values);
2970 for (i = 0; i < covcount; i++) {
2971 covvcnts[i].
percent = (double) covvcnts[i].
count / covtotal;
2975 funcctx->user_fctx = covvcnts;
2978 funcctx->max_calls = covcount;
2981 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2983 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2985 "function returning record called in context "
2986 "that cannot accept type record"
2991 BlessTupleDesc(tupdesc);
2992 funcctx->tuple_desc = tupdesc;
2994 MemoryContextSwitchTo(oldcontext);
2998 funcctx = SRF_PERCALL_SETUP();
3000 call_cntr = funcctx->call_cntr;
3001 max_calls = funcctx->max_calls;
3002 tupdesc = funcctx->tuple_desc;
3003 covvcnts2 = funcctx->user_fctx;
3006 if (call_cntr < max_calls) {
3016 values[0] = Float8GetDatum(covvcnts2[call_cntr].
value);
3017 values[1] = UInt32GetDatum(covvcnts2[call_cntr].
count);
3018 values[2] = Float8GetDatum(covvcnts2[call_cntr].percent);
3021 tuple = heap_form_tuple(tupdesc, values, nulls);
3024 result = HeapTupleGetDatum(tuple);
3026 SRF_RETURN_NEXT(funcctx, result);
3031 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.
struct rt_bandstats_t * rt_bandstats
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)
struct rt_valuecount_t * rt_valuecount
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_valuecount rt_band_get_value_count(rt_band band, int exclude_nodata_value, double *search_values, uint32_t search_values_count, double roundto, uint32_t *rtn_total, uint32_t *rtn_count)
Count the number of times provided value(s) occur in the band.
rt_quantile rt_band_get_quantiles(rt_bandstats stats, double *quantiles, int quantiles_count, uint32_t *rtn_count)
Compute the default set of or requested quantiles for a set of data the quantile formula used is same...
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)
Datum RASTER_summaryStats(PG_FUNCTION_ARGS)
Datum RASTER_summaryStatsCoverage(PG_FUNCTION_ARGS)
struct rtpg_summarystats_arg_t * rtpg_summarystats_arg
Datum RASTER_histogram(PG_FUNCTION_ARGS)
static void rtpg_summarystats_arg_destroy(rtpg_summarystats_arg arg)
Datum RASTER_histogramCoverage(PG_FUNCTION_ARGS)
Datum RASTER_valueCountCoverage(PG_FUNCTION_ARGS)
Datum RASTER_valueCount(PG_FUNCTION_ARGS)
Datum RASTER_quantileCoverage(PG_FUNCTION_ARGS)
static rtpg_summarystats_arg rtpg_summarystats_arg_init()
Datum RASTER_summaryStats_transfn(PG_FUNCTION_ARGS)
Datum RASTER_quantile(PG_FUNCTION_ARGS)
Datum RASTER_summaryStats_finalfn(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(RASTER_summaryStats)
Get summary stats of a band.
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)
bool exclude_nodata_value