]> granicus.if.org Git - postgis/commitdiff
Corrected clamped values in tests for ST_MapAlgebraExpr and ST_MapAlgebraFct.
authorDavid Zwarg <dzwarg@azavea.com>
Tue, 7 Feb 2012 18:07:57 +0000 (18:07 +0000)
committerDavid Zwarg <dzwarg@azavea.com>
Tue, 7 Feb 2012 18:07:57 +0000 (18:07 +0000)
Implemented prepared statements in ST_MapAlgebraExpr.

git-svn-id: http://svn.osgeo.org/postgis/trunk@9068 b70326c6-7e19-0410-871a-916f4a2858ee

raster/rt_pg/rt_pg.c
raster/test/regress/rt_mapalgebraexpr.sql
raster/test/regress/rt_mapalgebraexpr_expected
raster/test/regress/rt_mapalgebrafct_expected

index d0126471071e9bf735caa7c8ddcf07ec1f5a8bc5..04fb35cce8d8ca32a9513d3eeb32edb8bb241df0 100644 (file)
@@ -2526,14 +2526,26 @@ Datum RASTER_mapAlgebraExpr(PG_FUNCTION_ARGS)
     double nodataval = 0.;
     rt_pixtype newpixeltype;
     int skipcomputation = 0;
-    char strnewval[50];
     int len = 0;
+    int argcount = 0;
+    Oid *argtype = NULL;
+    const int argkwcount = 3;
+    char *argkw[] = {"[rast]", "[rast.x]", "[rast.y]"};
+    uint8_t argpos[3] = {0};
+    char place[5];
+    int idx = 0;
     int ret = -1;
     TupleDesc tupdesc;
     SPIPlanPtr spi_plan = NULL;
     SPITupleTable * tuptable = NULL;
     HeapTuple tuple;
     char * strFromText = NULL;
+    Datum *values = NULL;
+    Datum datum = (Datum)NULL;
+    char *nulls = NULL;
+    bool isnull = FALSE;
+    int i = 0;
+    int j = 0;
 
     POSTGIS_RT_DEBUG(2, "RASTER_mapAlgebraExpr: Starting...");
 
