- #2565, ST_SummaryStats(tablename, rastercolumn, ...) uses
ST_SummaryStatsAgg()
+ - #2567, ST_Count(tablename, rastercolumn, ...) uses ST_CountAgg()
* Deprecated signatures *
- #2565, ST_SummaryStats(tablename, rastercolumn, ...)
+ - #2567, ST_Count(tablename, rastercolumn, ...)
* New Features *
variable GDAL_DATA
- #2397, read encoding info automatically in shapefile loader
- #2565, ST_SummaryStatsAgg()
+ - #2567, ST_CountAgg()
* Enhancements *
<sect1 id="RasterBand_Stats">
<title>Raster Band Statistics and Analytics</title>
+
<refentry id="RT_ST_Count">
<refnamediv>
<refname>ST_Count</refname>
<para>Returns the number of pixels in a given band of a raster or raster coverage. If no band is specified <varname>nband</varname> defaults to 1. </para>
<note><para>If <varname>exclude_nodata_value</varname> is set to true, will only count pixels with value not equal to the <varname>nodata</varname> value of the raster. Set <varname>exclude_nodata_value</varname> to false to get count all pixels</para></note>
<para>Availability: 2.0.0 </para>
+
+ <warning>
+ <para>
+ The ST_Count(rastertable, rastercolumn, ...) variants are deprecated as of 2.2.0. Use <xref linkend="RT_ST_CountAgg" /> instead.
+ </para>
+ </warning>
+
</refsection>
<refsection>
<refsection>
<title>See Also</title>
- <para><xref linkend="RT_ST_SetBandNoDataValue" /></para>
+ <para>
+ <xref linkend="RT_ST_CountAgg" />,
+ <xref linkend="RT_ST_SummaryStats" />,
+ <xref linkend="RT_ST_SetBandNoDataValue" />
+ </para>
+ </refsection>
+ </refentry>
+
+ <refentry id="RT_ST_CountAgg">
+ <refnamediv>
+ <refname>ST_CountAgg</refname>
+ <refpurpose>
+ Aggregate. Returns the number of pixels in a given band of a set of rasters. If no band is specified defaults to band 1. If exclude_nodata_value is set to true, will only count pixels that are not equal to the NODATA value.
+ </refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <funcsynopsis>
+ <funcprototype>
+ <funcdef>bigint <function>ST_CountAgg</function></funcdef>
+ <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
+ <paramdef><type>integer </type> <parameter>nband</parameter></paramdef>
+ <paramdef><type>boolean </type> <parameter>exclude_nodata_value</parameter></paramdef>
+ <paramdef><type>double precision </type> <parameter>sample_percent</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>bigint <function>ST_CountAgg</function></funcdef>
+ <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
+ <paramdef><type>integer </type> <parameter>nband</parameter></paramdef>
+ <paramdef><type>boolean </type> <parameter>exclude_nodata_value</parameter></paramdef>
+ </funcprototype>
+
+ <funcprototype>
+ <funcdef>bigint <function>ST_CountAgg</function></funcdef>
+ <paramdef><type>raster </type> <parameter>rast</parameter></paramdef>
+ <paramdef><type>boolean </type> <parameter>exclude_nodata_value</parameter></paramdef>
+ </funcprototype>
+
+ </funcsynopsis>
+ </refsynopsisdiv>
+
+ <refsection>
+ <title>Description</title>
+
+ <para>Returns the number of pixels in a given band of a set of rasters. If no band is specified <varname>nband</varname> defaults to 1.</para>
+ <para>
+ If <varname>exclude_nodata_value</varname> is set to true, will only count pixels with value not equal to the <varname>NODATA</varname> value of the raster. Set <varname>exclude_nodata_value</varname> to false to get count all pixels
+ </para>
+ <para>By default will sample all pixels. To get faster response, set <varname>sample_percent</varname> to value between zero (0) and one (1)</para>
+
+ <para>Availability: 2.2.0 </para>
+ </refsection>
+
+ <refsection>
+ <title>Examples</title>
+ <programlisting>
+WITH foo AS (
+ SELECT
+ rast.rast
+ FROM (
+ SELECT ST_SetValue(
+ ST_SetValue(
+ ST_SetValue(
+ ST_AddBand(
+ ST_MakeEmptyRaster(10, 10, 10, 10, 2, 2, 0, 0,0)
+ , 1, '64BF', 0, 0
+ )
+ , 1, 1, 1, -10
+ )
+ , 1, 5, 4, 0
+ )
+ , 1, 5, 5, 3.14159
+ ) AS rast
+ ) AS rast
+ FULL JOIN (
+ SELECT generate_series(1, 10) AS id
+ ) AS id
+ ON 1 = 1
+)
+SELECT
+ ST_CountAgg(rast, 1, TRUE)
+FROM foo;
+
+ st_countagg
+-------------
+ 20
+(1 row)
+ </programlisting>
+ </refsection>
+
+ <refsection>
+ <title>See Also</title>
+ <para>
+ <xref linkend="RT_ST_Count" />,
+ <xref linkend="RT_ST_SummaryStats" />,
+ <xref linkend="RT_ST_SetBandNoDataValue" />
+ </para>
</refsection>
</refentry>
stats summarystats;
BEGIN
EXECUTE 'SELECT (stats).* FROM (SELECT ST_SummaryStatsAgg('
- || $2 || ', '
+ || quote_ident($2) || ', '
|| $3 || ', '
|| $4 || ', '
|| $5 || ') AS stats '
AS $$ SELECT _st_summarystats($1, $2, 1, TRUE, $3) $$
LANGUAGE 'sql' STABLE STRICT;
-
-----------------------------------------------------------------------
-- ST_Count and ST_ApproxCount
-----------------------------------------------------------------------
+
CREATE OR REPLACE FUNCTION _st_count(rast raster, nband int DEFAULT 1, exclude_nodata_value boolean DEFAULT TRUE, sample_percent double precision DEFAULT 1)
RETURNS bigint
AS $$
AS $$ SELECT _st_count($1, 1, TRUE, $2) $$
LANGUAGE 'sql' IMMUTABLE STRICT;
-CREATE OR REPLACE FUNCTION _st_count(rastertable text, rastercolumn text, nband integer DEFAULT 1, exclude_nodata_value boolean DEFAULT TRUE, sample_percent double precision DEFAULT 1)
+-----------------------------------------------------------------------
+-- ST_CountAgg
+-----------------------------------------------------------------------
+
+CREATE TYPE agg_count AS (
+ count bigint,
+ nband integer,
+ exclude_nodata_value boolean,
+ sample_percent double precision
+);
+
+CREATE OR REPLACE FUNCTION _st_countagg_finalfn(agg agg_count)
RETURNS bigint
AS $$
- DECLARE
- curs refcursor;
+ BEGIN
+ IF agg IS NULL THEN
+ RAISE EXCEPTION 'Cannot count coverage';
+ END IF;
- ctable text;
- ccolumn text;
- rast raster;
+ RETURN agg.count;
+ END;
+ $$ LANGUAGE 'plpgsql' IMMUTABLE;
- rtn bigint;
- tmp bigint;
+CREATE OR REPLACE FUNCTION __st_countagg_transfn(
+ agg agg_count,
+ rast raster,
+ nband integer DEFAULT 1, exclude_nodata_value boolean DEFAULT TRUE,
+ sample_percent double precision DEFAULT 1
+)
+ RETURNS agg_count
+ AS $$
+ DECLARE
+ _count bigint;
+ rtn_agg agg_count;
BEGIN
- -- nband
- IF nband < 1 THEN
- RAISE WARNING 'Invalid band index (must use 1-based). Returning NULL';
- RETURN NULL;
- END IF;
- -- sample percent
- IF sample_percent < 0 OR sample_percent > 1 THEN
- RAISE WARNING 'Invalid sample percentage (must be between 0 and 1). Returning NULL';
- RETURN NULL;
+ -- only process parameter args once
+ IF agg IS NULL THEN
+ rtn_agg.count := 0;
+
+ IF nband < 1 THEN
+ RAISE EXCEPTION 'Band index must be greater than zero (1-based)';
+ ELSE
+ rtn_agg.nband := nband;
+ END IF;
+
+ IF exclude_nodata_value IS FALSE THEN
+ rtn_agg.exclude_nodata_value := FALSE;
+ ELSE
+ rtn_agg.exclude_nodata_value := TRUE;
+ END IF;
+
+ IF sample_percent < 0. OR sample_percent > 1. THEN
+ RAISE EXCEPTION 'Sample percent must be between zero and one';
+ ELSE
+ rtn_agg.sample_percent := sample_percent;
+ END IF;
+ ELSE
+ rtn_agg := agg;
END IF;
- -- exclude_nodata_value IS TRUE
- IF exclude_nodata_value IS TRUE THEN
- SELECT count INTO rtn FROM _st_summarystats($1, $2, $3, $4, $5);
- RETURN rtn;
+ IF rast IS NOT NULL THEN
+ IF rtn_agg.exclude_nodata_value IS FALSE THEN
+ SELECT width * height INTO _count FROM ST_Metadata(rast);
+ ELSE
+ SELECT count INTO _count FROM _st_summarystats(
+ rast,
+ rtn_agg.nband, rtn_agg.exclude_nodata_value,
+ rtn_agg.sample_percent
+ );
+ END IF;
END IF;
- -- clean rastertable and rastercolumn
- ctable := quote_ident(rastertable);
- ccolumn := quote_ident(rastercolumn);
+ rtn_agg.count := rtn_agg.count + _count;
+ RETURN rtn_agg;
+ END;
+ $$ LANGUAGE 'plpgsql' IMMUTABLE;
- BEGIN
- OPEN curs FOR EXECUTE 'SELECT '
- || ccolumn
- || ' FROM '
- || ctable
- || ' WHERE '
- || ccolumn
- || ' IS NOT NULL';
- EXCEPTION
- WHEN OTHERS THEN
- RAISE WARNING 'Invalid table or column name. Returning NULL';
- RETURN NULL;
- END;
+CREATE OR REPLACE FUNCTION _st_countagg_transfn(
+ agg agg_count,
+ rast raster,
+ nband integer, exclude_nodata_value boolean,
+ sample_percent double precision
+)
+ RETURNS agg_count
+ AS $$
+ DECLARE
+ rtn_agg agg_count;
+ BEGIN
+ rtn_agg := __st_countagg_transfn(
+ agg,
+ rast,
+ nband, exclude_nodata_value,
+ sample_percent
+ );
+ RETURN rtn_agg;
+ END;
+ $$ LANGUAGE 'plpgsql' IMMUTABLE;
- rtn := 0;
- LOOP
- FETCH curs INTO rast;
- EXIT WHEN NOT FOUND;
+CREATE AGGREGATE st_countagg(
+ raster,
+ integer, boolean,
+ double precision
+) (
+ SFUNC = _st_countagg_transfn,
+ STYPE = agg_count,
+ FINALFUNC = _st_countagg_finalfn
+);
- SELECT (width * height) INTO tmp FROM ST_Metadata(rast);
- rtn := rtn + tmp;
- END LOOP;
+CREATE OR REPLACE FUNCTION _st_countagg_transfn(
+ agg agg_count,
+ rast raster,
+ nband integer, exclude_nodata_value boolean
+)
+ RETURNS agg_count
+ AS $$
+ DECLARE
+ rtn_agg agg_count;
+ BEGIN
+ rtn_agg := __st_countagg_transfn(
+ agg,
+ rast,
+ nband, exclude_nodata_value,
+ 1
+ );
+ RETURN rtn_agg;
+ END;
+ $$ LANGUAGE 'plpgsql' IMMUTABLE;
- CLOSE curs;
+CREATE AGGREGATE st_countagg(
+ raster,
+ integer, boolean
+) (
+ SFUNC = _st_countagg_transfn,
+ STYPE = agg_count,
+ FINALFUNC = _st_countagg_finalfn
+);
- RETURN rtn;
+CREATE OR REPLACE FUNCTION _st_countagg_transfn(
+ agg agg_count,
+ rast raster,
+ exclude_nodata_value boolean
+)
+ RETURNS agg_count
+ AS $$
+ DECLARE
+ rtn_agg agg_count;
+ BEGIN
+ rtn_agg := __st_countagg_transfn(
+ agg,
+ rast,
+ 1, exclude_nodata_value,
+ 1
+ );
+ RETURN rtn_agg;
END;
- $$ LANGUAGE 'plpgsql' STABLE STRICT;
+ $$ LANGUAGE 'plpgsql' IMMUTABLE;
+
+CREATE AGGREGATE st_countagg(raster, boolean) (
+ SFUNC = _st_countagg_transfn,
+ STYPE = agg_count,
+ FINALFUNC = _st_countagg_finalfn
+);
+
+-----------------------------------------------------------------------
+-- ST_Count for table
+-----------------------------------------------------------------------
+
+CREATE OR REPLACE FUNCTION _st_count(rastertable text, rastercolumn text, nband integer DEFAULT 1, exclude_nodata_value boolean DEFAULT TRUE, sample_percent double precision DEFAULT 1)
+ RETURNS bigint
+ AS $$
+ DECLARE
+ count bigint;
+ BEGIN
+ EXECUTE 'SELECT ST_CountAgg('
+ || quote_ident($2) || ', '
+ || $3 || ', '
+ || $4 || ', '
+ || $5 || ') '
+ || 'FROM ' || quote_ident($1)
+ INTO count;
+ RETURN count;
+ END;
+ $$ LANGUAGE 'plpgsql' STABLE STRICT;
CREATE OR REPLACE FUNCTION st_count(rastertable text, rastercolumn text, nband int DEFAULT 1, exclude_nodata_value boolean DEFAULT TRUE)
RETURNS bigint
-----------------------------------------------------------------------
-- ST_Histogram and ST_ApproxHistogram
-----------------------------------------------------------------------
+
-- Cannot be strict as "width", "min" and "max" can be NULL
CREATE OR REPLACE FUNCTION _st_histogram(
rast raster, nband int DEFAULT 1,
DROP AGGREGATE IF EXISTS ST_SummaryStatsAgg(raster, integer, boolean, double precision);
DROP AGGREGATE IF EXISTS ST_SummaryStatsAgg(raster, boolean, double precision);
DROP AGGREGATE IF EXISTS ST_SummaryStatsAgg(raster, integer, boolean);
+
+-- drop aggregates
+DROP AGGREGATE IF EXISTS ST_CountAgg(raster, integer, boolean, double precision);
+DROP AGGREGATE IF EXISTS ST_CountAgg(raster, integer, boolean);
+DROP AGGREGATE IF EXISTS ST_CountAgg(raster, boolean);
SELECT ST_Count('test', 'rast', 1);
SELECT ST_Count('test', 'rast', FALSE);
SELECT ST_Count('test', 'rast');
+
+SELECT ST_CountAgg(rast, 1, TRUE, 1) FROM test;
+SELECT ST_CountAgg(rast, 1, TRUE, 0) FROM test;
+SELECT ST_CountAgg(rast, 1, FALSE, 1) FROM test;
+SELECT ST_CountAgg(rast, 1, FALSE, 0) FROM test;
+SELECT ST_CountAgg(rast, 1, TRUE) FROM test;
+SELECT ST_CountAgg(rast, 1, FALSE) FROM test;
+SELECT ST_CountAgg(rast, TRUE) FROM test;
+SELECT ST_CountAgg(rast, FALSE) FROM test;
+
+SAVEPOINT test;
+SELECT ST_CountAgg(rast, 2, TRUE) FROM test;
+ROLLBACK TO SAVEPOINT test;
+RELEASE SAVEPOINT test;
+
+SAVEPOINT test;
+SELECT ST_CountAgg(rast, 1, TRUE, 2) FROM test;
+ROLLBACK TO SAVEPOINT test;
+RELEASE SAVEPOINT test;
+
ROLLBACK;
20
1000
20
+20
+20
+1000
+1000
+20
+1000
+20
+1000
+SAVEPOINT
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+NOTICE: Invalid band index (must use 1-based). Returning NULL
+COMMIT
+RELEASE
+SAVEPOINT
+ERROR: Sample percent must be between zero and one
+COMMIT
+RELEASE
COMMIT