31 #define _LARGEFILE64_SOURCE 1
36 #include <utils/builtins.h>
37 #include "utils/lsyscache.h"
38 #include "utils/array.h"
39 #include "catalog/pg_type.h"
41 #include "../../postgis_config.h"
44 #include "access/htup_details.h"
81 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
82 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
85 bandindex = PG_GETARG_INT32(1);
86 if ( bandindex < 1 ) {
87 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
88 PG_FREE_IF_COPY(pgraster, 0);
94 PG_FREE_IF_COPY(pgraster, 0);
95 elog(ERROR,
"RASTER_getBandPixelType: Could not deserialize raster");
102 elog(NOTICE,
"Could not find raster band of index %d when getting pixel type. Returning NULL", bandindex);
104 PG_FREE_IF_COPY(pgraster, 0);
111 PG_FREE_IF_COPY(pgraster, 0);
113 PG_RETURN_INT32(pixtype);
129 const size_t name_size = 8;
135 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
136 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
139 bandindex = PG_GETARG_INT32(1);
140 if ( bandindex < 1 ) {
141 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
142 PG_FREE_IF_COPY(pgraster, 0);
148 PG_FREE_IF_COPY(pgraster, 0);
149 elog(ERROR,
"RASTER_getBandPixelTypeName: Could not deserialize raster");
156 elog(NOTICE,
"Could not find raster band of index %d when getting pixel type name. Returning NULL", bandindex);
158 PG_FREE_IF_COPY(pgraster, 0);
164 result = palloc(VARHDRSZ + name_size);
169 memset(VARDATA(result), 0, name_size);
170 ptr = (
char *)result + VARHDRSZ;
173 size = VARHDRSZ + strlen(ptr);
174 SET_VARSIZE(result, size);
177 PG_FREE_IF_COPY(pgraster, 0);
179 PG_RETURN_TEXT_P(result);
196 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
197 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
200 bandindex = PG_GETARG_INT32(1);
201 if ( bandindex < 1 ) {
202 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
203 PG_FREE_IF_COPY(pgraster, 0);
209 PG_FREE_IF_COPY(pgraster, 0);
210 elog(ERROR,
"RASTER_getBandNoDataValue: Could not deserialize raster");
217 elog(NOTICE,
"Could not find raster band of index %d when getting band nodata value. Returning NULL", bandindex);
219 PG_FREE_IF_COPY(pgraster, 0);
226 PG_FREE_IF_COPY(pgraster, 0);
233 PG_FREE_IF_COPY(pgraster, 0);
235 PG_RETURN_FLOAT8(nodata);
246 bool forcechecking =
FALSE;
247 bool bandisnodata =
FALSE;
250 bandindex = PG_GETARG_INT32(1);
251 if ( bandindex < 1 ) {
252 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
257 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
258 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
262 PG_FREE_IF_COPY(pgraster, 0);
263 elog(ERROR,
"RASTER_bandIsNoData: Could not deserialize raster");
270 elog(NOTICE,
"Could not find raster band of index %d when determining if band is nodata. Returning NULL", bandindex);
272 PG_FREE_IF_COPY(pgraster, 0);
276 forcechecking = PG_GETARG_BOOL(2);
278 bandisnodata = (forcechecking) ?
282 PG_FREE_IF_COPY(pgraster, 0);
284 PG_RETURN_BOOL(bandisnodata);
297 const char *bandpath;
301 bandindex = PG_GETARG_INT32(1);
302 if ( bandindex < 1 ) {
303 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
308 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
309 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
313 PG_FREE_IF_COPY(pgraster, 0);
314 elog(ERROR,
"RASTER_getBandPath: Could not deserialize raster");
323 "Could not find raster band of index %d when getting band path. Returning NULL",
327 PG_FREE_IF_COPY(pgraster, 0);
335 PG_FREE_IF_COPY(pgraster, 0);
339 result = cstring_to_text(bandpath);
343 PG_FREE_IF_COPY(pgraster, 0);
345 PG_RETURN_TEXT_P(result);
362 bandindex = PG_GETARG_INT32(1);
363 if ( bandindex < 1 ) {
364 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
368 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
369 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
373 PG_FREE_IF_COPY(pgraster, 0);
374 elog(ERROR,
"RASTER_getFileSize: Could not deserialize raster");
383 "Could not find raster band of index %d when getting band path. Returning NULL",
387 PG_FREE_IF_COPY(pgraster, 0);
392 elog(NOTICE,
"Band of index %d is not out-db.", bandindex);
395 PG_FREE_IF_COPY(pgraster, 0);
403 PG_FREE_IF_COPY(pgraster, 0);
405 PG_RETURN_INT64(fileSize);
421 bandindex = PG_GETARG_INT32(1);
422 if ( bandindex < 1 ) {
423 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
427 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
428 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
432 PG_FREE_IF_COPY(pgraster, 0);
433 elog(ERROR,
"RASTER_getBandFileTimestamp: Could not deserialize raster");
442 "Could not find raster band of index %d when getting band path. Returning NULL",
446 PG_FREE_IF_COPY(pgraster, 0);
451 elog(NOTICE,
"Band of index %d is not out-db.", bandindex);
454 PG_FREE_IF_COPY(pgraster, 0);
462 PG_FREE_IF_COPY(pgraster, 0);
464 PG_RETURN_INT64(fileSize);
467 #define VALUES_LENGTH 8
475 FuncCallContext *funcctx;
480 struct bandmetadata {
491 struct bandmetadata *bmd = NULL;
492 struct bandmetadata *bmd2 = NULL;
497 if (SRF_IS_FIRSTCALL()) {
498 MemoryContext oldcontext;
518 const char *chartmp = NULL;
525 funcctx = SRF_FIRSTCALL_INIT();
528 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
531 if (PG_ARGISNULL(0)) {
532 MemoryContextSwitchTo(oldcontext);
533 SRF_RETURN_DONE(funcctx);
535 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
540 PG_FREE_IF_COPY(pgraster, 0);
541 MemoryContextSwitchTo(oldcontext);
542 elog(ERROR,
"RASTER_bandmetadata: Could not deserialize raster");
543 SRF_RETURN_DONE(funcctx);
549 elog(NOTICE,
"Raster provided has no bands");
551 PG_FREE_IF_COPY(pgraster, 0);
552 MemoryContextSwitchTo(oldcontext);
553 SRF_RETURN_DONE(funcctx);
557 array = PG_GETARG_ARRAYTYPE_P(1);
558 etype = ARR_ELEMTYPE(array);
559 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
567 PG_FREE_IF_COPY(pgraster, 0);
568 MemoryContextSwitchTo(oldcontext);
569 elog(ERROR,
"RASTER_bandmetadata: Invalid data type for band number(s)");
570 SRF_RETURN_DONE(funcctx);
574 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
577 bandNums = palloc(
sizeof(
uint32_t) * n);
578 for (i = 0, j = 0; i < n; i++) {
579 if (nulls[i])
continue;
583 idx = (
uint32_t) DatumGetInt16(e[i]);
586 idx = (
uint32_t) DatumGetInt32(e[i]);
591 if (idx > numBands || idx < 1) {
592 elog(NOTICE,
"Invalid band index: %d. Indices must be 1-based. Returning NULL", idx);
595 PG_FREE_IF_COPY(pgraster, 0);
596 MemoryContextSwitchTo(oldcontext);
597 SRF_RETURN_DONE(funcctx);
607 bandNums = repalloc(bandNums,
sizeof(
uint32_t) * j);
608 for (i = 0; i < j; i++)
612 bandNums = repalloc(bandNums,
sizeof(
uint32_t) * j);
614 bmd = (
struct bandmetadata *) palloc(
sizeof(
struct bandmetadata) * j);
616 for (i = 0; i < j; i++) {
619 elog(NOTICE,
"Could not get raster band at index %d", bandNums[i]);
621 PG_FREE_IF_COPY(pgraster, 0);
622 MemoryContextSwitchTo(oldcontext);
623 SRF_RETURN_DONE(funcctx);
627 bmd[i].bandnum = bandNums[i];
631 charlen = strlen(chartmp) + 1;
632 bmd[i].pixeltype = palloc(
sizeof(
char) * charlen);
633 strncpy(bmd[i].pixeltype, chartmp, charlen);
637 bmd[i].hasnodata =
TRUE;
639 bmd[i].hasnodata =
FALSE;
642 if (bmd[i].hasnodata)
645 bmd[i].nodataval = 0;
650 charlen = strlen(chartmp) + 1;
651 bmd[i].bandpath = palloc(
sizeof(
char) * charlen);
652 strncpy(bmd[i].bandpath, chartmp, charlen);
655 bmd[i].bandpath = NULL;
658 bmd[i].isoutdb = bmd[i].bandpath ?
TRUE :
FALSE;
662 bmd[i].extbandnum = extbandnum + 1;
664 bmd[i].extbandnum = 0;
667 bmd[i].timestamp = 0;
670 if( VSIStatL(bmd[i].bandpath, &sStat) == 0 ) {
671 bmd[i].filesize = sStat.st_size;
672 bmd[i].timestamp = sStat.st_mtime;
680 PG_FREE_IF_COPY(pgraster, 0);
683 funcctx->user_fctx = bmd;
686 funcctx->max_calls = j;
689 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
690 MemoryContextSwitchTo(oldcontext);
692 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
694 "function returning record called in context "
695 "that cannot accept type record"
700 BlessTupleDesc(tupdesc);
701 funcctx->tuple_desc = tupdesc;
703 MemoryContextSwitchTo(oldcontext);
707 funcctx = SRF_PERCALL_SETUP();
709 call_cntr = funcctx->call_cntr;
710 max_calls = funcctx->max_calls;
711 tupdesc = funcctx->tuple_desc;
712 bmd2 = funcctx->user_fctx;
715 if (call_cntr < max_calls) {
721 values[0] = UInt32GetDatum(bmd2[call_cntr].bandnum);
722 values[1] = CStringGetTextDatum(bmd2[call_cntr].pixeltype);
724 if (bmd2[call_cntr].hasnodata)
725 values[2] = Float8GetDatum(bmd2[call_cntr].nodataval);
729 values[3] = BoolGetDatum(bmd2[call_cntr].isoutdb);
730 if (bmd2[call_cntr].bandpath && strlen(bmd2[call_cntr].bandpath)) {
731 values[4] = CStringGetTextDatum(bmd2[call_cntr].bandpath);
732 values[5] = UInt32GetDatum(bmd2[call_cntr].extbandnum);
739 if (bmd2[call_cntr].filesize) {
740 #if POSTGIS_PGSQL_VERSION > 95
741 values[6] = UInt64GetDatum(bmd2[call_cntr].filesize);
742 values[7] = UInt64GetDatum(bmd2[call_cntr].timestamp);
744 values[6] = Int64GetDatum(bmd2[call_cntr].filesize);
745 values[7] = Int64GetDatum(bmd2[call_cntr].timestamp);
754 tuple = heap_form_tuple(tupdesc, values, nulls);
757 result = HeapTupleGetDatum(tuple);
760 pfree(bmd2[call_cntr].pixeltype);
761 if (bmd2[call_cntr].bandpath) pfree(bmd2[call_cntr].bandpath);
763 SRF_RETURN_NEXT(funcctx, result);
768 SRF_RETURN_DONE(funcctx);
784 bool forcechecking =
FALSE;
785 bool skipset =
FALSE;
790 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
796 bandindex = PG_GETARG_INT32(1);
798 elog(NOTICE,
"Invalid band index (must use 1-based). Nodata value not set. Returning original raster");
804 PG_FREE_IF_COPY(pgraster, 0);
805 elog(ERROR,
"RASTER_setBandNoDataValue: Could not deserialize raster");
813 elog(NOTICE,
"Could not find raster band of index %d when setting pixel value. Nodata value not set. Returning original raster", bandindex);
816 if (!PG_ARGISNULL(3))
817 forcechecking = PG_GETARG_BOOL(3);
819 if (PG_ARGISNULL(2)) {
826 nodata = PG_GETARG_FLOAT8(2);
840 PG_FREE_IF_COPY(pgraster, 0);
844 SET_VARSIZE(pgrtn, pgrtn->
size);
845 PG_RETURN_POINTER(pgrtn);
862 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
866 PG_FREE_IF_COPY(pgraster, 0);
867 elog(ERROR,
"RASTER_setBandIsNoData: Could not deserialize raster");
875 bandindex = PG_GETARG_INT32(1);
878 elog(NOTICE,
"Invalid band index (must use 1-based). Isnodata flag not set. Returning original raster");
884 elog(NOTICE,
"Could not find raster band of index %d. Isnodata flag not set. Returning original raster", bandindex);
887 elog(NOTICE,
"Band of index %d has no NODATA so cannot be NODATA. Returning original raster", bandindex);
899 PG_FREE_IF_COPY(pgraster, 0);
900 if (!pgrtn) PG_RETURN_NULL();
902 SET_VARSIZE(pgrtn, pgrtn->
size);
903 PG_RETURN_POINTER(pgrtn);
916 int32_t bandindex = 1;
917 const char *outdbpathchar = NULL;
918 int32_t outdbindex = 1;
919 bool forceset =
FALSE;
923 double nodataval = 0.;
927 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
931 PG_FREE_IF_COPY(pgraster, 0);
932 elog(ERROR,
"RASTER_setBandPath: Cannot deserialize raster");
937 if (!PG_ARGISNULL(1))
938 bandindex = PG_GETARG_INT32(1);
941 elog(NOTICE,
"Invalid band index (must use 1-based). Returning original raster");
947 elog(NOTICE,
"Cannot find raster band of index %d. Returning original raster", bandindex);
949 elog(NOTICE,
"Band of index %d is not out-db. Returning original raster", bandindex);
953 if (!PG_ARGISNULL(2))
959 if (!PG_ARGISNULL(3))
960 outdbindex = PG_GETARG_INT32(3);
963 if (!PG_ARGISNULL(4))
964 forceset = PG_GETARG_BOOL(4);
981 elog(NOTICE,
"Cannot change path of band. Returning original raster");
991 PG_FREE_IF_COPY(pgraster, 0);
992 if (!pgrtn) PG_RETURN_NULL();
994 SET_VARSIZE(pgrtn, pgrtn->
size);
995 PG_RETURN_POINTER(pgrtn);
void rt_band_set_hasnodata_flag(rt_band band, int flag)
Set hasnodata flag value.
rt_errorstate rt_band_set_isnodata_flag(rt_band band, int flag)
Set isnodata flag value.
const char * rt_band_get_ext_path(rt_band band)
Return band's external path (only valid when rt_band_is_offline returns non-zero).
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
rt_band rt_raster_replace_band(rt_raster raster, rt_band band, int index)
Replace band at provided index with new band.
uint64_t rt_band_get_file_size(rt_band band)
Return file size in bytes.
int rt_band_check_is_nodata(rt_band band)
Returns TRUE if the band is only nodata values.
rt_errorstate rt_band_set_nodata(rt_band band, double val, int *converted)
Set nodata value.
void rt_band_destroy(rt_band band)
Destroy a raster band.
uint16_t rt_raster_get_num_bands(rt_raster raster)
uint16_t rt_raster_get_height(rt_raster raster)
rt_errorstate rt_band_get_ext_band_num(rt_band band, uint8_t *bandnum)
Return bands' external band number (only valid when rt_band_is_offline returns non-zero).
uint64_t rt_band_get_file_timestamp(rt_band band)
Return file timestamp.
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
const char * rt_pixtype_name(rt_pixtype pixtype)
rt_band rt_band_new_offline_from_path(uint16_t width, uint16_t height, int hasnodata, double nodataval, uint8_t bandNum, const char *path, int force)
Create an out-db rt_band from path.
uint16_t rt_raster_get_width(rt_raster raster)
int rt_band_is_offline(rt_band band)
Return non-zero if the given band data is on the filesystem.
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_bandIsNoData(PG_FUNCTION_ARGS)
Datum RASTER_setBandIndex(PG_FUNCTION_ARGS)
Datum RASTER_bandmetadata(PG_FUNCTION_ARGS)
Datum RASTER_setBandNoDataValue(PG_FUNCTION_ARGS)
PG_FUNCTION_INFO_V1(RASTER_getBandPixelType)
Return pixel type of the specified band of raster.
bool enable_outdb_rasters
Datum RASTER_getBandPath(PG_FUNCTION_ARGS)
Datum RASTER_getBandFileTimestamp(PG_FUNCTION_ARGS)
Datum RASTER_getBandFileSize(PG_FUNCTION_ARGS)
Datum RASTER_getBandNoDataValue(PG_FUNCTION_ARGS)
Datum RASTER_setBandPath(PG_FUNCTION_ARGS)
Datum RASTER_getBandPixelType(PG_FUNCTION_ARGS)
Datum RASTER_setBandIsNoData(PG_FUNCTION_ARGS)
Datum RASTER_getBandPixelTypeName(PG_FUNCTION_ARGS)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)