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"
65 #define VALUES_LENGTH 6
76 int32_t bandindex = 1;
77 bool exclude_nodata_value =
TRUE;
91 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
95 PG_FREE_IF_COPY(pgraster, 0);
96 elog(ERROR,
"RASTER_summaryStats: Cannot deserialize raster");
101 if (!PG_ARGISNULL(1))
102 bandindex = PG_GETARG_INT32(1);
104 if (bandindex < 1 || bandindex > num_bands) {
105 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
107 PG_FREE_IF_COPY(pgraster, 0);
112 if (!PG_ARGISNULL(2))
113 exclude_nodata_value = PG_GETARG_BOOL(2);
116 if (!PG_ARGISNULL(3)) {
117 sample = PG_GETARG_FLOAT8(3);
118 if (sample < 0 || sample > 1) {
119 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
121 PG_FREE_IF_COPY(pgraster, 0);
124 else if (
FLT_EQ(sample, 0.0))
133 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
135 PG_FREE_IF_COPY(pgraster, 0);
143 PG_FREE_IF_COPY(pgraster, 0);
145 elog(NOTICE,
"Cannot compute summary statistics for band at index %d. Returning NULL", bandindex);
150 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
152 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
154 "function returning record called in context "
155 "that cannot accept type record"
160 BlessTupleDesc(tupdesc);
164 values[0] = Int64GetDatum(stats->
count);
165 if (stats->
count > 0) {
166 values[1] = Float8GetDatum(stats->
sum);
167 values[2] = Float8GetDatum(stats->
mean);
168 values[3] = Float8GetDatum(stats->
stddev);
169 values[4] = Float8GetDatum(stats->
min);
170 values[5] = Float8GetDatum(stats->
max);
181 tuple = heap_form_tuple(tupdesc, values, nulls);
184 result = HeapTupleGetDatum(tuple);
198 text *tablenametext = NULL;
199 char *tablename = NULL;
200 text *colnametext = NULL;
201 char *colname = NULL;
202 int32_t bandindex = 1;
203 bool exclude_nodata_value =
TRUE;
211 SPITupleTable *tuptable = NULL;
231 if (PG_ARGISNULL(0)) {
232 elog(NOTICE,
"Table name must be provided");
235 tablenametext = PG_GETARG_TEXT_P(0);
236 tablename = text_to_cstring(tablenametext);
237 if (!strlen(tablename)) {
238 elog(NOTICE,
"Table name must be provided");
243 if (PG_ARGISNULL(1)) {
244 elog(NOTICE,
"Column name must be provided");
247 colnametext = PG_GETARG_TEXT_P(1);
248 colname = text_to_cstring(colnametext);
249 if (!strlen(colname)) {
250 elog(NOTICE,
"Column name must be provided");
255 if (!PG_ARGISNULL(2))
256 bandindex = PG_GETARG_INT32(2);
259 if (!PG_ARGISNULL(3))
260 exclude_nodata_value = PG_GETARG_BOOL(3);
263 if (!PG_ARGISNULL(4)) {
264 sample = PG_GETARG_FLOAT8(4);
265 if (sample < 0 || sample > 1) {
266 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
270 else if (
FLT_EQ(sample, 0.0))
278 spi_result = SPI_connect();
279 if (spi_result != SPI_OK_CONNECT) {
281 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot connect to database using SPI");
286 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
287 sql = (
char *) palloc(len);
289 if (SPI_tuptable) SPI_freetuptable(tuptable);
291 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot allocate memory for sql");
296 snprintf(
sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
297 portal = SPI_cursor_open_with_args(
307 SPI_cursor_fetch(portal,
TRUE, 1);
308 while (SPI_processed == 1 && SPI_tuptable != NULL) {
309 tupdesc = SPI_tuptable->tupdesc;
310 tuple = SPI_tuptable->vals[0];
312 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
313 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
314 SPI_freetuptable(SPI_tuptable);
315 SPI_cursor_close(portal);
318 if (NULL != rtn) pfree(rtn);
319 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot get raster of coverage");
323 SPI_cursor_fetch(portal,
TRUE, 1);
327 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
331 SPI_freetuptable(SPI_tuptable);
332 SPI_cursor_close(portal);
335 if (NULL != rtn) pfree(rtn);
336 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot deserialize raster");
342 if (bandindex < 1 || bandindex > num_bands) {
343 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
347 SPI_freetuptable(SPI_tuptable);
348 SPI_cursor_close(portal);
351 if (NULL != rtn) pfree(rtn);
358 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
362 SPI_freetuptable(SPI_tuptable);
363 SPI_cursor_close(portal);
366 if (NULL != rtn) pfree(rtn);
377 elog(NOTICE,
"Cannot compute summary statistics for band at index %d. Returning NULL", bandindex);
379 SPI_freetuptable(SPI_tuptable);
380 SPI_cursor_close(portal);
383 if (NULL != rtn) pfree(rtn);
388 if (stats->
count > 0) {
392 SPI_freetuptable(SPI_tuptable);
393 SPI_cursor_close(portal);
396 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot allocate memory for summary stats of coverage");
415 if (stats->
min < rtn->
min)
417 if (stats->
max > rtn->
max)
425 SPI_cursor_fetch(portal,
TRUE, 1);
428 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
429 SPI_cursor_close(portal);
433 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot compute coverage summary stats");
447 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
449 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
451 "function returning record called in context "
452 "that cannot accept type record"
457 BlessTupleDesc(tupdesc);
461 values[0] = Int64GetDatum(rtn->
count);
462 if (rtn->
count > 0) {
463 values[1] = Float8GetDatum(rtn->
sum);
464 values[2] = Float8GetDatum(rtn->
mean);
465 values[3] = Float8GetDatum(rtn->
stddev);
466 values[4] = Float8GetDatum(rtn->
min);
467 values[5] = Float8GetDatum(rtn->
max);
478 tuple = heap_form_tuple(tupdesc, values, nulls);
481 result = HeapTupleGetDatum(tuple);
509 if (arg->
stats != NULL)
523 "rtpg_summarystats_arg_init: Cannot allocate memory for function arguments"
529 if (arg->
stats == NULL) {
533 "rtpg_summarystats_arg_init: Cannot allocate memory for stats function argument"
562 MemoryContext aggcontext;
563 MemoryContext oldcontext;
565 bool skiparg =
FALSE;
578 if (!AggCheckCallContext(fcinfo, &aggcontext)) {
581 "RASTER_summaryStats_transfn: Cannot be called in a non-aggregate context"
587 oldcontext = MemoryContextSwitchTo(aggcontext);
589 if (PG_ARGISNULL(0)) {
594 MemoryContextSwitchTo(oldcontext);
597 "RASTER_summaryStats_transfn: Cannot allocate memory for state variable"
611 if (!PG_ARGISNULL(1)) {
613 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
620 PG_FREE_IF_COPY(pgraster, 1);
622 MemoryContextSwitchTo(oldcontext);
623 elog(ERROR,
"RASTER_summaryStats_transfn: Cannot deserialize raster");
639 for (i = 2; i < nargs; i++) {
643 calltype = get_fn_expr_argtype(fcinfo->flinfo, i);
647 (calltype == INT2OID || calltype == INT4OID) &&
650 if (calltype == INT2OID)
661 PG_FREE_IF_COPY(pgraster, 1);
664 MemoryContextSwitchTo(oldcontext);
667 "RASTER_summaryStats_transfn: Invalid band index (must use 1-based). Returning NULL"
674 calltype == BOOLOID && (
682 (calltype == FLOAT4OID || calltype == FLOAT8OID) &&
685 if (calltype == FLOAT4OID)
686 state->
sample = PG_GETARG_FLOAT4(i);
688 state->
sample = PG_GETARG_FLOAT8(i);
696 PG_FREE_IF_COPY(pgraster, 1);
699 MemoryContextSwitchTo(oldcontext);
702 "Invalid sample percentage (must be between 0 and 1). Returning NULL"
715 PG_FREE_IF_COPY(pgraster, 1);
718 MemoryContextSwitchTo(oldcontext);
721 "RASTER_summaryStats_transfn: Unknown function parameter at index %d",
731 if (PG_ARGISNULL(1)) {
733 MemoryContextSwitchTo(oldcontext);
734 PG_RETURN_POINTER(state);
742 "Raster does not have band at index %d. Skipping raster",
747 PG_FREE_IF_COPY(pgraster, 1);
749 MemoryContextSwitchTo(oldcontext);
750 PG_RETURN_POINTER(state);
757 NOTICE,
"Cannot find band at index %d. Skipping raster",
762 PG_FREE_IF_COPY(pgraster, 1);
764 MemoryContextSwitchTo(oldcontext);
765 PG_RETURN_POINTER(state);
772 &(state->
cK), &(state->
cM), &(state->
cQ)
777 PG_FREE_IF_COPY(pgraster, 1);
782 "Cannot compute summary statistics for band at index %d. Returning NULL",
788 MemoryContextSwitchTo(oldcontext);
792 if (stats->
count > 0) {
816 MemoryContextSwitchTo(oldcontext);
820 PG_RETURN_POINTER(state);
837 if (!AggCheckCallContext(fcinfo, NULL)) {
838 elog(ERROR,
"RASTER_summaryStats_finalfn: Cannot be called in a non-aggregate context");
849 elog(ERROR,
"RASTER_summaryStats_finalfn: Cannot compute coverage summary stats");
865 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
868 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
870 "function returning record called in context "
871 "that cannot accept type record"
876 BlessTupleDesc(tupdesc);
880 values[0] = Int64GetDatum(state->
stats->
count);
882 values[1] = Float8GetDatum(state->
stats->
sum);
883 values[2] = Float8GetDatum(state->
stats->
mean);
885 values[4] = Float8GetDatum(state->
stats->
min);
886 values[5] = Float8GetDatum(state->
stats->
max);
897 tuple = heap_form_tuple(tupdesc, values, nulls);
900 result = HeapTupleGetDatum(tuple);
913 #define VALUES_LENGTH 4
921 FuncCallContext *funcctx;
931 if (SRF_IS_FIRSTCALL()) {
932 MemoryContext oldcontext;
937 int32_t bandindex = 1;
939 bool exclude_nodata_value =
TRUE;
941 uint32_t bin_count = 0;
942 double *bin_width = NULL;
943 uint32_t bin_width_count = 0;
965 funcctx = SRF_FIRSTCALL_INIT();
968 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
971 if (PG_ARGISNULL(0)) {
972 MemoryContextSwitchTo(oldcontext);
973 SRF_RETURN_DONE(funcctx);
975 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
979 PG_FREE_IF_COPY(pgraster, 0);
980 MemoryContextSwitchTo(oldcontext);
981 elog(ERROR,
"RASTER_histogram: Cannot deserialize raster");
982 SRF_RETURN_DONE(funcctx);
986 if (!PG_ARGISNULL(1))
987 bandindex = PG_GETARG_INT32(1);
989 if (bandindex < 1 || bandindex > num_bands) {
990 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
992 PG_FREE_IF_COPY(pgraster, 0);
993 MemoryContextSwitchTo(oldcontext);
994 SRF_RETURN_DONE(funcctx);
998 if (!PG_ARGISNULL(2))
999 exclude_nodata_value = PG_GETARG_BOOL(2);
1002 if (!PG_ARGISNULL(3)) {
1003 sample = PG_GETARG_FLOAT8(3);
1004 if (sample < 0 || sample > 1) {
1005 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
1007 PG_FREE_IF_COPY(pgraster, 0);
1008 MemoryContextSwitchTo(oldcontext);
1009 SRF_RETURN_DONE(funcctx);
1011 else if (
FLT_EQ(sample, 0.0))
1018 if (!PG_ARGISNULL(4)) {
1019 bin_count = PG_GETARG_INT32(4);
1020 if (bin_count < 1) bin_count = 0;
1024 if (!PG_ARGISNULL(5)) {
1025 array = PG_GETARG_ARRAYTYPE_P(5);
1026 etype = ARR_ELEMTYPE(array);
1027 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1035 PG_FREE_IF_COPY(pgraster, 0);
1036 MemoryContextSwitchTo(oldcontext);
1037 elog(ERROR,
"RASTER_histogram: Invalid data type for width");
1038 SRF_RETURN_DONE(funcctx);
1042 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1045 bin_width = palloc(
sizeof(
double) * n);
1046 for (i = 0, j = 0; i < n; i++) {
1047 if (nulls[i])
continue;
1051 width = (double) DatumGetFloat4(e[i]);
1054 width = (double) DatumGetFloat8(e[i]);
1058 if (width < 0 ||
FLT_EQ(width, 0.0)) {
1059 elog(NOTICE,
"Invalid value for width (must be greater than 0). Returning NULL");
1062 PG_FREE_IF_COPY(pgraster, 0);
1063 MemoryContextSwitchTo(oldcontext);
1064 SRF_RETURN_DONE(funcctx);
1067 bin_width[j] = width;
1071 bin_width_count = j;
1080 if (!PG_ARGISNULL(6))
1081 right = PG_GETARG_BOOL(6);
1084 if (!PG_ARGISNULL(7)) min = PG_GETARG_FLOAT8(7);
1087 if (!PG_ARGISNULL(8)) max = PG_GETARG_FLOAT8(8);
1092 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1094 PG_FREE_IF_COPY(pgraster, 0);
1095 MemoryContextSwitchTo(oldcontext);
1096 SRF_RETURN_DONE(funcctx);
1103 PG_FREE_IF_COPY(pgraster, 0);
1104 if (NULL == stats || NULL == stats->
values) {
1105 elog(NOTICE,
"Cannot compute summary statistics for band at index %d", bandindex);
1106 MemoryContextSwitchTo(oldcontext);
1107 SRF_RETURN_DONE(funcctx);
1109 else if (stats->
count < 1) {
1110 elog(NOTICE,
"Cannot compute histogram for band at index %d as the band has no values", bandindex);
1111 MemoryContextSwitchTo(oldcontext);
1112 SRF_RETURN_DONE(funcctx);
1117 if (bin_width_count) pfree(bin_width);
1119 if (NULL == hist || !
count) {
1120 elog(NOTICE,
"Cannot compute histogram for band at index %d", bandindex);
1121 MemoryContextSwitchTo(oldcontext);
1122 SRF_RETURN_DONE(funcctx);
1128 funcctx->user_fctx = hist;
1131 funcctx->max_calls =
count;
1134 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1136 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1138 "function returning record called in context "
1139 "that cannot accept type record"
1144 BlessTupleDesc(tupdesc);
1145 funcctx->tuple_desc = tupdesc;
1147 MemoryContextSwitchTo(oldcontext);
1151 funcctx = SRF_PERCALL_SETUP();
1153 call_cntr = funcctx->call_cntr;
1154 max_calls = funcctx->max_calls;
1155 tupdesc = funcctx->tuple_desc;
1156 hist2 = funcctx->user_fctx;
1159 if (call_cntr < max_calls) {
1169 values[0] = Float8GetDatum(hist2[call_cntr].min);
1170 values[1] = Float8GetDatum(hist2[call_cntr].max);
1171 values[2] = Int64GetDatum(hist2[call_cntr].
count);
1172 values[3] = Float8GetDatum(hist2[call_cntr].percent);
1175 tuple = heap_form_tuple(tupdesc, values, nulls);
1178 result = HeapTupleGetDatum(tuple);
1180 SRF_RETURN_NEXT(funcctx,
result);
1185 SRF_RETURN_DONE(funcctx);
1189 #undef VALUES_LENGTH
1190 #define VALUES_LENGTH 2
1198 FuncCallContext *funcctx;
1208 if (SRF_IS_FIRSTCALL()) {
1209 MemoryContext oldcontext;
1214 int32_t bandindex = 0;
1216 bool exclude_nodata_value =
TRUE;
1218 double *quantiles = NULL;
1219 uint32_t quantiles_count = 0;
1220 double quantile = 0;
1236 funcctx = SRF_FIRSTCALL_INIT();
1239 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1242 if (PG_ARGISNULL(0)) {
1243 MemoryContextSwitchTo(oldcontext);
1244 SRF_RETURN_DONE(funcctx);
1246 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1250 PG_FREE_IF_COPY(pgraster, 0);
1251 MemoryContextSwitchTo(oldcontext);
1252 elog(ERROR,
"RASTER_quantile: Cannot deserialize raster");
1253 SRF_RETURN_DONE(funcctx);
1257 bandindex = PG_GETARG_INT32(1);
1259 if (bandindex < 1 || bandindex > num_bands) {
1260 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1262 PG_FREE_IF_COPY(pgraster, 0);
1263 MemoryContextSwitchTo(oldcontext);
1264 SRF_RETURN_DONE(funcctx);
1268 if (!PG_ARGISNULL(2))
1269 exclude_nodata_value = PG_GETARG_BOOL(2);
1272 if (!PG_ARGISNULL(3)) {
1273 sample = PG_GETARG_FLOAT8(3);
1274 if (sample < 0 || sample > 1) {
1275 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
1277 PG_FREE_IF_COPY(pgraster, 0);
1278 MemoryContextSwitchTo(oldcontext);
1279 SRF_RETURN_DONE(funcctx);
1281 else if (
FLT_EQ(sample, 0.0))
1288 if (!PG_ARGISNULL(4)) {
1289 array = PG_GETARG_ARRAYTYPE_P(4);
1290 etype = ARR_ELEMTYPE(array);
1291 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1299 PG_FREE_IF_COPY(pgraster, 0);
1300 MemoryContextSwitchTo(oldcontext);
1301 elog(ERROR,
"RASTER_quantile: Invalid data type for quantiles");
1302 SRF_RETURN_DONE(funcctx);
1306 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1309 quantiles = palloc(
sizeof(
double) * n);
1310 for (i = 0, j = 0; i < n; i++) {
1311 if (nulls[i])
continue;
1315 quantile = (double) DatumGetFloat4(e[i]);
1318 quantile = (double) DatumGetFloat8(e[i]);
1322 if (quantile < 0 || quantile > 1) {
1323 elog(NOTICE,
"Invalid value for quantile (must be between 0 and 1). Returning NULL");
1326 PG_FREE_IF_COPY(pgraster, 0);
1327 MemoryContextSwitchTo(oldcontext);
1328 SRF_RETURN_DONE(funcctx);
1331 quantiles[j] = quantile;
1335 quantiles_count = j;
1346 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1348 PG_FREE_IF_COPY(pgraster, 0);
1349 MemoryContextSwitchTo(oldcontext);
1350 SRF_RETURN_DONE(funcctx);
1357 PG_FREE_IF_COPY(pgraster, 0);
1358 if (NULL == stats || NULL == stats->
values) {
1359 elog(NOTICE,
"Cannot retrieve summary statistics for band at index %d", bandindex);
1360 MemoryContextSwitchTo(oldcontext);
1361 SRF_RETURN_DONE(funcctx);
1363 else if (stats->
count < 1) {
1364 elog(NOTICE,
"Cannot compute quantiles for band at index %d as the band has no values", bandindex);
1365 MemoryContextSwitchTo(oldcontext);
1366 SRF_RETURN_DONE(funcctx);
1371 if (quantiles_count) pfree(quantiles);
1373 if (NULL == quant || !
count) {
1374 elog(NOTICE,
"Cannot compute quantiles for band at index %d", bandindex);
1375 MemoryContextSwitchTo(oldcontext);
1376 SRF_RETURN_DONE(funcctx);
1382 funcctx->user_fctx = quant;
1385 funcctx->max_calls =
count;
1388 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1390 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1392 "function returning record called in context "
1393 "that cannot accept type record"
1398 BlessTupleDesc(tupdesc);
1399 funcctx->tuple_desc = tupdesc;
1401 MemoryContextSwitchTo(oldcontext);
1405 funcctx = SRF_PERCALL_SETUP();
1407 call_cntr = funcctx->call_cntr;
1408 max_calls = funcctx->max_calls;
1409 tupdesc = funcctx->tuple_desc;
1410 quant2 = funcctx->user_fctx;
1413 if (call_cntr < max_calls) {
1423 values[0] = Float8GetDatum(quant2[call_cntr].quantile);
1424 values[1] = Float8GetDatum(quant2[call_cntr].
value);
1427 tuple = heap_form_tuple(tupdesc, values, nulls);
1430 result = HeapTupleGetDatum(tuple);
1432 SRF_RETURN_NEXT(funcctx,
result);
1437 SRF_RETURN_DONE(funcctx);
1441 #undef VALUES_LENGTH
1442 #define VALUES_LENGTH 3
1447 FuncCallContext *funcctx;
1457 if (SRF_IS_FIRSTCALL()) {
1458 MemoryContext oldcontext;
1463 int32_t bandindex = 0;
1465 bool exclude_nodata_value =
TRUE;
1466 double *search_values = NULL;
1467 uint32_t search_values_count = 0;
1483 funcctx = SRF_FIRSTCALL_INIT();
1486 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1489 if (PG_ARGISNULL(0)) {
1490 MemoryContextSwitchTo(oldcontext);
1491 SRF_RETURN_DONE(funcctx);
1493 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1497 PG_FREE_IF_COPY(pgraster, 0);
1498 MemoryContextSwitchTo(oldcontext);
1499 elog(ERROR,
"RASTER_valueCount: Cannot deserialize raster");
1500 SRF_RETURN_DONE(funcctx);
1504 bandindex = PG_GETARG_INT32(1);
1506 if (bandindex < 1 || bandindex > num_bands) {
1507 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1509 PG_FREE_IF_COPY(pgraster, 0);
1510 MemoryContextSwitchTo(oldcontext);
1511 SRF_RETURN_DONE(funcctx);
1515 if (!PG_ARGISNULL(2))
1516 exclude_nodata_value = PG_GETARG_BOOL(2);
1519 if (!PG_ARGISNULL(3)) {
1520 array = PG_GETARG_ARRAYTYPE_P(3);
1521 etype = ARR_ELEMTYPE(array);
1522 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1530 PG_FREE_IF_COPY(pgraster, 0);
1531 MemoryContextSwitchTo(oldcontext);
1532 elog(ERROR,
"RASTER_valueCount: Invalid data type for values");
1533 SRF_RETURN_DONE(funcctx);
1537 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1540 search_values = palloc(
sizeof(
double) * n);
1541 for (i = 0, j = 0; i < n; i++) {
1542 if (nulls[i])
continue;
1546 search_values[j] = (double) DatumGetFloat4(e[i]);
1549 search_values[j] = (double) DatumGetFloat8(e[i]);
1556 search_values_count = j;
1559 pfree(search_values);
1560 search_values = NULL;
1565 if (!PG_ARGISNULL(4)) {
1566 roundto = PG_GETARG_FLOAT8(4);
1567 if (roundto < 0.) roundto = 0;
1573 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1575 PG_FREE_IF_COPY(pgraster, 0);
1576 MemoryContextSwitchTo(oldcontext);
1577 SRF_RETURN_DONE(funcctx);
1584 PG_FREE_IF_COPY(pgraster, 0);
1585 if (NULL == vcnts || !
count) {
1586 elog(NOTICE,
"Cannot count the values for band at index %d", bandindex);
1587 MemoryContextSwitchTo(oldcontext);
1588 SRF_RETURN_DONE(funcctx);
1594 funcctx->user_fctx = vcnts;
1597 funcctx->max_calls =
count;
1600 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1602 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1604 "function returning record called in context "
1605 "that cannot accept type record"
1610 BlessTupleDesc(tupdesc);
1611 funcctx->tuple_desc = tupdesc;
1613 MemoryContextSwitchTo(oldcontext);
1617 funcctx = SRF_PERCALL_SETUP();
1619 call_cntr = funcctx->call_cntr;
1620 max_calls = funcctx->max_calls;
1621 tupdesc = funcctx->tuple_desc;
1622 vcnts2 = funcctx->user_fctx;
1625 if (call_cntr < max_calls) {
1635 values[0] = Float8GetDatum(vcnts2[call_cntr].
value);
1636 values[1] = UInt32GetDatum(vcnts2[call_cntr].
count);
1637 values[2] = Float8GetDatum(vcnts2[call_cntr].percent);
1640 tuple = heap_form_tuple(tupdesc, values, nulls);
1643 result = HeapTupleGetDatum(tuple);
1645 SRF_RETURN_NEXT(funcctx,
result);
1650 SRF_RETURN_DONE(funcctx);
1657 FuncCallContext *funcctx;
1661 uint64_t covcount = 0;
1662 uint64_t covtotal = 0;
1671 if (SRF_IS_FIRSTCALL()) {
1672 MemoryContext oldcontext;
1674 text *tablenametext = NULL;
1675 char *tablename = NULL;
1676 text *colnametext = NULL;
1677 char *colname = NULL;
1678 int32_t bandindex = 1;
1679 bool exclude_nodata_value =
TRUE;
1680 double *search_values = NULL;
1681 uint32_t search_values_count = 0;
1690 bool isNull =
FALSE;
1712 funcctx = SRF_FIRSTCALL_INIT();
1715 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1718 if (PG_ARGISNULL(0)) {
1719 elog(NOTICE,
"Table name must be provided");
1720 MemoryContextSwitchTo(oldcontext);
1721 SRF_RETURN_DONE(funcctx);
1723 tablenametext = PG_GETARG_TEXT_P(0);
1724 tablename = text_to_cstring(tablenametext);
1725 if (!strlen(tablename)) {
1726 elog(NOTICE,
"Table name must be provided");
1727 MemoryContextSwitchTo(oldcontext);
1728 SRF_RETURN_DONE(funcctx);
1733 if (PG_ARGISNULL(1)) {
1734 elog(NOTICE,
"Column name must be provided");
1735 MemoryContextSwitchTo(oldcontext);
1736 SRF_RETURN_DONE(funcctx);
1738 colnametext = PG_GETARG_TEXT_P(1);
1739 colname = text_to_cstring(colnametext);
1740 if (!strlen(colname)) {
1741 elog(NOTICE,
"Column name must be provided");
1742 MemoryContextSwitchTo(oldcontext);
1743 SRF_RETURN_DONE(funcctx);
1748 if (!PG_ARGISNULL(2))
1749 bandindex = PG_GETARG_INT32(2);
1752 if (!PG_ARGISNULL(3))
1753 exclude_nodata_value = PG_GETARG_BOOL(3);
1756 if (!PG_ARGISNULL(4)) {
1757 array = PG_GETARG_ARRAYTYPE_P(4);
1758 etype = ARR_ELEMTYPE(array);
1759 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1766 MemoryContextSwitchTo(oldcontext);
1767 elog(ERROR,
"RASTER_valueCountCoverage: Invalid data type for values");
1768 SRF_RETURN_DONE(funcctx);
1772 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1775 search_values = palloc(
sizeof(
double) * n);
1776 for (i = 0, j = 0; i < (uint32_t) n; i++) {
1777 if (nulls[i])
continue;
1781 search_values[j] = (double) DatumGetFloat4(e[i]);
1784 search_values[j] = (double) DatumGetFloat8(e[i]);
1791 search_values_count = j;
1794 pfree(search_values);
1795 search_values = NULL;
1800 if (!PG_ARGISNULL(5)) {
1801 roundto = PG_GETARG_FLOAT8(5);
1802 if (roundto < 0.) roundto = 0;
1807 spi_result = SPI_connect();
1808 if (spi_result != SPI_OK_CONNECT) {
1810 if (search_values_count) pfree(search_values);
1812 MemoryContextSwitchTo(oldcontext);
1813 elog(ERROR,
"RASTER_valueCountCoverage: Cannot connect to database using SPI");
1814 SRF_RETURN_DONE(funcctx);
1818 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
1819 sql = (
char *) palloc(len);
1822 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
1825 if (search_values_count) pfree(search_values);
1827 MemoryContextSwitchTo(oldcontext);
1828 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for sql");
1829 SRF_RETURN_DONE(funcctx);
1833 snprintf(
sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
1835 portal = SPI_cursor_open_with_args(
1845 SPI_cursor_fetch(portal,
TRUE, 1);
1846 while (SPI_processed == 1 && SPI_tuptable != NULL) {
1847 tupdesc = SPI_tuptable->tupdesc;
1848 tuple = SPI_tuptable->vals[0];
1850 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
1851 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1853 SPI_freetuptable(SPI_tuptable);
1854 SPI_cursor_close(portal);
1857 if (NULL != covvcnts) pfree(covvcnts);
1858 if (search_values_count) pfree(search_values);
1860 MemoryContextSwitchTo(oldcontext);
1861 elog(ERROR,
"RASTER_valueCountCoverage: Cannot get raster of coverage");
1862 SRF_RETURN_DONE(funcctx);
1865 SPI_cursor_fetch(portal,
TRUE, 1);
1869 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
1874 SPI_freetuptable(SPI_tuptable);
1875 SPI_cursor_close(portal);
1878 if (NULL != covvcnts) pfree(covvcnts);
1879 if (search_values_count) pfree(search_values);
1881 MemoryContextSwitchTo(oldcontext);
1882 elog(ERROR,
"RASTER_valueCountCoverage: Cannot deserialize raster");
1883 SRF_RETURN_DONE(funcctx);
1888 if (bandindex < 1 || bandindex > num_bands) {
1889 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1893 SPI_freetuptable(SPI_tuptable);
1894 SPI_cursor_close(portal);
1897 if (NULL != covvcnts) pfree(covvcnts);
1898 if (search_values_count) pfree(search_values);
1900 MemoryContextSwitchTo(oldcontext);
1901 SRF_RETURN_DONE(funcctx);
1907 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1911 SPI_freetuptable(SPI_tuptable);
1912 SPI_cursor_close(portal);
1915 if (NULL != covvcnts) pfree(covvcnts);
1916 if (search_values_count) pfree(search_values);
1918 MemoryContextSwitchTo(oldcontext);
1919 SRF_RETURN_DONE(funcctx);
1926 if (NULL == vcnts || !
count) {
1927 elog(NOTICE,
"Cannot count the values for band at index %d", bandindex);
1929 SPI_freetuptable(SPI_tuptable);
1930 SPI_cursor_close(portal);
1933 if (NULL != covvcnts)
free(covvcnts);
1934 if (search_values_count) pfree(search_values);
1936 MemoryContextSwitchTo(oldcontext);
1937 SRF_RETURN_DONE(funcctx);
1942 if (NULL == covvcnts) {
1944 if (NULL == covvcnts) {
1946 SPI_freetuptable(SPI_tuptable);
1947 SPI_cursor_close(portal);
1950 if (search_values_count) pfree(search_values);
1952 MemoryContextSwitchTo(oldcontext);
1953 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for value counts of coverage");
1954 SRF_RETURN_DONE(funcctx);
1957 for (i = 0; i <
count; i++) {
1966 for (i = 0; i <
count; i++) {
1969 for (j = 0; j < covcount; j++) {
1981 covvcnts = SPI_repalloc(covvcnts,
sizeof(
struct rt_valuecount_t) * covcount);
1983 SPI_freetuptable(SPI_tuptable);
1984 SPI_cursor_close(portal);
1987 if (search_values_count) pfree(search_values);
1989 MemoryContextSwitchTo(oldcontext);
1990 elog(ERROR,
"RASTER_valueCountCoverage: Cannot change allocated memory for value counts of coverage");
1991 SRF_RETURN_DONE(funcctx);
1994 covvcnts[covcount - 1].
value = vcnts[i].
value;
1995 covvcnts[covcount - 1].
count = vcnts[i].
count;
1996 covvcnts[covcount - 1].
percent = -1;
2006 SPI_cursor_fetch(portal,
TRUE, 1);
2009 if (SPI_tuptable) SPI_freetuptable(SPI_tuptable);
2010 SPI_cursor_close(portal);
2013 if (search_values_count) pfree(search_values);
2016 for (i = 0; i < covcount; i++) {
2017 covvcnts[i].
percent = (double) covvcnts[i].
count / covtotal;
2021 funcctx->user_fctx = covvcnts;
2024 funcctx->max_calls = covcount;
2027 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2029 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2031 "function returning record called in context "
2032 "that cannot accept type record"
2037 BlessTupleDesc(tupdesc);
2038 funcctx->tuple_desc = tupdesc;
2040 MemoryContextSwitchTo(oldcontext);
2044 funcctx = SRF_PERCALL_SETUP();
2046 call_cntr = funcctx->call_cntr;
2047 max_calls = funcctx->max_calls;
2048 tupdesc = funcctx->tuple_desc;
2049 covvcnts2 = funcctx->user_fctx;
2052 if (call_cntr < max_calls) {
2062 values[0] = Float8GetDatum(covvcnts2[call_cntr].
value);
2063 values[1] = UInt32GetDatum(covvcnts2[call_cntr].
count);
2064 values[2] = Float8GetDatum(covvcnts2[call_cntr].percent);
2067 tuple = heap_form_tuple(tupdesc, values, nulls);
2070 result = HeapTupleGetDatum(tuple);
2072 SRF_RETURN_NEXT(funcctx,
result);
2077 SRF_RETURN_DONE(funcctx);
char result[OUT_DOUBLE_BUFFER_SIZE]
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
struct rt_bandstats_t * rt_bandstats
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.
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): ...
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_valueCountCoverage(PG_FUNCTION_ARGS)
Datum RASTER_valueCount(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