-- pg_lion's create_upper_paths_hook installed AFTER another extension's, so -- pg_lion's is the one core calls and it chains to the other. Without a -- preload this is LOAD-on-first-use: lion_hooktest is LOADed, and pg_lion is -- loaded by the planner in the middle of planning the first query that -- touches a lion index; with shared_preload_libraries = 'lion_hooktest, -- pg_lion' the order is the same and the loads below are no-ops. \set VERBOSITY terse LOAD 'lion_hooktest'; SELECT lion_hooktest_reset(); lion_hooktest_reset --------------------- (1 row) -- the first query over a lion index: pushed down, and exact EXPLAIN (COSTS OFF) SELECT count(*) FROM hk WHERE k = 3; QUERY PLAN ------------------------------ Custom Scan (LionCount) Lion Indexes: hk_k (k = 3) (2 rows) SELECT count(*) FROM hk WHERE k = 3; count ------- 1000 (1 row) EXPLAIN (COSTS OFF) SELECT g, count(*) FROM hk WHERE k IN (1, 2) GROUP BY g; QUERY PLAN --------------------------------------------------------------- Custom Scan (LionCount) Lion Indexes: hk_g (g), hk_k (k = ANY ('{1,2}'::integer[])) Group Key: g (3 rows) SELECT g, count(*) FROM hk WHERE k IN (1, 2) GROUP BY g ORDER BY g; g | count ---+------- 1 | 1000 2 | 1000 (2 rows) EXPLAIN (COSTS OFF) SELECT k, count(*) FROM hk_p GROUP BY k; QUERY PLAN ---------------------------------- Finalize HashAggregate Group Key: hk_p.k -> Custom Scan (LionCount) Partitions: hk_p1, hk_p2 Lion Indexes: (k) Group Key: k (6 rows) SELECT k, count(*) FROM hk_p WHERE k IN (0, 7, 19) GROUP BY k ORDER BY k; k | count ----+------- 0 | 1000 7 | 1000 19 | 1000 (3 rows) -- the other hook ran on every query, and before pg_lion added its path SELECT lion_hooktest_calls() > 0 AS hooktest_ran, lion_hooktest_saw_lion() AS hooktest_saw_lion_path; hooktest_ran | hooktest_saw_lion_path --------------+------------------------ t | 0 (1 row) -- the same answers without the pushdown SET pg_lion.enable_count_pushdown = off; SELECT count(*) FROM hk WHERE k = 3; count ------- 1000 (1 row) SELECT g, count(*) FROM hk WHERE k IN (1, 2) GROUP BY g ORDER BY g; g | count ---+------- 1 | 1000 2 | 1000 (2 rows) SELECT k, count(*) FROM hk_p WHERE k IN (0, 7, 19) GROUP BY k ORDER BY k; k | count ----+------- 0 | 1000 7 | 1000 19 | 1000 (3 rows) RESET pg_lion.enable_count_pushdown; -- the LionOrdered scan (DESIGN.md ยง30), which set_rel_pathlist_hook adds, -- chained the same way: the lion filter k = 3 over a walk of the btree on v. -- The rel hook's counters start here: pg_lion offers ordered paths for the -- queries above too (an ORDER BY of a lion column walks that column). SELECT lion_hooktest_reset(); lion_hooktest_reset --------------------- (1 row) SET enable_seqscan = off; SET enable_bitmapscan = off; SET pg_lion.enable_plain_scan = off; SET enable_indexonlyscan = off; SET pg_lion.pushdown_margin = 1000; EXPLAIN (COSTS OFF) SELECT v FROM hk WHERE k = 3 ORDER BY v LIMIT 5; QUERY PLAN --------------------------------------- Limit -> Custom Scan (LionOrdered) on hk Ordered By: hk_v Lion Cond: (k = 3) Lion Indexes: hk_k (5 rows) SELECT v FROM hk WHERE k = 3 ORDER BY v LIMIT 5; v ---- 3 23 43 63 83 (5 rows) RESET enable_seqscan; RESET enable_bitmapscan; RESET pg_lion.enable_plain_scan; RESET enable_indexonlyscan; RESET pg_lion.pushdown_margin; SET pg_lion.enable_ordered_scan = off; SELECT v FROM hk WHERE k = 3 ORDER BY v LIMIT 5; v ---- 3 23 43 63 83 (5 rows) RESET pg_lion.enable_ordered_scan; -- the other rel hook ran first, before pg_lion added its path SELECT lion_hooktest_rel_calls() > 0 AS rel_hook_ran, lion_hooktest_rel_saw_ordered() AS rel_hook_saw_ordered_path; rel_hook_ran | rel_hook_saw_ordered_path --------------+--------------------------- t | 0 (1 row) -- both prefixes are reserved SET pg_lion.no_such_setting = 1; ERROR: invalid configuration parameter name "pg_lion.no_such_setting" SET lion_hooktest.no_such_setting = 1; ERROR: invalid configuration parameter name "lion_hooktest.no_such_setting"