\set ECHO 0 BEGIN; \set QUIET 1 \i sql/explanation.sql -- Set up the names of the columns to select CREATE FUNCTION mycols () RETURNS TEXT [] LANGUAGE SQL AS $$ SELECT ARRAY[ 'planned_at', 'node_id', 'parent_id', 'node_type', 'total_runtime', 'strategy', 'operation', 'startup_cost', 'total_cost', 'plan_rows', 'plan_width', 'actual_startup_time', 'actual_total_time', 'actual_rows', 'actual_loops', 'parent_relationship', 'sort_key', 'sort_method', 'sort_space_used', 'sort_space_type', 'join_type', 'join_filter', 'hash_cond', 'relation_name', 'alias', 'scan_direction', 'index_name', 'index_cond', 'recheck_cond', 'tid_cond', 'merge_cond', 'subplan_name', 'function_name', 'function_call', 'filter', 'one_time_filter', 'command', 'shared_hit_blocks', 'shared_read_blocks', 'shared_written_blocks', 'local_hit_blocks', 'local_read_blocks', 'local_written_blocks', 'temp_read_blocks', 'temp_written_blocks', 'output', 'hash_buckets', 'hash_batches', 'original_hash_batches', 'peak_memory_usage', 'schema', 'cte_name', 'triggers' ]; $$; -- Need to mock md5() so that it emits known values, so the tests will pass. CREATE SCHEMA mock; CREATE TEMPORARY SEQUENCE md5seq; CREATE TEMPORARY TABLE md5s ( md5 TEXT, id INTEGER DEFAULT NEXTVAL('md5seq') ); INSERT INTO md5s VALUES ('6e9d7e0628d306480fece89e8483fe6e'), ('b012abc1673778343cb1b89aae1e9b94'), ('029dde3a3c872f0c960f03d2ecfaf5ee'), ('3e4c4968cee7653037613c234a953be1'), ('dd3d1b1fb6c70be827075e01b306250c'), ('037a8fe70739ed1be6a3006d0ab80c82'), ('2c4e922dc19ce9f01a3bf08fbd76b041'), ('709b2febd8e560dd8830f4c7277c3758'), ('9dd89be09ea07a1000a21cbfc09121c7'), ('8dc3d35ab978f6c6e46f7927e7b86d21'), ('3d7c72f13ae7571da70f434b5bc9e0af'); CREATE FUNCTION mock.md5(TEXT) RETURNS TEXT LANGUAGE plpgsql AS $$ DECLARE rec md5s; BEGIN SELECT * INTO rec FROM md5s WHERE id = (SELECT MIN(id) FROM md5s); DELETE FROM md5s WHERE id = rec.id; RETURN rec.md5; END; $$; -- Mock now(), too. CREATE FUNCTION mock.now() RETURNS TIMESTAMPTZ LANGUAGE SQL AS $$ SELECT '2010-11-08 19:21:19.817375+00'::timestamptz; $$; SET search_path = mock,public,pg_catalog; SET DateStyle = 'ISO'; SET IntervalStyle = 'postgres'; SET timezone = 'UTC'; -- Okay, now on with the tests. Create a table to query against. CREATE TABLE foo(id int); \set QUIET 0 -- Plan an explain and an explain analyze. SELECT * FROM explanation('select * from foo', false, mycols()); -- Plan an explain analyze. Omit imes because it varies. :-( SELECT planned_at = NOW() AS have_planned_at, node_id, parent_id, node_type, total_runtime IS NOT NULL AS have_total_runtime, strategy, operation, startup_cost, total_cost, plan_rows, plan_width, actual_startup_time IS NOT NULL AS have_actual_startup_time, actual_total_time IS NOT NULL AS have_actual_Total_time, actual_rows, actual_loops, parent_relationship, sort_key, sort_method, sort_space_used, sort_space_type, join_type, join_filter, hash_cond, relation_name, alias, scan_direction, index_name, index_cond, recheck_cond, tid_cond, merge_cond, subplan_name, function_name, function_call, filter, one_time_filter, command, shared_hit_blocks, shared_read_blocks, shared_written_blocks, local_hit_blocks, local_read_blocks, local_written_blocks, temp_read_blocks, temp_written_blocks, output, hash_buckets, hash_batches, original_hash_batches, peak_memory_usage, schema, cte_name FROM explanation('select * from foo', true, mycols()); -- Make sure parse_node() recurses. SELECT * FROM parse_node(mycols(), $$ Aggregate Sorted 258.13 262.31 4 324 0.121 0.121 0 1 Sort Outer 258.13 258.14 4 324 0.117 0.117 0 1 d.name d.version d.abstract d.description d.relstatus d.owner d.sha1 d.meta quicksort 25 Memory Nested Loop Outer Left 16.75 258.09 4 324 0.009 0.009 0 1 (semver_cmp(d.version, dt.version) = 0) Hash Join Outer Inner 16.75 253.06 4 292 0.009 0.009 0 1 (de.distribution = d.name) (semver_cmp(d.version, de.dist_version) = 0) Seq Scan Outer distribution_extensions de 0.00 15.10 510 128 0.008 0.008 0 1 Hash Inner 13.00 13.00 300 228 0.000 0.000 0 0 Seq Scan Outer distributions d 0.00 13.00 300 228 0.000 0.000 0 0 Index Scan Inner NoMovement distribution_tags_pkey distribution_tags dt 0.00 0.46 3 96 0.000 0.000 0 0 (d.name = dt.distribution) Function Scan SubPlan SubPlan 1 unnest g 0.00 1.00 100 32 0.000 0.000 0 0 (x IS NOT NULL) $$); SELECT * FROM parse_node('{}'::text[], $$ Aggregate Sorted 258.13 262.31 4 324 0.121 0.121 0 1 Sort Outer 258.13 258.14 4 324 0.117 0.117 0 1 d.name d.version d.abstract d.description d.relstatus d.owner d.sha1 d.meta quicksort 25 Memory Nested Loop Outer Left 16.75 258.09 4 324 0.009 0.009 0 1 (semver_cmp(d.version, dt.version) = 0) Hash Join Outer Inner 16.75 253.06 4 292 0.009 0.009 0 1 (de.distribution = d.name) (semver_cmp(d.version, de.dist_version) = 0) Seq Scan Outer distribution_extensions de 0.00 15.10 510 128 0.008 0.008 0 1 Hash Inner 13.00 13.00 300 228 0.000 0.000 0 0 Seq Scan Outer distributions d 0.00 13.00 300 228 0.000 0.000 0 0 Index Scan Inner NoMovement distribution_tags_pkey distribution_tags dt 0.00 0.46 3 96 0.000 0.000 0 0 (d.name = dt.distribution) Function Scan SubPlan SubPlan 1 unnest g 0.00 1.00 100 32 0.000 0.000 0 0 (x IS NOT NULL) $$); ROLLBACK;