-- Create data table and index. Analyze.
CREATE TABLE boxen AS
	SELECT row_number() OVER() As gid,
		box(point(x, y),point(x+1, y+1)) AS b, x, y
	FROM generate_series(-100,100) As y, generate_series(-100,100) As x;
CREATE INDEX idx_b_geom_gist ON boxen USING gist(b);
ANALYZE boxen;

-- An inlined function
-- When set 'STRICT' it breaks index access
-- However 'IMMUTABLE' doesn't seem to bother it
CREATE OR REPLACE FUNCTION good_box(box, box)
	RETURNS boolean
		AS 'SELECT $1 OPERATOR(&&) $2 AND length(lseg(point($1),point($2))) < 3'
	LANGUAGE 'sql';

-- Start with a low cost circle()
ALTER FUNCTION circle(point, double precision) COST 1;

-- [A] Query plan hits index
EXPLAIN SELECT gid
FROM boxen
WHERE good_box(
	boxen.b,
	box(circle(point(20.5, 20.5), 2))
);

-- [B] Query plan hits index
EXPLAIN SELECT gid
FROM boxen,
	(SELECT x, y FROM boxen WHERE x < 0 and y < 0) AS c
WHERE good_box(
	boxen.b,
	box(circle(point(c.x, c.y), 2))
);

-- Increase cost of circle
ALTER FUNCTION circle(point, double precision) COST 100;

-- [B] Query plan does not hit index!
EXPLAIN SELECT gid
FROM boxen,
	(SELECT x, y FROM boxen WHERE x < 0 and y < 0) AS c
WHERE good_box(
	boxen.b,
	box(circle(point(c.x, c.y), 2))
);