@@ -2950,13 +2962,63 @@ Datum RASTER_mapAlgebraExpr(PG_FUNCTION_ARGS)
 
     /* Convert [rast.val] to [rast] */
     if (initexpr != NULL) {
-       newexpr = rtpg_strreplace(initexpr, "[rast.val]", "[rast]", NULL);
-       pfree(initexpr); initexpr=newexpr;
+        newexpr = rtpg_strreplace(initexpr, "[rast.val]", "[rast]", NULL);
+        pfree(initexpr); initexpr=newexpr;
+
+        sprintf(place,"$1");
+        for (i = 0, j = 1; i < argkwcount; i++) {
+            len = 0;
+            newexpr = rtpg_strreplace(initexpr, argkw[i], place, &len);
+            pfree(initexpr); initexpr=newexpr;
+            if (len > 0) {
+                argcount++;
+                argpos[i] = j++;
+
+                sprintf(place, "$%d", j);
+            }
+            else {
+                argpos[i] = 0;
+            }
+        }
+
+        POSTGIS_RT_DEBUGF(3, "RASTER_mapAlgebraExpr: initexpr = %s", initexpr);
+
+        /* Connect to SPI and prepare the expression */
+        ret = SPI_connect();
+        if (ret != SPI_OK_CONNECT) {
+            elog(ERROR, "RASTER_mapAlgebraExpr: Unable to connect to the SPI manager."
+                " Aborting");
+
+            if (initexpr)
+                pfree(initexpr);
+            rt_raster_destroy(raster);
+            rt_raster_destroy(newrast);
+
+            PG_RETURN_NULL();
+        };
+
+        /* Type of all arguments is FLOAT8OID */
+        argtype = (Oid *) palloc(argcount * sizeof(Oid));
+        for (i = 0; i < argcount; i++) argtype[i] = FLOAT8OID;
+        spi_plan = SPI_prepare(initexpr, argcount, argtype);
+
+        if (spi_plan == NULL) {
+            elog(ERROR, "RASTER_mapAlgebraExpr: Could not prepare expression."
+                                    " Aborting");
+
+            rt_raster_destroy(raster);
+            rt_raster_destroy(newrast);
+
+            SPI_finish();
+
+            pfree(initexpr);
+
+            PG_RETURN_NULL();
+        }
     }
 
     for (x = 0; x < width; x++) {
         for(y = 0; y < height; y++) {
-            char *tmp;
             ret = rt_band_get_pixel(band, x, y, &r);
 
             /**
@@ -2965,35 +3027,68 @@ Datum RASTER_mapAlgebraExpr(PG_FUNCTION_ARGS)
              **/
             if (ret != -1 && FLT_NEQ(r, newnodatavalue)) {
                 if (skipcomputation == 0) {
-
                     if (initexpr != NULL) {
+                        /* define values */
+                        values = (Datum *) palloc(sizeof(Datum) * argcount);
+                        if (values == NULL) {
+                            elog(ERROR, "RASTER_mapAlgebraExpr: Unable to allocate memory for value parameters of prepared statement");
 
-                        sprintf(strnewval, "%d", x+1);
-                        newexpr = rtpg_strreplace(initexpr, "[rast.x]", strnewval, NULL);
-                        sprintf(strnewval, "%d", y+1);
-                        tmp = rtpg_strreplace(newexpr, "[rast.y]", strnewval, NULL);
-                        pfree(newexpr); newexpr=tmp;
-                        sprintf(strnewval, "%f", r);
-                        tmp = rtpg_strreplace(newexpr, "[rast]", strnewval, NULL);
-                        pfree(newexpr); newexpr=tmp;
+                            SPI_finish();
+
+                            rt_raster_destroy(raster);
+                            rt_raster_destroy(newrast);
+
+                            PG_RETURN_NULL();
+                        }
 
-                        POSTGIS_RT_DEBUGF(3, "RASTER_mapAlgebraExpr: (%dx%d), "
-                                "r = %s, newexpr = %s",
-                                x, y, strnewval, newexpr);
+                        /* define nulls */
+                        nulls = (char *)palloc(argcount);
+                        if (nulls == NULL) {
+                            elog(ERROR, "RASTER_mapAlgebraExpr: Unable to allocate memory for null parameters of prepared statement");
 
-                        SPI_connect();
+                            SPI_finish();
 
-                        ret = SPI_execute(newexpr, FALSE, 0);
+                            rt_raster_destroy(raster);
+                            rt_raster_destroy(newrast);
 
+                            PG_RETURN_NULL();
+                        }
+                        memset(nulls, 'n', argcount);
+
+                        for (i = 0; i < argkwcount; i++) {
+                            idx = argpos[i];
+                            if (idx < 1) continue;
+                            idx--;
+
+                            if (strstr(argkw[i], "[rast.x]") != NULL) {
+                                /* x is 0 based index, but SQL expects 1 based index */
+                                values[idx] = Float8GetDatum((float)(x+1));
+                                nulls[idx] = ' ';
+                            }
+                            else if (strstr(argkw[i], "[rast.y]") != NULL) {
+                                /* y is 0 based index, but SQL expects 1 based index */
+                                values[idx] = Float8GetDatum((float)(y+1));
+                                nulls[idx] = ' ';
+                            }
+                            else if (strstr(argkw[i], "[rast]") != NULL) {
+                                values[idx] = Float8GetDatum(r);
+                                nulls[idx] = ' ';
+                            }
+
+                        }
+
+                        ret = SPI_execute_plan(spi_plan, values, nulls, FALSE, 0);
+                        pfree(values);
+                        pfree(nulls);
                         if (ret != SPI_OK_SELECT || SPI_tuptable == NULL ||
                                 SPI_processed != 1) {
                             elog(ERROR, "RASTER_mapAlgebraExpr: Invalid construction"
                                     " for expression. Aborting");
 
-                            pfree(newexpr);
                             if (SPI_tuptable)
                                 SPI_freetuptable(tuptable);
 
+                            SPI_freeplan(spi_plan);
                             SPI_finish();
                             PG_RETURN_NULL();
                         }
@@ -3002,19 +3097,19 @@ Datum RASTER_mapAlgebraExpr(PG_FUNCTION_ARGS)
                         tuptable = SPI_tuptable;
 
                         tuple = tuptable->vals[0];
-                        tmp = SPI_getvalue(tuple, tupdesc, 1);
-                        if ( tmp ) {
-                            newval = atof(tmp);
-                        } else {
+                        datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
+                        if ( SPI_result == SPI_ERROR_NOATTRIBUTE ) {
+                            POSTGIS_RT_DEBUGF(3, "Expression for pixel %d,%d (value %g) errored, skip setting", x+1,y+1,r);
+                            newval = newinitialvalue;
+                        }
+                        else if ( isnull ) {
                             POSTGIS_RT_DEBUGF(3, "Expression for pixel %d,%d (value %g) evaluated to NULL, skip setting", x+1,y+1,r);
                             newval = newinitialvalue;
+                        } else {
+                            newval = DatumGetFloat8(datum);
                         }
 
                         SPI_freetuptable(tuptable);
-
-                        SPI_finish();
-
-                        pfree(newexpr);
                     }
 
                     else
@@ -3031,7 +3126,16 @@ Datum RASTER_mapAlgebraExpr(PG_FUNCTION_ARGS)
         }
     }
 
-   if (initexpr != NULL) pfree(initexpr);
+    if (initexpr != NULL) {
+        SPI_freeplan(spi_plan);
+        SPI_finish();
+
+        pfree(initexpr);
+    }
+    else {
+        POSTGIS_RT_DEBUG(3, "RASTER_mapAlgebraExpr: no SPI cleanup");
+    }
+
 
     /* The newrast band has been modified */
 
index 07449624c779bc3885d9a0ccdc7c98cfb9bc7375..8ab2a6ebfb69439f2cb65561c78b53a92d11a4c8 100644 (file)
@@ -30,6 +30,11 @@ FROM ST_TestRaster(0, 0, 10) rast,
      generate_series(2, 4) as y
 ORDER BY x, y;
 
+-- Test divide by zero; blows up the whole query, not just the SPI
+SELECT ST_Value(rast, 1, 1),
+    ST_Value(ST_MapAlgebraExpr(rast, 1, NULL, '[rast]/0'), 1, 1)
+FROM ST_TestRaster(0, 0, 10) rast;
+
 -- Test evaluations to null (see #1523)
 WITH op AS ( select rast AS rin,
   ST_MapAlgebraExpr(rast, 1, NULL, 'g from (select NULL as g) as foo', 2)
index 3478afd0fc82abb67aeeb06a4171366a0d33f45e..7d98be1b1039796594f102cb183296e071df37c4 100644 (file)
@@ -8,9 +8,9 @@ T3||19
 T4||2
 T5||2
 T6||-1
-T7|100|
+T7|100|15
 T8|100|120
-T9|101|
+T9|101|3
 T10.6.2|10|40
 T10.6.3|10|30
 T10.6.4|10|25
@@ -20,5 +20,6 @@ T10.7.4|10|28
 T10.8.2|10|50
 T10.8.3|10|37
 T10.8.4|10|30
+ERROR:  division by zero
 T11.1|10|2
 T11.2|10|2
index d703c0ef82ddf5ac2d46d2eee015409220c5ee5b..38f4eaaf414323cfdb61ad0853c1d4220921c135 100644 (file)
@@ -114,9 +114,9 @@ NOTICE:  Pixel value is null.
 NOTICE:  Pixel value is null.
 |
 |19
-100|
+100|15
 100|120
-101|
+101|3
 213|213
 6314|6314
 100|