From 90ece61b862d42cb1a74caa83080464bd2c58a04 Mon Sep 17 00:00:00 2001 From: Bborie Park Date: Mon, 6 Feb 2012 20:53:19 +0000 Subject: [PATCH] Added support to pass pixel positions of both rasters to user function in 2-raster ST_MapAlgebraFct. This provides similar functionality to the keywords described in #1525. git-svn-id: http://svn.osgeo.org/postgis/trunk@9052 b70326c6-7e19-0410-871a-916f4a2858ee --- raster/rt_pg/rt_pg.c | 86 +++++++++++++------ .../test/regress/rt_mapalgebrafct_2raster.sql | 13 +-- 2 files changed, 66 insertions(+), 33 deletions(-) diff --git a/raster/rt_pg/rt_pg.c b/raster/rt_pg/rt_pg.c index 1e4ef01d4..d01264710 100644 --- a/raster/rt_pg/rt_pg.c +++ b/raster/rt_pg/rt_pg.c @@ -8438,10 +8438,10 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS) int hasnodatanodataval = 0; double nodatanodataval = 0; - Oid ufcnoid = InvalidOid; - FmgrInfo uflinfo; - FunctionCallInfoData ufcinfo; - int ufcnullcount = 0; + Oid ufc_noid = InvalidOid; + FmgrInfo ufl_info; + FunctionCallInfoData ufc_info; + int ufc_nullcount = 0; int idx = 0; uint32_t i = 0; @@ -8983,24 +8983,29 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS) case REGPROCEDUREOID: { POSTGIS_RT_DEBUG(3, "arg 4 is \"userfunction\"!"); if (!PG_ARGISNULL(4)) { - ufcnullcount = 0; - ufcnoid = PG_GETARG_OID(4); + ufc_nullcount = 0; + ufc_noid = PG_GETARG_OID(4); /* get function info */ - fmgr_info(ufcnoid, &uflinfo); + fmgr_info(ufc_noid, &ufl_info); /* function cannot return set */ err = 0; - if (uflinfo.fn_retset) { + if (ufl_info.fn_retset) { elog(ERROR, "RASTER_mapAlgebra2: Function provided must return double precision not resultset"); err = 1; } /* function should have correct # of args */ - else if (uflinfo.fn_nargs != 3) { - elog(ERROR, "RASTER_mapAlgebra2: Function does not have three input parameters"); + else if (ufl_info.fn_nargs < 3 || ufl_info.fn_nargs > 4) { + elog(ERROR, "RASTER_mapAlgebra2: Function provided must have three or four input parameters"); err = 1; } + /* + TODO: consider adding checks of the userfunction parameters + should be able to use get_fn_expr_argtype() of fmgr.c + */ + if (err) { for (k = 0; k < set_count; k++) rt_raster_destroy(_rast[k]); rt_raster_destroy(raster); @@ -9008,25 +9013,29 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } - if (func_volatile(ufcnoid) == 'v') { + if (func_volatile(ufc_noid) == '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(ufcinfo, &uflinfo, 3, InvalidOid, NULL); + InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL); #else - InitFunctionCallInfoData(ufcinfo, &uflinfo, 3, InvalidOid, NULL, NULL); + InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL); #endif - memset(ufcinfo.argnull, FALSE, 3); + memset(ufc_info.argnull, FALSE, ufl_info.fn_nargs); + if (ufl_info.fn_nargs != 4) + k = 2; + else + k = 3; if (!PG_ARGISNULL(7)) { - ufcinfo.arg[2] = PG_GETARG_DATUM(7); + ufc_info.arg[k] = PG_GETARG_DATUM(7); } else { - ufcinfo.arg[2] = (Datum) NULL; - ufcinfo.argnull[2] = TRUE; - ufcnullcount++; + ufc_info.arg[k] = (Datum) NULL; + ufc_info.argnull[k] = TRUE; + ufc_nullcount++; } } break; @@ -9046,7 +9055,7 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS) (spi_empty != spi_count) || hasnodatanodataval ) ) || ( - (calltype == REGPROCEDUREOID) && (ufcnoid != InvalidOid) + (calltype == REGPROCEDUREOID) && (ufc_noid != InvalidOid) )) { for (x = 0; x < dim[0]; x++) { for (y = 0; y < dim[1]; y++) { @@ -9258,29 +9267,52 @@ Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS) } } break; case REGPROCEDUREOID: { + Datum d[4]; + ArrayType *a; + /* build fcnarg */ for (i = 0; i < set_count; i++) { - ufcinfo.arg[i] = Float8GetDatum(_pixel[i]); + ufc_info.arg[i] = Float8GetDatum(_pixel[i]); if (_haspixel[i]) { - ufcinfo.argnull[i] = FALSE; - ufcnullcount--; + ufc_info.argnull[i] = FALSE; + ufc_nullcount--; } else { - ufcinfo.argnull[i] = TRUE; - ufcnullcount++; + ufc_info.argnull[i] = TRUE; + ufc_nullcount++; } } /* function is strict and null parameter is passed */ /* http://archives.postgresql.org/pgsql-general/2011-11/msg00424.php */ - if (uflinfo.fn_strict && ufcnullcount) + if (ufl_info.fn_strict && ufc_nullcount) break; - datum = FunctionCallInvoke(&ufcinfo); + /* 4 parameters, add position */ + if (ufl_info.fn_nargs == 4) { + /* Datum of 4 element array */ + /* array is (x1, y1, x2, y2) */ + for (i = 0; i < set_count; i++) { + if (i < 1) { + d[0] = Int32GetDatum(_pos[i][0]); + d[1] = Int32GetDatum(_pos[i][1]); + } + else { + d[2] = Int32GetDatum(_pos[i][0]); + d[3] = Int32GetDatum(_pos[i][1]); + } + } + + a = construct_array(d, 4, INT4OID, sizeof(int4), true, 'i'); + ufc_info.arg[2] = PointerGetDatum(a); + ufc_info.argnull[2] = FALSE; + } + + datum = FunctionCallInvoke(&ufc_info); /* result is not null*/ - if (!ufcinfo.isnull) { + if (!ufc_info.isnull) { haspixel = 1; pixel = DatumGetFloat8(datum); } diff --git a/raster/test/regress/rt_mapalgebrafct_2raster.sql b/raster/test/regress/rt_mapalgebrafct_2raster.sql index 135ab607c..13b0c8c6b 100644 --- a/raster/test/regress/rt_mapalgebrafct_2raster.sql +++ b/raster/test/regress/rt_mapalgebrafct_2raster.sql @@ -55,6 +55,7 @@ DROP FUNCTION IF EXISTS make_test_raster(integer, integer, integer, double preci CREATE OR REPLACE FUNCTION raster_mapalgebra_intersection( rast1 double precision, rast2 double precision, + xy int[], VARIADIC userargs text[] ) RETURNS double precision @@ -142,7 +143,7 @@ CREATE OR REPLACE FUNCTION raster_mapalgebra_second( -- INTERSECTION INSERT INTO raster_mapalgebra_out (SELECT r1.rid, r2.rid, 'INTERSECTION', st_mapalgebrafct( - r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION' + r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION' ) FROM raster_mapalgebra r1 JOIN raster_mapalgebra r2 @@ -151,7 +152,7 @@ INSERT INTO raster_mapalgebra_out AND r2.rid BETWEEN 1 AND 9 ) UNION ALL ( SELECT r1.rid, r2.rid, 'INTERSECTION', st_mapalgebrafct( - r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION' + r1.rast, r2.rast, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION' ) FROM raster_mapalgebra r1 JOIN raster_mapalgebra r2 @@ -162,21 +163,21 @@ INSERT INTO raster_mapalgebra_out INSERT INTO raster_mapalgebra_out SELECT NULL AS rid, rid, 'INTERSECTION', st_mapalgebrafct( - NULL::raster, rast, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION' + NULL::raster, rast, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION' ) FROM raster_mapalgebra ; INSERT INTO raster_mapalgebra_out SELECT rid, NULL AS rid, 'INTERSECTION', st_mapalgebrafct( - rast, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION' + rast, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION' ) FROM raster_mapalgebra ; INSERT INTO raster_mapalgebra_out SELECT NULL AS rid, NULL AS rid, 'INTERSECTION', st_mapalgebrafct( - NULL::raster, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, text[])'::regprocedure, '32BF', 'INTERSECTION' + NULL::raster, NULL::raster, 'raster_mapalgebra_intersection(double precision, double precision, int[], text[])'::regprocedure, '32BF', 'INTERSECTION' ) ; @@ -335,7 +336,7 @@ FROM ( FROM raster_mapalgebra_out ) AS r; -DROP FUNCTION IF EXISTS raster_mapalgebra_intersection(double precision, double precision, VARIADIC text[]); +DROP FUNCTION IF EXISTS raster_mapalgebra_intersection(double precision, double precision, int[], VARIADIC text[]); DROP FUNCTION IF EXISTS raster_mapalgebra_union(double precision, double precision, VARIADIC text[]); DROP FUNCTION IF EXISTS raster_mapalgebra_first(double precision, double precision, VARIADIC text[]); DROP FUNCTION IF EXISTS raster_mapalgebra_second(double precision, double precision, VARIADIC text[]); -- 2.40.0