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);
238 tablename = text_to_cstring(tablenametext);
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);
250 colname = text_to_cstring(colnametext);
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 tuptable = SPI_tuptable;
313 tuple = tuptable->vals[0];
315 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
316 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
318 if (SPI_tuptable) SPI_freetuptable(tuptable);
319 SPI_cursor_close(portal);
322 if (NULL != rtn) pfree(rtn);
323 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot get raster of coverage");
327 SPI_cursor_fetch(portal,
TRUE, 1);
331 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
336 if (SPI_tuptable) SPI_freetuptable(tuptable);
337 SPI_cursor_close(portal);
340 if (NULL != rtn) pfree(rtn);
341 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot deserialize raster");
347 if (bandindex < 1 || bandindex > num_bands) {
348 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
352 if (SPI_tuptable) SPI_freetuptable(tuptable);
353 SPI_cursor_close(portal);
356 if (NULL != rtn) pfree(rtn);
363 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
367 if (SPI_tuptable) SPI_freetuptable(tuptable);
368 SPI_cursor_close(portal);
371 if (NULL != rtn) pfree(rtn);
382 elog(NOTICE,
"Cannot compute summary statistics for band at index %d. Returning NULL", bandindex);
384 if (SPI_tuptable) SPI_freetuptable(tuptable);
385 SPI_cursor_close(portal);
388 if (NULL != rtn) pfree(rtn);
393 if (stats->
count > 0) {
398 if (SPI_tuptable) SPI_freetuptable(tuptable);
399 SPI_cursor_close(portal);
402 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot allocate memory for summary stats of coverage");
421 if (stats->
min < rtn->
min)
423 if (stats->
max > rtn->
max)
431 SPI_cursor_fetch(portal,
TRUE, 1);
434 if (SPI_tuptable) SPI_freetuptable(tuptable);
435 SPI_cursor_close(portal);
439 elog(ERROR,
"RASTER_summaryStatsCoverage: Cannot compute coverage summary stats");
453 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
455 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
457 "function returning record called in context " 458 "that cannot accept type record" 463 BlessTupleDesc(tupdesc);
467 values[0] = Int64GetDatum(rtn->
count);
468 if (rtn->
count > 0) {
469 values[1] = Float8GetDatum(rtn->
sum);
470 values[2] = Float8GetDatum(rtn->
mean);
471 values[3] = Float8GetDatum(rtn->
stddev);
472 values[4] = Float8GetDatum(rtn->
min);
473 values[5] = Float8GetDatum(rtn->
max);
484 tuple = heap_form_tuple(tupdesc, values, nulls);
487 result = HeapTupleGetDatum(tuple);
492 PG_RETURN_DATUM(result);
515 if (arg->
stats != NULL)
521 static rtpg_summarystats_arg
523 rtpg_summarystats_arg arg = NULL;
529 "rtpg_summarystats_arg_init: Cannot allocate memory for function arguments" 535 if (arg->
stats == NULL) {
539 "rtpg_summarystats_arg_init: Cannot allocate memory for stats function argument" 568 MemoryContext aggcontext;
569 MemoryContext oldcontext;
570 rtpg_summarystats_arg state = NULL;
571 bool skiparg =
FALSE;
584 if (!AggCheckCallContext(fcinfo, &aggcontext)) {
587 "RASTER_summaryStats_transfn: Cannot be called in a non-aggregate context" 593 oldcontext = MemoryContextSwitchTo(aggcontext);
595 if (PG_ARGISNULL(0)) {
600 MemoryContextSwitchTo(oldcontext);
603 "RASTER_summaryStats_transfn: Cannot allocate memory for state variable" 617 if (!PG_ARGISNULL(1)) {
619 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
623 if (raster == NULL) {
626 PG_FREE_IF_COPY(pgraster, 1);
628 MemoryContextSwitchTo(oldcontext);
629 elog(ERROR,
"RASTER_summaryStats_transfn: Cannot deserialize raster");
645 for (i = 2; i < nargs; i++) {
649 calltype = get_fn_expr_argtype(fcinfo->flinfo, i);
653 (calltype == INT2OID || calltype == INT4OID) &&
656 if (calltype == INT2OID)
665 if (raster != NULL) {
667 PG_FREE_IF_COPY(pgraster, 1);
670 MemoryContextSwitchTo(oldcontext);
673 "RASTER_summaryStats_transfn: Invalid band index (must use 1-based). Returning NULL" 680 calltype == BOOLOID && (
688 (calltype == FLOAT4OID || calltype == FLOAT8OID) &&
691 if (calltype == FLOAT4OID)
692 state->
sample = PG_GETARG_FLOAT4(i);
694 state->
sample = PG_GETARG_FLOAT8(i);
700 if (raster != NULL) {
702 PG_FREE_IF_COPY(pgraster, 1);
705 MemoryContextSwitchTo(oldcontext);
708 "Invalid sample percentage (must be between 0 and 1). Returning NULL" 719 if (raster != NULL) {
721 PG_FREE_IF_COPY(pgraster, 1);
724 MemoryContextSwitchTo(oldcontext);
727 "RASTER_summaryStats_transfn: Unknown function parameter at index %d",
737 if (PG_ARGISNULL(1)) {
739 MemoryContextSwitchTo(oldcontext);
740 PG_RETURN_POINTER(state);
748 "Raster does not have band at index %d. Skipping raster",
753 PG_FREE_IF_COPY(pgraster, 1);
755 MemoryContextSwitchTo(oldcontext);
756 PG_RETURN_POINTER(state);
763 NOTICE,
"Cannot find band at index %d. Skipping raster",
768 PG_FREE_IF_COPY(pgraster, 1);
770 MemoryContextSwitchTo(oldcontext);
771 PG_RETURN_POINTER(state);
778 &(state->
cK), &(state->
cM), &(state->
cQ)
783 PG_FREE_IF_COPY(pgraster, 1);
788 "Cannot compute summary statistics for band at index %d. Returning NULL",
794 MemoryContextSwitchTo(oldcontext);
798 if (stats->
count > 0) {
822 MemoryContextSwitchTo(oldcontext);
826 PG_RETURN_POINTER(state);
832 rtpg_summarystats_arg state = NULL;
843 if (!AggCheckCallContext(fcinfo, NULL)) {
844 elog(ERROR,
"RASTER_summaryStats_finalfn: Cannot be called in a non-aggregate context");
855 elog(ERROR,
"RASTER_summaryStats_finalfn: Cannot compute coverage summary stats");
871 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
874 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
876 "function returning record called in context " 877 "that cannot accept type record" 882 BlessTupleDesc(tupdesc);
886 values[0] = Int64GetDatum(state->
stats->
count);
888 values[1] = Float8GetDatum(state->
stats->
sum);
889 values[2] = Float8GetDatum(state->
stats->
mean);
891 values[4] = Float8GetDatum(state->
stats->
min);
892 values[5] = Float8GetDatum(state->
stats->
max);
903 tuple = heap_form_tuple(tupdesc, values, nulls);
906 result = HeapTupleGetDatum(tuple);
911 PG_RETURN_DATUM(result);
915 #define VALUES_LENGTH 4 923 FuncCallContext *funcctx;
933 if (SRF_IS_FIRSTCALL()) {
934 MemoryContext oldcontext;
939 int32_t bandindex = 1;
944 double *bin_width = NULL;
967 funcctx = SRF_FIRSTCALL_INIT();
970 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
973 if (PG_ARGISNULL(0)) {
974 MemoryContextSwitchTo(oldcontext);
975 SRF_RETURN_DONE(funcctx);
977 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
981 PG_FREE_IF_COPY(pgraster, 0);
982 MemoryContextSwitchTo(oldcontext);
983 elog(ERROR,
"RASTER_histogram: Cannot deserialize raster");
984 SRF_RETURN_DONE(funcctx);
988 if (!PG_ARGISNULL(1))
989 bandindex = PG_GETARG_INT32(1);
991 if (bandindex < 1 || bandindex > num_bands) {
992 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
994 PG_FREE_IF_COPY(pgraster, 0);
995 MemoryContextSwitchTo(oldcontext);
996 SRF_RETURN_DONE(funcctx);
1000 if (!PG_ARGISNULL(2))
1001 exclude_nodata_value = PG_GETARG_BOOL(2);
1004 if (!PG_ARGISNULL(3)) {
1005 sample = PG_GETARG_FLOAT8(3);
1006 if (sample < 0 || sample > 1) {
1007 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
1009 PG_FREE_IF_COPY(pgraster, 0);
1010 MemoryContextSwitchTo(oldcontext);
1011 SRF_RETURN_DONE(funcctx);
1013 else if (
FLT_EQ(sample, 0.0))
1020 if (!PG_ARGISNULL(4)) {
1021 bin_count = PG_GETARG_INT32(4);
1022 if (bin_count < 1) bin_count = 0;
1026 if (!PG_ARGISNULL(5)) {
1027 array = PG_GETARG_ARRAYTYPE_P(5);
1028 etype = ARR_ELEMTYPE(array);
1029 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1037 PG_FREE_IF_COPY(pgraster, 0);
1038 MemoryContextSwitchTo(oldcontext);
1039 elog(ERROR,
"RASTER_histogram: Invalid data type for width");
1040 SRF_RETURN_DONE(funcctx);
1044 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1047 bin_width = palloc(
sizeof(
double) * n);
1048 for (i = 0, j = 0; i < n; i++) {
1049 if (nulls[i])
continue;
1053 width = (double) DatumGetFloat4(e[i]);
1056 width = (double) DatumGetFloat8(e[i]);
1060 if (width < 0 ||
FLT_EQ(width, 0.0)) {
1061 elog(NOTICE,
"Invalid value for width (must be greater than 0). Returning NULL");
1064 PG_FREE_IF_COPY(pgraster, 0);
1065 MemoryContextSwitchTo(oldcontext);
1066 SRF_RETURN_DONE(funcctx);
1069 bin_width[j] = width;
1073 bin_width_count = j;
1082 if (!PG_ARGISNULL(6))
1083 right = PG_GETARG_BOOL(6);
1086 if (!PG_ARGISNULL(7)) min = PG_GETARG_FLOAT8(7);
1089 if (!PG_ARGISNULL(8)) max = PG_GETARG_FLOAT8(8);
1094 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1096 PG_FREE_IF_COPY(pgraster, 0);
1097 MemoryContextSwitchTo(oldcontext);
1098 SRF_RETURN_DONE(funcctx);
1105 PG_FREE_IF_COPY(pgraster, 0);
1106 if (NULL == stats || NULL == stats->
values) {
1107 elog(NOTICE,
"Cannot compute summary statistics for band at index %d", bandindex);
1108 MemoryContextSwitchTo(oldcontext);
1109 SRF_RETURN_DONE(funcctx);
1111 else if (stats->
count < 1) {
1112 elog(NOTICE,
"Cannot compute histogram for band at index %d as the band has no values", bandindex);
1113 MemoryContextSwitchTo(oldcontext);
1114 SRF_RETURN_DONE(funcctx);
1118 hist =
rt_band_get_histogram(stats, bin_count, bin_width, bin_width_count, right, min, max, &count);
1119 if (bin_width_count) pfree(bin_width);
1121 if (NULL == hist || !count) {
1122 elog(NOTICE,
"Cannot compute histogram for band at index %d", bandindex);
1123 MemoryContextSwitchTo(oldcontext);
1124 SRF_RETURN_DONE(funcctx);
1130 funcctx->user_fctx = hist;
1133 funcctx->max_calls =
count;
1136 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1138 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1140 "function returning record called in context " 1141 "that cannot accept type record" 1146 BlessTupleDesc(tupdesc);
1147 funcctx->tuple_desc = tupdesc;
1149 MemoryContextSwitchTo(oldcontext);
1153 funcctx = SRF_PERCALL_SETUP();
1155 call_cntr = funcctx->call_cntr;
1156 max_calls = funcctx->max_calls;
1157 tupdesc = funcctx->tuple_desc;
1158 hist2 = funcctx->user_fctx;
1161 if (call_cntr < max_calls) {
1171 values[0] = Float8GetDatum(hist2[call_cntr].min);
1172 values[1] = Float8GetDatum(hist2[call_cntr].max);
1173 values[2] = Int64GetDatum(hist2[call_cntr].
count);
1174 values[3] = Float8GetDatum(hist2[call_cntr].percent);
1177 tuple = heap_form_tuple(tupdesc, values, nulls);
1180 result = HeapTupleGetDatum(tuple);
1182 SRF_RETURN_NEXT(funcctx, result);
1187 SRF_RETURN_DONE(funcctx);
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;
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);
1721 #undef VALUES_LENGTH 1722 #define VALUES_LENGTH 2 1730 FuncCallContext *funcctx;
1740 if (SRF_IS_FIRSTCALL()) {
1741 MemoryContext oldcontext;
1746 int32_t bandindex = 0;
1750 double *quantiles = NULL;
1752 double quantile = 0;
1768 funcctx = SRF_FIRSTCALL_INIT();
1771 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1774 if (PG_ARGISNULL(0)) {
1775 MemoryContextSwitchTo(oldcontext);
1776 SRF_RETURN_DONE(funcctx);
1778 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1782 PG_FREE_IF_COPY(pgraster, 0);
1783 MemoryContextSwitchTo(oldcontext);
1784 elog(ERROR,
"RASTER_quantile: Cannot deserialize raster");
1785 SRF_RETURN_DONE(funcctx);
1789 bandindex = PG_GETARG_INT32(1);
1791 if (bandindex < 1 || bandindex > num_bands) {
1792 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1794 PG_FREE_IF_COPY(pgraster, 0);
1795 MemoryContextSwitchTo(oldcontext);
1796 SRF_RETURN_DONE(funcctx);
1800 if (!PG_ARGISNULL(2))
1801 exclude_nodata_value = PG_GETARG_BOOL(2);
1804 if (!PG_ARGISNULL(3)) {
1805 sample = PG_GETARG_FLOAT8(3);
1806 if (sample < 0 || sample > 1) {
1807 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
1809 PG_FREE_IF_COPY(pgraster, 0);
1810 MemoryContextSwitchTo(oldcontext);
1811 SRF_RETURN_DONE(funcctx);
1813 else if (
FLT_EQ(sample, 0.0))
1820 if (!PG_ARGISNULL(4)) {
1821 array = PG_GETARG_ARRAYTYPE_P(4);
1822 etype = ARR_ELEMTYPE(array);
1823 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1831 PG_FREE_IF_COPY(pgraster, 0);
1832 MemoryContextSwitchTo(oldcontext);
1833 elog(ERROR,
"RASTER_quantile: Invalid data type for quantiles");
1834 SRF_RETURN_DONE(funcctx);
1838 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1841 quantiles = palloc(
sizeof(
double) * n);
1842 for (i = 0, j = 0; i < n; i++) {
1843 if (nulls[i])
continue;
1847 quantile = (double) DatumGetFloat4(e[i]);
1850 quantile = (double) DatumGetFloat8(e[i]);
1854 if (quantile < 0 || quantile > 1) {
1855 elog(NOTICE,
"Invalid value for quantile (must be between 0 and 1). Returning NULL");
1858 PG_FREE_IF_COPY(pgraster, 0);
1859 MemoryContextSwitchTo(oldcontext);
1860 SRF_RETURN_DONE(funcctx);
1863 quantiles[j] = quantile;
1867 quantiles_count = j;
1878 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
1880 PG_FREE_IF_COPY(pgraster, 0);
1881 MemoryContextSwitchTo(oldcontext);
1882 SRF_RETURN_DONE(funcctx);
1889 PG_FREE_IF_COPY(pgraster, 0);
1890 if (NULL == stats || NULL == stats->
values) {
1891 elog(NOTICE,
"Cannot retrieve summary statistics for band at index %d", bandindex);
1892 MemoryContextSwitchTo(oldcontext);
1893 SRF_RETURN_DONE(funcctx);
1895 else if (stats->
count < 1) {
1896 elog(NOTICE,
"Cannot compute quantiles for band at index %d as the band has no values", bandindex);
1897 MemoryContextSwitchTo(oldcontext);
1898 SRF_RETURN_DONE(funcctx);
1903 if (quantiles_count) pfree(quantiles);
1905 if (NULL == quant || !count) {
1906 elog(NOTICE,
"Cannot compute quantiles for band at index %d", bandindex);
1907 MemoryContextSwitchTo(oldcontext);
1908 SRF_RETURN_DONE(funcctx);
1914 funcctx->user_fctx = quant;
1917 funcctx->max_calls =
count;
1920 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1922 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1924 "function returning record called in context " 1925 "that cannot accept type record" 1930 BlessTupleDesc(tupdesc);
1931 funcctx->tuple_desc = tupdesc;
1933 MemoryContextSwitchTo(oldcontext);
1937 funcctx = SRF_PERCALL_SETUP();
1939 call_cntr = funcctx->call_cntr;
1940 max_calls = funcctx->max_calls;
1941 tupdesc = funcctx->tuple_desc;
1942 quant2 = funcctx->user_fctx;
1945 if (call_cntr < max_calls) {
1955 values[0] = Float8GetDatum(quant2[call_cntr].quantile);
1956 values[1] = Float8GetDatum(quant2[call_cntr].
value);
1959 tuple = heap_form_tuple(tupdesc, values, nulls);
1962 result = HeapTupleGetDatum(tuple);
1964 SRF_RETURN_NEXT(funcctx, result);
1969 SRF_RETURN_DONE(funcctx);
1979 FuncCallContext *funcctx;
1991 if (SRF_IS_FIRSTCALL()) {
1992 MemoryContext oldcontext;
1994 text *tablenametext = NULL;
1995 char *tablename = NULL;
1996 text *colnametext = NULL;
1997 char *colname = NULL;
1998 int32_t bandindex = 1;
2001 double *quantiles = NULL;
2003 double quantile = 0;
2009 uint64_t cov_count = 0;
2012 SPITupleTable *tuptable = NULL;
2015 bool isNull =
FALSE;
2038 funcctx = SRF_FIRSTCALL_INIT();
2041 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2044 if (PG_ARGISNULL(0)) {
2045 elog(NOTICE,
"Table name must be provided");
2046 MemoryContextSwitchTo(oldcontext);
2047 SRF_RETURN_DONE(funcctx);
2049 tablenametext = PG_GETARG_TEXT_P(0);
2050 tablename = text_to_cstring(tablenametext);
2051 if (!strlen(tablename)) {
2052 elog(NOTICE,
"Table name must be provided");
2053 MemoryContextSwitchTo(oldcontext);
2054 SRF_RETURN_DONE(funcctx);
2059 if (PG_ARGISNULL(1)) {
2060 elog(NOTICE,
"Column name must be provided");
2061 MemoryContextSwitchTo(oldcontext);
2062 SRF_RETURN_DONE(funcctx);
2064 colnametext = PG_GETARG_TEXT_P(1);
2065 colname = text_to_cstring(colnametext);
2066 if (!strlen(colname)) {
2067 elog(NOTICE,
"Column name must be provided");
2068 MemoryContextSwitchTo(oldcontext);
2069 SRF_RETURN_DONE(funcctx);
2074 if (!PG_ARGISNULL(2))
2075 bandindex = PG_GETARG_INT32(2);
2078 if (!PG_ARGISNULL(3))
2079 exclude_nodata_value = PG_GETARG_BOOL(3);
2082 if (!PG_ARGISNULL(4)) {
2083 sample = PG_GETARG_FLOAT8(4);
2084 if (sample < 0 || sample > 1) {
2085 elog(NOTICE,
"Invalid sample percentage (must be between 0 and 1). Returning NULL");
2086 MemoryContextSwitchTo(oldcontext);
2087 SRF_RETURN_DONE(funcctx);
2089 else if (
FLT_EQ(sample, 0.0))
2096 if (!PG_ARGISNULL(5)) {
2097 array = PG_GETARG_ARRAYTYPE_P(5);
2098 etype = ARR_ELEMTYPE(array);
2099 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2106 MemoryContextSwitchTo(oldcontext);
2107 elog(ERROR,
"RASTER_quantileCoverage: Invalid data type for quantiles");
2108 SRF_RETURN_DONE(funcctx);
2112 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2115 quantiles = palloc(
sizeof(
double) * n);
2116 for (i = 0, j = 0; i < n; i++) {
2117 if (nulls[i])
continue;
2121 quantile = (double) DatumGetFloat4(e[i]);
2124 quantile = (double) DatumGetFloat8(e[i]);
2128 if (quantile < 0 || quantile > 1) {
2129 elog(NOTICE,
"Invalid value for quantile (must be between 0 and 1). Returning NULL");
2131 MemoryContextSwitchTo(oldcontext);
2132 SRF_RETURN_DONE(funcctx);
2139 quantiles_count = j;
2149 spi_result = SPI_connect();
2150 if (spi_result != SPI_OK_CONNECT) {
2151 MemoryContextSwitchTo(oldcontext);
2152 elog(ERROR,
"RASTER_quantileCoverage: Cannot connect to database using SPI");
2153 SRF_RETURN_DONE(funcctx);
2156 len =
sizeof(char) * (strlen(
"SELECT count FROM _st_summarystats('','',,::boolean,)") + strlen(tablename) + strlen(colname) + (
MAX_INT_CHARLEN * 2) +
MAX_DBL_CHARLEN + 1);
2157 sql = (
char *) palloc(len);
2160 if (SPI_tuptable) SPI_freetuptable(tuptable);
2163 MemoryContextSwitchTo(oldcontext);
2164 elog(ERROR,
"RASTER_quantileCoverage: Cannot allocate memory for sql");
2165 SRF_RETURN_DONE(funcctx);
2169 snprintf(sql, len,
"SELECT count FROM _st_summarystats('%s','%s',%d,%d::boolean,%f)", tablename, colname, bandindex, (exclude_nodata_value ? 1 : 0), sample);
2171 spi_result = SPI_execute(sql,
TRUE, 0);
2173 if (spi_result != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
2175 if (SPI_tuptable) SPI_freetuptable(tuptable);
2178 MemoryContextSwitchTo(oldcontext);
2179 elog(ERROR,
"RASTER_quantileCoverage: Cannot get summary stats of coverage");
2180 SRF_RETURN_DONE(funcctx);
2183 tupdesc = SPI_tuptable->tupdesc;
2184 tuptable = SPI_tuptable;
2185 tuple = tuptable->vals[0];
2187 tmp = SPI_getvalue(tuple, tupdesc, 1);
2188 if (NULL == tmp || !strlen(tmp)) {
2190 if (SPI_tuptable) SPI_freetuptable(tuptable);
2193 MemoryContextSwitchTo(oldcontext);
2194 elog(ERROR,
"RASTER_quantileCoverage: Cannot get summary stats of coverage");
2195 SRF_RETURN_DONE(funcctx);
2197 cov_count = strtol(tmp, NULL, 10);
2203 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
2204 sql = (
char *) palloc(len);
2207 if (SPI_tuptable) SPI_freetuptable(tuptable);
2210 MemoryContextSwitchTo(oldcontext);
2211 elog(ERROR,
"RASTER_quantileCoverage: Cannot allocate memory for sql");
2212 SRF_RETURN_DONE(funcctx);
2216 snprintf(sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
2218 portal = SPI_cursor_open_with_args(
2228 SPI_cursor_fetch(portal,
TRUE, 1);
2229 while (SPI_processed == 1 && SPI_tuptable != NULL) {
2230 if (NULL != covquant) pfree(covquant);
2232 tupdesc = SPI_tuptable->tupdesc;
2233 tuptable = SPI_tuptable;
2234 tuple = tuptable->vals[0];
2236 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
2237 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
2239 if (SPI_tuptable) SPI_freetuptable(tuptable);
2240 SPI_cursor_close(portal);
2243 MemoryContextSwitchTo(oldcontext);
2244 elog(ERROR,
"RASTER_quantileCoverage: Cannot get raster of coverage");
2245 SRF_RETURN_DONE(funcctx);
2248 SPI_cursor_fetch(portal,
TRUE, 1);
2252 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
2257 if (SPI_tuptable) SPI_freetuptable(tuptable);
2258 SPI_cursor_close(portal);
2261 MemoryContextSwitchTo(oldcontext);
2262 elog(ERROR,
"RASTER_quantileCoverage: Cannot deserialize raster");
2263 SRF_RETURN_DONE(funcctx);
2268 if (bandindex < 1 || bandindex > num_bands) {
2269 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2273 if (SPI_tuptable) SPI_freetuptable(tuptable);
2274 SPI_cursor_close(portal);
2277 MemoryContextSwitchTo(oldcontext);
2278 SRF_RETURN_DONE(funcctx);
2284 elog(NOTICE,
"Cannot find raster band of index %d. Returning NULL", bandindex);
2288 if (SPI_tuptable) SPI_freetuptable(tuptable);
2289 SPI_cursor_close(portal);
2292 MemoryContextSwitchTo(oldcontext);
2293 SRF_RETURN_DONE(funcctx);
2298 exclude_nodata_value, sample, cov_count,
2300 quantiles, quantiles_count,
2307 if (NULL == covquant || !count) {
2308 elog(NOTICE,
"Cannot compute quantiles for band at index %d", bandindex);
2310 if (SPI_tuptable) SPI_freetuptable(tuptable);
2311 SPI_cursor_close(portal);
2314 MemoryContextSwitchTo(oldcontext);
2315 SRF_RETURN_DONE(funcctx);
2319 SPI_cursor_fetch(portal,
TRUE, 1);
2322 covquant2 = SPI_palloc(
sizeof(
struct rt_quantile_t) * count);
2323 for (i = 0; i <
count; i++) {
2326 if (covquant2[i].has_value)
2330 if (NULL != covquant) pfree(covquant);
2333 if (SPI_tuptable) SPI_freetuptable(tuptable);
2334 SPI_cursor_close(portal);
2337 if (quantiles_count) pfree(quantiles);
2342 funcctx->user_fctx = covquant2;
2345 funcctx->max_calls =
count;
2348 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2350 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2352 "function returning record called in context " 2353 "that cannot accept type record" 2358 BlessTupleDesc(tupdesc);
2359 funcctx->tuple_desc = tupdesc;
2361 MemoryContextSwitchTo(oldcontext);
2365 funcctx = SRF_PERCALL_SETUP();
2367 call_cntr = funcctx->call_cntr;
2368 max_calls = funcctx->max_calls;
2369 tupdesc = funcctx->tuple_desc;
2370 covquant2 = funcctx->user_fctx;
2373 if (call_cntr < max_calls) {
2383 values[0] = Float8GetDatum(covquant2[call_cntr].
quantile);
2384 if (covquant2[call_cntr].has_value)
2385 values[1] = Float8GetDatum(covquant2[call_cntr].
value);
2390 tuple = heap_form_tuple(tupdesc, values, nulls);
2393 result = HeapTupleGetDatum(tuple);
2395 SRF_RETURN_NEXT(funcctx, result);
2401 SRF_RETURN_DONE(funcctx);
2405 #undef VALUES_LENGTH 2406 #define VALUES_LENGTH 3 2411 FuncCallContext *funcctx;
2421 if (SRF_IS_FIRSTCALL()) {
2422 MemoryContext oldcontext;
2427 int32_t bandindex = 0;
2430 double *search_values = NULL;
2447 funcctx = SRF_FIRSTCALL_INIT();
2450 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2453 if (PG_ARGISNULL(0)) {
2454 MemoryContextSwitchTo(oldcontext);
2455 SRF_RETURN_DONE(funcctx);
2457 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
2461 PG_FREE_IF_COPY(pgraster, 0);
2462 MemoryContextSwitchTo(oldcontext);
2463 elog(ERROR,
"RASTER_valueCount: Cannot deserialize raster");
2464 SRF_RETURN_DONE(funcctx);
2468 bandindex = PG_GETARG_INT32(1);
2470 if (bandindex < 1 || bandindex > num_bands) {
2471 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2473 PG_FREE_IF_COPY(pgraster, 0);
2474 MemoryContextSwitchTo(oldcontext);
2475 SRF_RETURN_DONE(funcctx);
2479 if (!PG_ARGISNULL(2))
2480 exclude_nodata_value = PG_GETARG_BOOL(2);
2483 if (!PG_ARGISNULL(3)) {
2484 array = PG_GETARG_ARRAYTYPE_P(3);
2485 etype = ARR_ELEMTYPE(array);
2486 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2494 PG_FREE_IF_COPY(pgraster, 0);
2495 MemoryContextSwitchTo(oldcontext);
2496 elog(ERROR,
"RASTER_valueCount: Invalid data type for values");
2497 SRF_RETURN_DONE(funcctx);
2501 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2504 search_values = palloc(
sizeof(
double) * n);
2505 for (i = 0, j = 0; i < n; i++) {
2506 if (nulls[i])
continue;
2510 search_values[j] = (double) DatumGetFloat4(e[i]);
2513 search_values[j] = (double) DatumGetFloat8(e[i]);
2520 search_values_count = j;
2523 pfree(search_values);
2524 search_values = NULL;
2529 if (!PG_ARGISNULL(4)) {
2530 roundto = PG_GETARG_FLOAT8(4);
2531 if (roundto < 0.) roundto = 0;
2537 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
2539 PG_FREE_IF_COPY(pgraster, 0);
2540 MemoryContextSwitchTo(oldcontext);
2541 SRF_RETURN_DONE(funcctx);
2545 vcnts =
rt_band_get_value_count(band, (
int) exclude_nodata_value, search_values, search_values_count, roundto, NULL, &count);
2548 PG_FREE_IF_COPY(pgraster, 0);
2549 if (NULL == vcnts || !count) {
2550 elog(NOTICE,
"Cannot count the values for band at index %d", bandindex);
2551 MemoryContextSwitchTo(oldcontext);
2552 SRF_RETURN_DONE(funcctx);
2558 funcctx->user_fctx = vcnts;
2561 funcctx->max_calls =
count;
2564 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2566 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2568 "function returning record called in context " 2569 "that cannot accept type record" 2574 BlessTupleDesc(tupdesc);
2575 funcctx->tuple_desc = tupdesc;
2577 MemoryContextSwitchTo(oldcontext);
2581 funcctx = SRF_PERCALL_SETUP();
2583 call_cntr = funcctx->call_cntr;
2584 max_calls = funcctx->max_calls;
2585 tupdesc = funcctx->tuple_desc;
2586 vcnts2 = funcctx->user_fctx;
2589 if (call_cntr < max_calls) {
2599 values[0] = Float8GetDatum(vcnts2[call_cntr].
value);
2600 values[1] = UInt32GetDatum(vcnts2[call_cntr].
count);
2601 values[2] = Float8GetDatum(vcnts2[call_cntr].percent);
2604 tuple = heap_form_tuple(tupdesc, values, nulls);
2607 result = HeapTupleGetDatum(tuple);
2609 SRF_RETURN_NEXT(funcctx, result);
2614 SRF_RETURN_DONE(funcctx);
2621 FuncCallContext *funcctx;
2625 uint64_t covcount = 0;
2626 uint64_t covtotal = 0;
2635 if (SRF_IS_FIRSTCALL()) {
2636 MemoryContext oldcontext;
2638 text *tablenametext = NULL;
2639 char *tablename = NULL;
2640 text *colnametext = NULL;
2641 char *colname = NULL;
2642 int32_t bandindex = 1;
2644 double *search_values = NULL;
2652 SPITupleTable *tuptable = NULL;
2655 bool isNull =
FALSE;
2677 funcctx = SRF_FIRSTCALL_INIT();
2680 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
2683 if (PG_ARGISNULL(0)) {
2684 elog(NOTICE,
"Table name must be provided");
2685 MemoryContextSwitchTo(oldcontext);
2686 SRF_RETURN_DONE(funcctx);
2688 tablenametext = PG_GETARG_TEXT_P(0);
2689 tablename = text_to_cstring(tablenametext);
2690 if (!strlen(tablename)) {
2691 elog(NOTICE,
"Table name must be provided");
2692 MemoryContextSwitchTo(oldcontext);
2693 SRF_RETURN_DONE(funcctx);
2698 if (PG_ARGISNULL(1)) {
2699 elog(NOTICE,
"Column name must be provided");
2700 MemoryContextSwitchTo(oldcontext);
2701 SRF_RETURN_DONE(funcctx);
2703 colnametext = PG_GETARG_TEXT_P(1);
2704 colname = text_to_cstring(colnametext);
2705 if (!strlen(colname)) {
2706 elog(NOTICE,
"Column name must be provided");
2707 MemoryContextSwitchTo(oldcontext);
2708 SRF_RETURN_DONE(funcctx);
2713 if (!PG_ARGISNULL(2))
2714 bandindex = PG_GETARG_INT32(2);
2717 if (!PG_ARGISNULL(3))
2718 exclude_nodata_value = PG_GETARG_BOOL(3);
2721 if (!PG_ARGISNULL(4)) {
2722 array = PG_GETARG_ARRAYTYPE_P(4);
2723 etype = ARR_ELEMTYPE(array);
2724 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
2731 MemoryContextSwitchTo(oldcontext);
2732 elog(ERROR,
"RASTER_valueCountCoverage: Invalid data type for values");
2733 SRF_RETURN_DONE(funcctx);
2737 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
2740 search_values = palloc(
sizeof(
double) * n);
2741 for (i = 0, j = 0; i < n; i++) {
2742 if (nulls[i])
continue;
2746 search_values[j] = (double) DatumGetFloat4(e[i]);
2749 search_values[j] = (double) DatumGetFloat8(e[i]);
2756 search_values_count = j;
2759 pfree(search_values);
2760 search_values = NULL;
2765 if (!PG_ARGISNULL(5)) {
2766 roundto = PG_GETARG_FLOAT8(5);
2767 if (roundto < 0.) roundto = 0;
2772 spi_result = SPI_connect();
2773 if (spi_result != SPI_OK_CONNECT) {
2775 if (search_values_count) pfree(search_values);
2777 MemoryContextSwitchTo(oldcontext);
2778 elog(ERROR,
"RASTER_valueCountCoverage: Cannot connect to database using SPI");
2779 SRF_RETURN_DONE(funcctx);
2783 len =
sizeof(char) * (strlen(
"SELECT \"\" FROM \"\" WHERE \"\" IS NOT NULL") + (strlen(colname) * 2) + strlen(tablename) + 1);
2784 sql = (
char *) palloc(len);
2787 if (SPI_tuptable) SPI_freetuptable(tuptable);
2790 if (search_values_count) pfree(search_values);
2792 MemoryContextSwitchTo(oldcontext);
2793 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for sql");
2794 SRF_RETURN_DONE(funcctx);
2798 snprintf(sql, len,
"SELECT \"%s\" FROM \"%s\" WHERE \"%s\" IS NOT NULL", colname, tablename, colname);
2800 portal = SPI_cursor_open_with_args(
2810 SPI_cursor_fetch(portal,
TRUE, 1);
2811 while (SPI_processed == 1 && SPI_tuptable != NULL) {
2812 tupdesc = SPI_tuptable->tupdesc;
2813 tuptable = SPI_tuptable;
2814 tuple = tuptable->vals[0];
2816 datum = SPI_getbinval(tuple, tupdesc, 1, &isNull);
2817 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
2819 if (SPI_tuptable) SPI_freetuptable(tuptable);
2820 SPI_cursor_close(portal);
2823 if (NULL != covvcnts) pfree(covvcnts);
2824 if (search_values_count) pfree(search_values);
2826 MemoryContextSwitchTo(oldcontext);
2827 elog(ERROR,
"RASTER_valueCountCoverage: Cannot get raster of coverage");
2828 SRF_RETURN_DONE(funcctx);
2831 SPI_cursor_fetch(portal,
TRUE, 1);
2835 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(datum);
2840 if (SPI_tuptable) SPI_freetuptable(tuptable);
2841 SPI_cursor_close(portal);
2844 if (NULL != covvcnts) pfree(covvcnts);
2845 if (search_values_count) pfree(search_values);
2847 MemoryContextSwitchTo(oldcontext);
2848 elog(ERROR,
"RASTER_valueCountCoverage: Cannot deserialize raster");
2849 SRF_RETURN_DONE(funcctx);
2854 if (bandindex < 1 || bandindex > num_bands) {
2855 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2859 if (SPI_tuptable) SPI_freetuptable(tuptable);
2860 SPI_cursor_close(portal);
2863 if (NULL != covvcnts) pfree(covvcnts);
2864 if (search_values_count) pfree(search_values);
2866 MemoryContextSwitchTo(oldcontext);
2867 SRF_RETURN_DONE(funcctx);
2873 elog(NOTICE,
"Cannot find band at index %d. Returning NULL", bandindex);
2877 if (SPI_tuptable) SPI_freetuptable(tuptable);
2878 SPI_cursor_close(portal);
2881 if (NULL != covvcnts) pfree(covvcnts);
2882 if (search_values_count) pfree(search_values);
2884 MemoryContextSwitchTo(oldcontext);
2885 SRF_RETURN_DONE(funcctx);
2889 vcnts =
rt_band_get_value_count(band, (
int) exclude_nodata_value, search_values, search_values_count, roundto, &total, &count);
2892 if (NULL == vcnts || !count) {
2893 elog(NOTICE,
"Cannot count the values for band at index %d", bandindex);
2895 if (SPI_tuptable) SPI_freetuptable(tuptable);
2896 SPI_cursor_close(portal);
2899 if (NULL != covvcnts)
free(covvcnts);
2900 if (search_values_count) pfree(search_values);
2902 MemoryContextSwitchTo(oldcontext);
2903 SRF_RETURN_DONE(funcctx);
2908 if (NULL == covvcnts) {
2910 if (NULL == covvcnts) {
2912 if (SPI_tuptable) SPI_freetuptable(tuptable);
2913 SPI_cursor_close(portal);
2916 if (search_values_count) pfree(search_values);
2918 MemoryContextSwitchTo(oldcontext);
2919 elog(ERROR,
"RASTER_valueCountCoverage: Cannot allocate memory for value counts of coverage");
2920 SRF_RETURN_DONE(funcctx);
2923 for (i = 0; i <
count; i++) {
2932 for (i = 0; i <
count; i++) {
2935 for (j = 0; j < covcount; j++) {
2947 covvcnts = SPI_repalloc(covvcnts,
sizeof(
struct rt_valuecount_t) * covcount);
2948 if (NULL == covvcnts) {
2950 if (SPI_tuptable) SPI_freetuptable(tuptable);
2951 SPI_cursor_close(portal);
2954 if (search_values_count) pfree(search_values);
2955 if (NULL != covvcnts)
free(covvcnts);
2957 MemoryContextSwitchTo(oldcontext);
2958 elog(ERROR,
"RASTER_valueCountCoverage: Cannot change allocated memory for value counts of coverage");
2959 SRF_RETURN_DONE(funcctx);
2962 covvcnts[covcount - 1].
value = vcnts[i].
value;
2963 covvcnts[covcount - 1].
count = vcnts[i].
count;
2964 covvcnts[covcount - 1].
percent = -1;
2974 SPI_cursor_fetch(portal,
TRUE, 1);
2977 if (SPI_tuptable) SPI_freetuptable(tuptable);
2978 SPI_cursor_close(portal);
2981 if (search_values_count) pfree(search_values);
2984 for (i = 0; i < covcount; i++) {
2985 covvcnts[i].
percent = (double) covvcnts[i].count / covtotal;
2989 funcctx->user_fctx = covvcnts;
2992 funcctx->max_calls = covcount;
2995 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
2997 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2999 "function returning record called in context " 3000 "that cannot accept type record" 3005 BlessTupleDesc(tupdesc);
3006 funcctx->tuple_desc = tupdesc;
3008 MemoryContextSwitchTo(oldcontext);
3012 funcctx = SRF_PERCALL_SETUP();
3014 call_cntr = funcctx->call_cntr;
3015 max_calls = funcctx->max_calls;
3016 tupdesc = funcctx->tuple_desc;
3017 covvcnts2 = funcctx->user_fctx;
3020 if (call_cntr < max_calls) {
3030 values[0] = Float8GetDatum(covvcnts2[call_cntr].
value);
3031 values[1] = UInt32GetDatum(covvcnts2[call_cntr].
count);
3032 values[2] = Float8GetDatum(covvcnts2[call_cntr].percent);
3035 tuple = heap_form_tuple(tupdesc, values, nulls);
3038 result = HeapTupleGetDatum(tuple);
3040 SRF_RETURN_NEXT(funcctx, result);
3045 SRF_RETURN_DONE(funcctx);
Datum RASTER_summaryStats(PG_FUNCTION_ARGS)
static rtpg_summarystats_arg rtpg_summarystats_arg_init()
int quantile_llist_destroy(struct quantile_llist **list, uint32_t list_count)
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): ...
Datum RASTER_valueCount(PG_FUNCTION_ARGS)
void rt_band_destroy(rt_band band)
Destroy a raster band.
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, int quantiles_count, uint32_t *rtn_count)
Compute the default set of or requested quantiles for a coverage.
struct rtpg_summarystats_arg_t * rtpg_summarystats_arg
#define POSTGIS_RT_DEBUGF(level, msg,...)
Datum RASTER_summaryStats_transfn(PG_FUNCTION_ARGS)
Datum RASTER_histogramCoverage(PG_FUNCTION_ARGS)
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_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
PG_FUNCTION_INFO_V1(RASTER_summaryStats)
Get summary stats of a band.
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
bool exclude_nodata_value
struct rt_valuecount_t * rt_valuecount
struct rt_bandstats_t * rt_bandstats
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.
Datum RASTER_summaryStats_finalfn(PG_FUNCTION_ARGS)
Datum RASTER_valueCountCoverage(PG_FUNCTION_ARGS)
static void rtpg_summarystats_arg_destroy(rtpg_summarystats_arg arg)
Datum RASTER_histogram(PG_FUNCTION_ARGS)
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.
Datum RASTER_quantile(PG_FUNCTION_ARGS)
Datum RASTER_quantileCoverage(PG_FUNCTION_ARGS)
#define POSTGIS_RT_DEBUG(level, msg)
Datum RASTER_summaryStatsCoverage(PG_FUNCTION_ARGS)
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.