From: Paul Ramsey Date: Tue, 20 Nov 2012 20:51:42 +0000 (+0000) Subject: #2102, SQL hooks for calling selectivity functions X-Git-Tag: 2.1.0beta2~375 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6ed9d34ed3f2482fc83fdccf531bf1ff43f07bc5;p=postgis #2102, SQL hooks for calling selectivity functions git-svn-id: http://svn.osgeo.org/postgis/trunk@10720 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/postgis/geometry_estimate.c b/postgis/geometry_estimate.c index 54b349fd9..d260ed80f 100644 --- a/postgis/geometry_estimate.c +++ b/postgis/geometry_estimate.c @@ -116,6 +116,7 @@ static float8 estimate_selectivity(GBOX *box, GEOM_STATS *geomstats); Datum geometry_gist_sel_2d(PG_FUNCTION_ARGS); Datum geometry_gist_joinsel_2d(PG_FUNCTION_ARGS); +Datum geometry_gist_read_selectivity(PG_FUNCTION_ARGS); Datum geometry_analyze_2d(PG_FUNCTION_ARGS); Datum geometry_estimated_extent(PG_FUNCTION_ARGS); @@ -609,6 +610,52 @@ estimate_selectivity(GBOX *box, GEOM_STATS *geomstats) return selectivity; } +/** +* Utility function to read the calculated selectivity for a given search +* box and table/column. Used for debugging the selectivity code. +*/ +PG_FUNCTION_INFO_V1(geometry_gist_read_selectivity); +Datum geometry_gist_read_selectivity(PG_FUNCTION_ARGS) +{ + HeapTuple stats_tuple; + float4 *floatptr; + int32 table_oid = PG_GETARG_INT32(0); + int32 attr_num = PG_GETARG_INT32(1); + Datum geom_datum = PG_GETARG_DATUM(2); + int rv; + GBOX gbox; + int32 nvalues = 0; + float8 selectivity = 0; + + /* Calculate the gbox */ + if ( ! gserialized_datum_get_gbox_p(geom_datum, &gbox) ) + elog(ERROR, "Unable to calculate search box from geometry"); + + /* First pull the stats tuple */ + stats_tuple = SearchSysCache2(STATRELATT, Int32GetDatum(table_oid), Int32GetDatum(attr_num)); + if ( ! stats_tuple ) + elog(ERROR, "Unable to retreive stats tuple for oid(%d) attrnum(%d)", table_oid, attr_num); + + /* Then read the geom status histogram from that */ + rv = get_attstatsslot(stats_tuple, 0, 0, STATISTIC_KIND_GEOMETRY, InvalidOid, NULL, NULL, NULL, &floatptr, &nvalues); + if ( ! rv ) + { + ReleaseSysCache(stats_tuple); + elog(ERROR, "Unable to retreive geomstats"); + } + + /* Do the estimation */ + selectivity = estimate_selectivity(&gbox, (GEOM_STATS*)floatptr); + + /* Clean up */ + free_attstatsslot(0, NULL, 0, floatptr, nvalues); + ReleaseSysCache(stats_tuple); + + PG_RETURN_FLOAT8(selectivity); +} + + + /** * This function should return an estimation of the number of * rows returned by a query involving an overlap check diff --git a/postgis/postgis.sql.in.c b/postgis/postgis.sql.in.c index 71ec381f3..664aeafb9 100644 --- a/postgis/postgis.sql.in.c +++ b/postgis/postgis.sql.in.c @@ -428,6 +428,35 @@ CREATE OR REPLACE FUNCTION geometry_gist_joinsel_2d(internal, oid, internal, sma AS 'MODULE_PATHNAME', 'geometry_gist_joinsel_2d' LANGUAGE 'c'; +-- Availability: 2.1.0 +CREATE OR REPLACE FUNCTION geometry_gist_read_selectivity(relid integer, attnum integer, geom geometry) + RETURNS float8 + AS 'MODULE_PATHNAME', 'geometry_gist_read_selectivity' + LANGUAGE 'c'; + +-- Availability: 2.1.0 +CREATE OR REPLACE FUNCTION geometry_gist_selectivity(schemaname varchar, tablename varchar, attrname varchar, geom geometry) + RETURNS float8 + AS $$ + DECLARE + selectivity float8; + BEGIN + SELECT geometry_gist_read_selectivity(r.oid::integer, a.attnum::integer, 'SRID=4326;LINESTRING(0 0, 1 1)'::geometry) + INTO selectivity + FROM pg_class r + JOIN pg_attribute a ON (r.oid = a.attrelid) + JOIN pg_namespace n ON (r.relnamespace = n.oid) + WHERE n.nspname = $1 AND r.relname = $2 and a.attname = $3; + IF NOT FOUND THEN + RAISE EXCEPTION 'Couldn''t find table? column?'; + END IF; + RETURN selectivity; + END; + $$ + LANGUAGE 'plpgsql'; + + + ----------------------------------------------------------------------------- -- GEOMETRY Operators -----------------------------------------------------------------------------