mirror of
https://git.osgeo.org/gitea/postgis/postgis
synced 2024-10-24 09:02:37 +00:00
Refactored ST_MapAlgebraFctNgb to cache userfunction lookup, and accept NULL input and output values.
git-svn-id: http://svn.osgeo.org/postgis/trunk@8183 b70326c6-7e19-0410-871a-916f4a2858ee
This commit is contained in:
parent
15c2f240d2
commit
663a3de49e
|
@ -8938,7 +8938,8 @@ Datum RASTER_mapAlgebraFctNgb(PG_FUNCTION_ARGS)
|
||||||
rt_pixtype newpixeltype;
|
rt_pixtype newpixeltype;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
Oid oid;
|
Oid oid;
|
||||||
Datum extraargs;
|
FmgrInfo cbinfo;
|
||||||
|
FunctionCallInfoData cbdata;
|
||||||
Datum tmpnewval;
|
Datum tmpnewval;
|
||||||
ArrayType * neighborDatum;
|
ArrayType * neighborDatum;
|
||||||
char * strFromText = NULL;
|
char * strFromText = NULL;
|
||||||
|
@ -9126,6 +9127,10 @@ Datum RASTER_mapAlgebraFctNgb(PG_FUNCTION_ARGS)
|
||||||
|
|
||||||
if (newpixeltype == PT_END) {
|
if (newpixeltype == PT_END) {
|
||||||
elog(ERROR, "RASTER_mapAlgebraFctNgb: Invalid pixeltype. Returning NULL");
|
elog(ERROR, "RASTER_mapAlgebraFctNgb: Invalid pixeltype. Returning NULL");
|
||||||
|
|
||||||
|
rt_raster_destroy(raster);
|
||||||
|
rt_raster_destroy(newrast);
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9135,12 +9140,73 @@ Datum RASTER_mapAlgebraFctNgb(PG_FUNCTION_ARGS)
|
||||||
/* Get the name of the callback userfunction */
|
/* Get the name of the callback userfunction */
|
||||||
if (PG_ARGISNULL(5)) {
|
if (PG_ARGISNULL(5)) {
|
||||||
elog(ERROR, "RASTER_mapAlgebraFctNgb: Required function is missing. Returning NULL");
|
elog(ERROR, "RASTER_mapAlgebraFctNgb: Required function is missing. Returning NULL");
|
||||||
|
|
||||||
|
rt_raster_destroy(raster);
|
||||||
|
rt_raster_destroy(newrast);
|
||||||
|
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
|
||||||
oid = PG_GETARG_OID(5);
|
oid = PG_GETARG_OID(5);
|
||||||
|
if (oid == InvalidOid) {
|
||||||
|
elog(ERROR, "RASTER_mapAlgebraFctNgb: Got invalid function object id. Returning NULL");
|
||||||
|
|
||||||
POSTGIS_RT_DEBUGF(3, "RASTER_mapAlgebraFctNgb: Got function oid: %d", oid);
|
rt_raster_destroy(raster);
|
||||||
|
rt_raster_destroy(newrast);
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
fmgr_info(oid, &cbinfo);
|
||||||
|
|
||||||
|
/* function cannot return set */
|
||||||
|
if (cbinfo.fn_retset) {
|
||||||
|
elog(ERROR, "RASTER_mapAlgebraFctNgb: Function provided must return double precision not resultset. Returning NULL");
|
||||||
|
|
||||||
|
rt_raster_destroy(raster);
|
||||||
|
rt_raster_destroy(newrast);
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
/* function should have correct # of args */
|
||||||
|
else if (cbinfo.fn_nargs != 3) {
|
||||||
|
elog(ERROR, "RASTER_mapAlgebraFctNgb: Function does not have three input parameters. Returning NULL");
|
||||||
|
|
||||||
|
rt_raster_destroy(raster);
|
||||||
|
rt_raster_destroy(newrast);
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (func_volatile(oid) == 'v') {
|
||||||
|
elog(NOTICE, "Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prep function call data */
|
||||||
|
#if POSTGIS_PGSQL_VERSION <= 90
|
||||||
|
InitFunctionCallInfoData(cbdata, &cbinfo, 3, InvalidOid, NULL);
|
||||||
|
#else
|
||||||
|
InitFunctionCallInfoData(cbdata, &cbinfo, 3, InvalidOid, NULL, NULL);
|
||||||
|
#endif
|
||||||
|
memset(cbdata.argnull, FALSE, 3);
|
||||||
|
|
||||||
|
/* check that the function isn't strict if the args are null. */
|
||||||
|
if (PG_ARGISNULL(7)) {
|
||||||
|
if (cbinfo.fn_strict) {
|
||||||
|
elog(ERROR, "RASTER_mapAlgebraFctNgb: Strict callback functions cannot have null parameters. Returning NULL");
|
||||||
|
|
||||||
|
rt_raster_destroy(raster);
|
||||||
|
rt_raster_destroy(newrast);
|
||||||
|
|
||||||
|
PG_RETURN_NULL();
|
||||||
|
}
|
||||||
|
|
||||||
|
cbdata.arg[2] = (Datum)NULL;
|
||||||
|
cbdata.argnull[2] = TRUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cbdata.arg[2] = PG_GETARG_DATUM(7);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Optimization: If the raster is only filled with nodata values return
|
* Optimization: If the raster is only filled with nodata values return
|
||||||
|
@ -9281,6 +9347,9 @@ Datum RASTER_mapAlgebraFctNgb(PG_FUNCTION_ARGS)
|
||||||
SET_VARSIZE(txtCallbackParam, VARSIZE(txtNodataMode));
|
SET_VARSIZE(txtCallbackParam, VARSIZE(txtNodataMode));
|
||||||
memcpy((void *)VARDATA(txtCallbackParam), (void *)VARDATA(txtNodataMode), VARSIZE(txtNodataMode) - VARHDRSZ);
|
memcpy((void *)VARDATA(txtCallbackParam), (void *)VARDATA(txtNodataMode), VARSIZE(txtNodataMode) - VARHDRSZ);
|
||||||
|
|
||||||
|
/* pass the nodata mode into the user function */
|
||||||
|
cbdata.arg[1] = CStringGetDatum(txtCallbackParam);
|
||||||
|
|
||||||
strFromText = text_to_cstring(txtNodataMode);
|
strFromText = text_to_cstring(txtNodataMode);
|
||||||
strFromText = strtoupper(strFromText);
|
strFromText = strtoupper(strFromText);
|
||||||
|
|
||||||
|
@ -9322,8 +9391,6 @@ Datum RASTER_mapAlgebraFctNgb(PG_FUNCTION_ARGS)
|
||||||
POSTGIS_RT_DEBUGF(3, "RASTER_mapAlgebraFctNgb: Main computing loop (%d x %d)",
|
POSTGIS_RT_DEBUGF(3, "RASTER_mapAlgebraFctNgb: Main computing loop (%d x %d)",
|
||||||
width, height);
|
width, height);
|
||||||
|
|
||||||
extraargs = PG_GETARG_DATUM(7);
|
|
||||||
|
|
||||||
/* Allocate room for the neighborhood. */
|
/* Allocate room for the neighborhood. */
|
||||||
neighborData = (Datum *)palloc(winwidth * winheight * sizeof(Datum));
|
neighborData = (Datum *)palloc(winwidth * winheight * sizeof(Datum));
|
||||||
neighborNulls = (bool *)palloc(winwidth * winheight * sizeof(bool));
|
neighborNulls = (bool *)palloc(winwidth * winheight * sizeof(bool));
|
||||||
|
@ -9399,9 +9466,19 @@ Datum RASTER_mapAlgebraFctNgb(PG_FUNCTION_ARGS)
|
||||||
neighborDatum = construct_md_array((void *)neighborData, neighborNulls, 2, neighborDims, neighborLbs,
|
neighborDatum = construct_md_array((void *)neighborData, neighborNulls, 2, neighborDims, neighborLbs,
|
||||||
FLOAT8OID, typlen, typbyval, typalign);
|
FLOAT8OID, typlen, typbyval, typalign);
|
||||||
|
|
||||||
/* convert neighborData to a datum for OidFunctionCall3 */
|
/* Assign the neighbor matrix as the first argument to the user function */
|
||||||
tmpnewval = OidFunctionCall3(oid, PointerGetDatum(neighborDatum), CStringGetDatum(txtCallbackParam), extraargs);
|
cbdata.arg[0] = PointerGetDatum(neighborDatum);
|
||||||
|
|
||||||
|
/* Invoke the user function */
|
||||||
|
tmpnewval = FunctionCallInvoke(&cbdata);
|
||||||
|
|
||||||
|
/* Get the return value of the user function */
|
||||||
|
if (cbdata.isnull) {
|
||||||
|
newval = newnodatavalue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
newval = DatumGetFloat8(tmpnewval);
|
newval = DatumGetFloat8(tmpnewval);
|
||||||
|
}
|
||||||
|
|
||||||
POSTGIS_RT_DEBUGF(3, "RASTER_mapAlgebraFctNgb: new value = %f",
|
POSTGIS_RT_DEBUGF(3, "RASTER_mapAlgebraFctNgb: new value = %f",
|
||||||
newval);
|
newval);
|
||||||
|
@ -9416,13 +9493,9 @@ Datum RASTER_mapAlgebraFctNgb(PG_FUNCTION_ARGS)
|
||||||
|
|
||||||
|
|
||||||
/* clean up */
|
/* clean up */
|
||||||
POSTGIS_RT_DEBUG(3, "RASTER_mapAlgebraFctNgb: cleaning up memory (neighborNulls)");
|
|
||||||
pfree(neighborNulls);
|
pfree(neighborNulls);
|
||||||
POSTGIS_RT_DEBUG(3, "RASTER_mapAlgebraFctNgb: cleaning up memory (neighborData)");
|
|
||||||
pfree(neighborData);
|
pfree(neighborData);
|
||||||
POSTGIS_RT_DEBUGF(3, "RASTER_mapAlgebraFctNgb: cleaning up memory (strFromText = '%s')", strFromText);
|
|
||||||
pfree(strFromText);
|
pfree(strFromText);
|
||||||
POSTGIS_RT_DEBUGF(3, "RASTER_mapAlgebraFctNgb: cleaning up memory (txtCallbackFaram)", txtCallbackParam);
|
|
||||||
pfree(txtCallbackParam);
|
pfree(txtCallbackParam);
|
||||||
|
|
||||||
/* The newrast band has been modified */
|
/* The newrast band has been modified */
|
||||||
|
|
|
@ -29,7 +29,17 @@ CREATE OR REPLACE FUNCTION ST_Sum(matrix float[][], nodatamode text, variadic ar
|
||||||
RETURN sum;
|
RETURN sum;
|
||||||
END;
|
END;
|
||||||
$$
|
$$
|
||||||
LANGUAGE 'plpgsql';
|
LANGUAGE 'plpgsql' IMMUTABLE;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION ST_Nullage(matrix float[][], nodatamode text, VARIADIC args text[])
|
||||||
|
RETURNS float AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
RETURN NULL;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
LANGUAGE 'plpgsql' IMMUTABLE;
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
--Test rasters
|
--Test rasters
|
||||||
|
|
|
@ -165,3 +165,10 @@ SELECT
|
||||||
)).*
|
)).*
|
||||||
FROM ST_TestRasterNgb(5, 5, 1) AS rast) AS foo;
|
FROM ST_TestRasterNgb(5, 5, 1) AS rast) AS foo;
|
||||||
|
|
||||||
|
-- test a user function that nullifies everything
|
||||||
|
SELECT
|
||||||
|
ST_Value(rast, 2, 2) = 2,
|
||||||
|
ST_Value(
|
||||||
|
ST_MapAlgebraFctNgb(rast, 1, NULL, 1, 1, 'ST_Nullage(float[][], text, text[])'::regprocedure, 'NULL', NULL), 2, 2
|
||||||
|
) IS NULL
|
||||||
|
FROM ST_TestRasterNgb(3, 3, 2) AS rast;
|
||||||
|
|
|
@ -52,3 +52,4 @@ t|t|t
|
||||||
NOTICE: SRID value -1 converted to the officially unknown SRID value 0
|
NOTICE: SRID value -1 converted to the officially unknown SRID value 0
|
||||||
NOTICE: SRID value -1 converted to the officially unknown SRID value 0
|
NOTICE: SRID value -1 converted to the officially unknown SRID value 0
|
||||||
t|t|t
|
t|t|t
|
||||||
|
t|t
|
||||||
|
|
Loading…
Reference in a new issue