\set VERBOSITY terse SET search_path = 'public'; CREATE EXTENSION pg_pathman; CREATE SCHEMA array_qual; CREATE TABLE array_qual.test(val TEXT NOT NULL); CREATE SEQUENCE array_qual.test_seq; SELECT add_to_pathman_config('array_qual.test', 'val', NULL); SELECT add_range_partition('array_qual.test', 'a'::TEXT, 'b'); SELECT add_range_partition('array_qual.test', 'b'::TEXT, 'c'); SELECT add_range_partition('array_qual.test', 'c'::TEXT, 'd'); SELECT add_range_partition('array_qual.test', 'd'::TEXT, 'e'); INSERT INTO array_qual.test VALUES ('aaaa'); INSERT INTO array_qual.test VALUES ('bbbb'); INSERT INTO array_qual.test VALUES ('cccc'); ANALYZE; /* * Test expr op ANY (...) */ /* matching collations */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE val < ANY (array['a', 'b']); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE val < ANY (array['a', 'z']); /* different collations */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE val COLLATE "POSIX" < ANY (array['a', 'b']); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE val < ANY (array['a', 'b' COLLATE "POSIX"]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE val COLLATE "C" < ANY (array['a', 'b' COLLATE "POSIX"]); /* different collations (pruning should work) */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE val COLLATE "POSIX" = ANY (array['a', 'b']); /* non-btree operator */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE val ~~ ANY (array['a', 'b']); DROP TABLE array_qual.test CASCADE; CREATE TABLE array_qual.test(a INT4 NOT NULL, b INT4); SELECT create_range_partitions('array_qual.test', 'a', 1, 100, 10); INSERT INTO array_qual.test SELECT i, i FROM generate_series(1, 1000) g(i); ANALYZE; /* * Test expr IN (...) */ /* a IN (...) - pruning should work */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a IN (1, 2, 3, 4); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a IN (100, 200, 300, 400); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a IN (-100, 100); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a IN (-100, -200, -300); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a IN (-100, -200, -300, NULL); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a IN (NULL, NULL, NULL, NULL); /* b IN (...) - pruning should not work */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE b IN (1, 2, 3, 4); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE b IN (100, 200, 300, 400); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE b IN (-100, 100); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE b IN (-100, -200, -300); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE b IN (-100, -200, -300, NULL); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE b IN (NULL, NULL, NULL, NULL); /* * Test expr = ANY (...) */ /* a = ANY (...) - pruning should work */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ANY (NULL); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ANY (array[]::int4[]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ANY (array[100, 100]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ANY (array[100, 200, 300, 400]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ANY (array[array[100, 200], array[300, 400]]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ANY (array[array[100, 200], array[300, 400], array[NULL, NULL]::int4[]]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ANY (array[array[100, 200], array[300, NULL]]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ANY (array[NULL, NULL]::int4[]); /* * Test expr = ALL (...) */ /* a = ALL (...) - pruning should work */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ALL (NULL); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ALL (array[]::int4[]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ALL (array[100, 100]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ALL (array[100, 200, 300, 400]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ALL (array[array[100, 200], array[300, 400]]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ALL (array[array[100, 200], array[300, 400], array[NULL, NULL]::int4[]]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ALL (array[array[100, 200], array[300, NULL]]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a = ALL (array[NULL, NULL]::int4[]); /* * Test expr < ANY (...) */ /* a < ANY (...) - pruning should work */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ANY (NULL); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ANY (array[]::int4[]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ANY (array[100, 100]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ANY (array[99, 100, 101]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ANY (array[500, 550]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ANY (array[100, 700]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ANY (array[NULL, 700]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ANY (array[NULL, NULL]::int4[]); SET pg_pathman.enable = f; SELECT count(*) FROM array_qual.test WHERE a < ANY (array[NULL, 700]); SET pg_pathman.enable = t; SELECT count(*) FROM array_qual.test WHERE a < ANY (array[NULL, 700]); /* * Test expr < ALL (...) */ /* a < ALL (...) - pruning should work */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ALL (NULL); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ALL (array[]::int4[]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ALL (array[100, 100]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ALL (array[99, 100, 101]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ALL (array[500, 550]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ALL (array[100, 700]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ALL (array[NULL, 700]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a < ALL (array[NULL, NULL]::int4[]); SET pg_pathman.enable = f; SELECT count(*) FROM array_qual.test WHERE a < ALL (array[NULL, 700]); SET pg_pathman.enable = t; SELECT count(*) FROM array_qual.test WHERE a < ALL (array[NULL, 700]); /* * Test expr > ANY (...) */ /* a > ANY (...) - pruning should work */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ANY (NULL); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ANY (array[]::int4[]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ANY (array[100, 100]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ANY (array[99, 100, 101]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ANY (array[500, 550]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ANY (array[100, 700]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ANY (array[NULL, 700]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ANY (array[NULL, NULL]::int4[]); SET pg_pathman.enable = f; SELECT count(*) FROM array_qual.test WHERE a > ANY (array[NULL, 700]); SET pg_pathman.enable = t; SELECT count(*) FROM array_qual.test WHERE a > ANY (array[NULL, 700]); /* * Test expr > ALL (...) */ /* a > ALL (...) - pruning should work */ EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ALL (NULL); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ALL (array[]::int4[]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ALL (array[100, 100]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ALL (array[99, 100, 101]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ALL (array[500, 550]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ALL (array[100, 700]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ALL (array[NULL, 700]); EXPLAIN (COSTS OFF) SELECT * FROM array_qual.test WHERE a > ALL (array[NULL, NULL]::int4[]); SET pg_pathman.enable = f; SELECT count(*) FROM array_qual.test WHERE a > ALL (array[NULL, 700]); SET pg_pathman.enable = t; SELECT count(*) FROM array_qual.test WHERE a > ALL (array[NULL, 700]); /* * Test expr > ANY (... $1 ...) */ PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ANY (array[$1, 100, 600]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ANY (array[100, 600, $1]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ANY (array[NULL, $1]); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXECUTE q(NULL); DEALLOCATE q; /* * Test expr > ALL (... $1 ...) */ PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ALL (array[$1, 1000000, 600]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ALL (array[$1, NULL, 600]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ALL (array[NULL, $1, NULL]); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXPLAIN (COSTS OFF) EXECUTE q(500); EXECUTE q(NULL); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ALL (array[$1, 100, 600]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ALL (array[100, $1, 600]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ALL (array[100, 600, $1]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ALL (array[array[100, NULL], array[1, $1]]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ALL (array[array[100, 600], array[1, $1]]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(999); /* check query plan: EXECUTE q(999) */ DO language plpgsql $$ DECLARE query text; result jsonb; num int; BEGIN query := 'EXECUTE q(999)'; EXECUTE format('EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, FORMAT JSON) %s', query) INTO result; SELECT count(*) FROM jsonb_array_elements_text(result->0->'Plan'->'Plans') INTO num; RAISE notice '%: number of partitions: %', query, num; END $$; DEALLOCATE q; PREPARE q(int4[]) AS SELECT * FROM array_qual.test WHERE a > ALL (array[array[100, 600], $1]); EXPLAIN (COSTS OFF) EXECUTE q('{1, 1}'); EXPLAIN (COSTS OFF) EXECUTE q('{1, 1}'); EXPLAIN (COSTS OFF) EXECUTE q('{1, 1}'); EXPLAIN (COSTS OFF) EXECUTE q('{1, 1}'); EXPLAIN (COSTS OFF) EXECUTE q('{1, 1}'); EXPLAIN (COSTS OFF) EXECUTE q('{1, 1}'); EXPLAIN (COSTS OFF) EXECUTE q('{1, 1}'); EXPLAIN (COSTS OFF) EXECUTE q('{1, 999}'); /* check query plan: EXECUTE q('{1, 999}') */ DO language plpgsql $$ DECLARE query text; result jsonb; num int; BEGIN query := 'EXECUTE q(''{1, 999}'')'; EXECUTE format('EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, FORMAT JSON) %s', query) INTO result; SELECT count(*) FROM jsonb_array_elements_text(result->0->'Plan'->'Plans') INTO num; RAISE notice '%: number of partitions: %', query, num; END $$; DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a > ALL (array[$1, 898]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(900); /* check quals optimization */ EXECUTE q(1000); /* check query plan: EXECUTE q(999) */ DO language plpgsql $$ DECLARE query text; result jsonb; num int; BEGIN query := 'EXECUTE q(999)'; EXECUTE format('EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, FORMAT JSON) %s', query) INTO result; SELECT count(*) FROM jsonb_array_elements_text(result->0->'Plan'->'Plans') INTO num; RAISE notice '%: number of partitions: %', query, num; END $$; DEALLOCATE q; /* * Test expr = ALL (... $1 ...) */ PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a = ALL (array[$1, 100, 600]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a = ALL (array[100, 600, $1]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); DEALLOCATE q; PREPARE q(int4) AS SELECT * FROM array_qual.test WHERE a = ALL (array[100, $1]); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXPLAIN (COSTS OFF) EXECUTE q(1); EXECUTE q(1); EXECUTE q(100); DEALLOCATE q; DROP SCHEMA array_qual CASCADE; DROP EXTENSION pg_pathman;