]> granicus.if.org Git - postgis/commitdiff
Rework st_estimated_extent to deal with analyzed empty tables (#818)
authorSandro Santilli <strk@keybit.net>
Wed, 18 Jan 2012 15:47:45 +0000 (15:47 +0000)
committerSandro Santilli <strk@keybit.net>
Wed, 18 Jan 2012 15:47:45 +0000 (15:47 +0000)
Still doesn't distinguish between empty and not analyzed recently
(might be improved in that reguard)

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

postgis/geometry_estimate.c
regress/run_test
regress/tickets.sql
regress/tickets_expected

index 1f5a59e31c1805d2c3b801128558ad12f38a8d31..80040914f2fef4deeff5dabb8d75126a003dcff2 100644 (file)
@@ -1334,6 +1334,7 @@ Datum geometry_estimated_extent(PG_FUNCTION_ARGS)
        GBOX *box;
        size_t querysize;
        GEOM_STATS geomstats;
+       float reltuples;
 
        if ( PG_NARGS() == 3 )
        {
@@ -1428,11 +1429,27 @@ Datum geometry_estimated_extent(PG_FUNCTION_ARGS)
        /* Return the stats data */
        if ( txnsp )
        {
-               sprintf(query, "SELECT s.stanumbers1[5:8] FROM pg_statistic s, pg_class c, pg_attribute a, pg_namespace n WHERE c.relname = '%s' AND a.attrelid = c.oid AND a.attname = '%s' AND n.nspname = '%s' AND c.relnamespace = n.oid AND s.starelid=c.oid AND s.staattnum = a.attnum AND staattnum = attnum", tbl, col, nsp);
+         sprintf(query, 
+           "SELECT s.stanumbers1[5:8], c.reltuples FROM pg_class c"
+           " LEFT OUTER JOIN pg_namespace n ON (n.oid = c.relnamespace)"
+           " LEFT OUTER JOIN pg_attribute a ON (a.attrelid = c.oid )"
+           " LEFT OUTER JOIN pg_statistic s ON (s.starelid = c.oid AND "
+                                               "s.staattnum = a.attnum )"
+           " WHERE c.relname = '%s' AND a.attname = '%s' "
+           " AND n.nspname = '%s';",
+           tbl, col, nsp);
        }
        else
        {
-               sprintf(query, "SELECT s.stanumbers1[5:8] FROM pg_statistic s, pg_class c, pg_attribute a, pg_namespace n WHERE c.relname = '%s' AND a.attrelid = c.oid AND a.attname = '%s' AND n.nspname = current_schema() AND c.relnamespace = n.oid AND s.starelid=c.oid AND s.staattnum = a.attnum AND staattnum = attnum", tbl, col);
+         sprintf(query, 
+           "SELECT s.stanumbers1[5:8], c.reltuples FROM pg_class c"
+           " LEFT OUTER JOIN pg_namespace n ON (n.oid = c.relnamespace)"
+           " LEFT OUTER JOIN pg_attribute a ON (a.attrelid = c.oid )"
+           " LEFT OUTER JOIN pg_statistic s ON (s.starelid = c.oid AND "
+                                               "s.staattnum = a.attnum )"
+           " WHERE c.relname = '%s' AND a.attname = '%s' "
+           " AND n.nspname = current_schema();",
+           tbl, col);
        }
 
        POSTGIS_DEBUGF(4, " query: %s", query);
@@ -1449,10 +1466,7 @@ Datum geometry_estimated_extent(PG_FUNCTION_ARGS)
 
                POSTGIS_DEBUGF(3, " %d stat rows", SPI_processed);
 
-               /* 
-                * TODO: distinguish between empty and not analyzed ?
-                */
-               elog(WARNING, "No stats for \"%s\".\"%s\".\"%s\" (empty or not analyzed)",
+               elog(ERROR, "Unexistent field \"%s\".\"%s\".\"%s\"",
                        ( nsp ? nsp : "<current>" ), tbl, col);
 
                SPI_finish();
@@ -1462,6 +1476,33 @@ Datum geometry_estimated_extent(PG_FUNCTION_ARGS)
        tuptable = SPI_tuptable;
        tupdesc = SPI_tuptable->tupdesc;
        tuple = tuptable->vals[0];
+
+       /* Check if the table has zero rows first */
+       reltuples = DatumGetFloat4(SPI_getbinval(tuple, tupdesc, 2, &isnull));
+       if (isnull)
+       {
+
+               POSTGIS_DEBUG(3, " reltuples is NULL");
+
+               elog(ERROR, "geometry_estimated_extent: null reltuples for table");
+
+               SPI_finish();
+               PG_RETURN_NULL();
+       }
+       if ( ! reltuples )
+       {
+               POSTGIS_DEBUG(3, "table has estimated zero rows");
+
+               /* 
+                * TODO: distinguish between empty and not analyzed ?
+                */
+               elog(NOTICE, "\"%s\".\"%s\".\"%s\" is empty or not analyzed",
+                       ( nsp ? nsp : "<current>" ), tbl, col);
+
+               SPI_finish();
+               PG_RETURN_NULL();
+       }
+
        array = DatumGetArrayTypeP(SPI_getbinval(tuple, tupdesc, 1, &isnull));
        if (isnull)
        {
index 21a13994ad687f4defdda074ebeb95b64b289e58..93f342136d95f65edda93badd77adbf87c776cca 100755 (executable)
@@ -206,6 +206,7 @@ run_simple_test ()
                | grep --binary-files=text -v "^CREATE" \
                | grep --binary-files=text -v "^SELECT" \
                | grep --binary-files=text -v "^SET" \
+               | grep --binary-files=text -v "^TRUNCATE" \
                | grep --binary-files=text -v "^LINE [0-9]" \
                | grep --binary-files=text -v "^  *^$" \
                | sed 's/Infinity/inf/g;s/Inf/inf/g;s/1\.#INF/inf/g' \
index 8cf002018919a1addb9d6490aeda42ddf96b52b6..cba1487a8483f9173aae9e9d67bd18b1644340fa 100644 (file)
@@ -437,7 +437,7 @@ SELECT '#1273', st_equals(p.g, postgis_addbbox(p.g)) from p;
 WITH p AS ( SELECT 'MULTIPOINT((832694.188 816254.625))'::geometry as g ) 
 SELECT '#1273.1', st_equals(p.g, postgis_dropbbox(p.g)) from p;
 
--- #877
+-- #877, #818
 create table t(g geometry);
 select '#877.1', st_estimated_extent('t','g');
 analyze t;
@@ -446,6 +446,8 @@ insert into t(g) values ('LINESTRING(-10 -50, 20 30)');
 select '#877.3', st_estimated_extent('t','g');
 analyze t;
 select '#877.4', st_estimated_extent('t','g');
+truncate t;
+select '#818.1', st_estimated_extent('t','g');
 drop table t;
 
 -- #1320
index 16787e13997f24215db8f52badff2329ca199e9a..507367b406bbf52a7c88cd18983bde2a98798641 100644 (file)
@@ -136,13 +136,15 @@ ERROR:  First argument must be a LINESTRING
 #1060|FFFFFFFF2
 #1273|t
 #1273.1|t
-WARNING:  No stats for "<current>"."t"."g" (empty or not analyzed)
+NOTICE:  "<current>"."t"."g" is empty or not analyzed
 #877.1|
-WARNING:  No stats for "public"."t"."g" (empty or not analyzed)
+NOTICE:  "public"."t"."g" is empty or not analyzed
 #877.2|
-WARNING:  No stats for "<current>"."t"."g" (empty or not analyzed)
+NOTICE:  "<current>"."t"."g" is empty or not analyzed
 #877.3|
 #877.4|BOX(-10 -50,20 30)
+NOTICE:  "<current>"."t"."g" is empty or not analyzed
+#818.1|
 <#1320>
 #1320.geog.1|MULTIPOLYGON|4326
 #1320.geom.1|MULTIPOLYGON|4326