Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ REGRESS = aqo_disabled \
top_queries

fdw_srcdir = $(top_srcdir)/contrib/postgres_fdw
PG_CPPFLAGS += -I$(libpq_srcdir) -I$(fdw_srcdir)
stat_srcdir = $(top_srcdir)/contrib/pg_stat_statements
PG_CPPFLAGS += -I$(libpq_srcdir) -I$(fdw_srcdir) -I$(stat_srcdir)
EXTRA_REGRESS_OPTS=--temp-config=$(top_srcdir)/$(subdir)/conf.add
EXTRA_INSTALL = contrib/postgres_fdw
EXTRA_INSTALL = contrib/postgres_fdw contrib/pg_stat_statements

DATA = aqo--1.0.sql aqo--1.0--1.1.sql aqo--1.1--1.2.sql aqo--1.2.sql \
aqo--1.2--1.3.sql
Expand Down
1 change: 1 addition & 0 deletions aqo.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ _PG_init(void)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("AQO module could be loaded only on startup."),
errdetail("Add 'aqo' into the shared_preload_libraries list.")));
EnableQueryId();

DefineCustomEnumVariable("aqo.mode",
"Mode of aqo usage.",
Expand Down
113 changes: 70 additions & 43 deletions expected/aqo_fdw.out
Original file line number Diff line number Diff line change
Expand Up @@ -16,51 +16,59 @@ DO $d$
)$$;
END;
$d$;
--
-- Returns string-by-string explain of a query. Made for removing some strings
-- from the explain output.
--
CREATE OR REPLACE FUNCTION expln(query_string text default 'select * from table', verbose_p boolean default TRUE) RETURNS SETOF text AS $$
BEGIN
IF verbose_p=TRUE THEN
RETURN QUERY EXECUTE format('EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) %s', query_string);
else
RETURN QUERY EXECUTE format('EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) %s', query_string);
END IF;
Return;
END;
$$ LANGUAGE PLPGSQL;
CREATE USER MAPPING FOR PUBLIC SERVER loopback;
CREATE TABLE local (x int);
CREATE FOREIGN TABLE frgn(x int) SERVER loopback OPTIONS (table_name 'local');
INSERT INTO frgn (x) VALUES (1);
ANALYZE local;
-- Utility tool. Allow to filter system-dependent strings from explain output.
CREATE FUNCTION expln(query_string text) RETURNS SETOF text AS $$
BEGIN
RETURN QUERY
EXECUTE format('%s', query_string);
RETURN;
END;
$$ LANGUAGE PLPGSQL;

-- Trivial foreign scan.
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT x FROM frgn;
QUERY PLAN
----------------------------------------------
Foreign Scan on frgn (actual rows=1 loops=1)
AQO not used
Output: x
Remote SQL: SELECT x FROM public.local
Using aqo: true
AQO mode: LEARN
JOINS: 0
(5 rows)
(7 rows)

EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT x FROM frgn;
QUERY PLAN
----------------------------------------------
Foreign Scan on frgn (actual rows=1 loops=1)
SELECT str AS result
FROM expln('SELECT x FROM frgn;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
result
-----------------------------------------------------
Foreign Scan on public.frgn (actual rows=1 loops=1)
AQO: rows=1, error=0%
Output: x
Remote SQL: SELECT x FROM public.local
Using aqo: true
AQO mode: LEARN
JOINS: 0
(5 rows)
(7 rows)

-- Push down base filters. Use verbose mode to see filters.
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE))
SELECT x FROM frgn WHERE x < 10;
ERROR: syntax error at or near ")"
LINE 1: ...LAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE))
^
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE)
SELECT x FROM frgn WHERE x < 10;
QUERY PLAN
SELECT str AS result
FROM expln('SELECT x FROM frgn WHERE x < 10;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
result
-----------------------------------------------------------
Foreign Scan on public.frgn (actual rows=1 loops=1)
AQO not used
Expand All @@ -71,23 +79,39 @@ SELECT x FROM frgn WHERE x < 10;
JOINS: 0
(7 rows)

EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT x FROM frgn WHERE x < -10; -- AQO ignores constants
QUERY PLAN
----------------------------------------------
Foreign Scan on frgn (actual rows=0 loops=1)
SELECT str AS result
FROM expln('SELECT x FROM frgn WHERE x < 10;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
result
-----------------------------------------------------------
Foreign Scan on public.frgn (actual rows=1 loops=1)
AQO: rows=1, error=0%
Output: x
Remote SQL: SELECT x FROM public.local WHERE ((x < 10))
Using aqo: true
AQO mode: LEARN
JOINS: 0
(7 rows)

SELECT str AS result
FROM expln('SELECT x FROM frgn WHERE x < -10;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%'; -- AQO ignores constants
result
--------------------------------------------------------------
Foreign Scan on public.frgn (actual rows=0 loops=1)
AQO: rows=1, error=100%
Output: x
Remote SQL: SELECT x FROM public.local WHERE ((x < (-10)))
Using aqo: true
AQO mode: LEARN
JOINS: 0
(5 rows)
(7 rows)

-- Trivial JOIN push-down.
SELECT str FROM expln('
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;
') AS str WHERE str NOT LIKE '%Sort Method%';
str
SELECT str AS result
FROM expln('SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;', FALSE) AS str
WHERE str NOT LIKE 'Query Identifier%';
result
------------------------------------------------------------
Merge Join (actual rows=1 loops=1)
AQO not used
Expand All @@ -107,9 +131,10 @@ SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;
JOINS: 0
(16 rows)

EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE)
SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;
QUERY PLAN
SELECT str AS result
FROM expln('SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
result
--------------------------------------------------------------------------------------------------------
Foreign Scan (actual rows=1 loops=1)
AQO: rows=1, error=0%
Expand All @@ -122,9 +147,10 @@ SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;
(8 rows)

-- TODO: Non-mergejoinable join condition.
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT * FROM frgn AS a, frgn AS b WHERE a.x<b.x;
QUERY PLAN
SELECT str AS result
FROM expln('SELECT * FROM frgn AS a, frgn AS b WHERE a.x<b.x;', FALSE) AS str
WHERE str NOT LIKE 'Query Identifier%';
result
-------------------------------------------
Foreign Scan (actual rows=0 loops=1)
AQO not used
Expand All @@ -134,9 +160,10 @@ SELECT * FROM frgn AS a, frgn AS b WHERE a.x<b.x;
JOINS: 0
(6 rows)

EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE)
SELECT * FROM frgn AS a, frgn AS b WHERE a.x<b.x;
QUERY PLAN
SELECT str AS result
FROM expln('SELECT * FROM frgn AS a, frgn AS b WHERE a.x<b.x;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
result
--------------------------------------------------------------------------------------------------------
Foreign Scan (actual rows=0 loops=1)
AQO not used
Expand Down
28 changes: 22 additions & 6 deletions expected/gucs.out
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
CREATE EXTENSION aqo;
SET aqo.mode = 'learn';
SET aqo.show_details = true;
--
-- Returns string-by-string explain of a query. Made for removing some strings
-- from the explain output.
--
CREATE OR REPLACE FUNCTION expln(query_string text default 'select * from table', verbose_p boolean default TRUE) RETURNS SETOF text AS $$
BEGIN
IF verbose_p=TRUE THEN
RETURN QUERY EXECUTE format('EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) %s', query_string);
else
RETURN QUERY EXECUTE format('EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) %s', query_string);
END IF;
Return;
END;
$$ LANGUAGE PLPGSQL;
CREATE TABLE t(x int);
INSERT INTO t (x) (SELECT * FROM generate_series(1, 100) AS gs);
ANALYZE t;
EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF)
SELECT x FROM t;
QUERY PLAN
SELECT str AS result
FROM expln('SELECT x FROM t;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
result
------------------------------------------------
Seq Scan on public.t (actual rows=100 loops=1)
AQO not used
Expand All @@ -16,9 +31,10 @@ EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF)
JOINS: 0
(6 rows)

EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF)
SELECT x FROM t;
QUERY PLAN
SELECT str AS result
FROM expln('SELECT x FROM t;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
result
------------------------------------------------
Seq Scan on public.t (actual rows=100 loops=1)
AQO: rows=100, error=0%
Expand Down
12 changes: 11 additions & 1 deletion preprocessing.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,17 @@ aqo_planner(Query *parse,
}

selectivity_cache_clear();
query_context.query_hash = get_query_hash(parse, query_string);
/*
* TODO: this part of code ought to be clarified to clear understanding of
* such situation.
*/
if (parse->queryId == UINT64CONST(0))
JumbleQuery(parse, query_string);

Assert(parse->utilityStmt == NULL);
Assert(parse->queryId != UINT64CONST(0));

query_context.query_hash = (int) parse->queryId;

if (query_is_deactivated(query_context.query_hash) ||
list_member_uint64(cur_classes,query_context.query_hash))
Expand Down
60 changes: 35 additions & 25 deletions sql/aqo_fdw.sql
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ DO $d$
)$$;
END;
$d$;
--
-- Returns string-by-string explain of a query. Made for removing some strings
-- from the explain output.
--
CREATE OR REPLACE FUNCTION expln(query_string text default 'select * from table', verbose_p boolean default TRUE) RETURNS SETOF text AS $$
BEGIN
IF verbose_p=TRUE THEN
RETURN QUERY EXECUTE format('EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) %s', query_string);
else
RETURN QUERY EXECUTE format('EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) %s', query_string);
END IF;
Return;
END;
$$ LANGUAGE PLPGSQL;

CREATE USER MAPPING FOR PUBLIC SERVER loopback;

Expand All @@ -26,42 +40,38 @@ CREATE FOREIGN TABLE frgn(x int) SERVER loopback OPTIONS (table_name 'local');
INSERT INTO frgn (x) VALUES (1);
ANALYZE local;

-- Utility tool. Allow to filter system-dependent strings from explain output.
CREATE FUNCTION expln(query_string text) RETURNS SETOF text AS $$
BEGIN
RETURN QUERY
EXECUTE format('%s', query_string);
RETURN;
END;
$$ LANGUAGE PLPGSQL;

-- Trivial foreign scan.
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT x FROM frgn;
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT x FROM frgn;

-- Push down base filters. Use verbose mode to see filters.
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE))
SELECT x FROM frgn WHERE x < 10;
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE)
SELECT x FROM frgn WHERE x < 10;
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT x FROM frgn WHERE x < -10; -- AQO ignores constants
SELECT str AS result
FROM expln('SELECT x FROM frgn WHERE x < 10;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
SELECT str AS result
FROM expln('SELECT x FROM frgn WHERE x < 10;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
SELECT str AS result
FROM expln('SELECT x FROM frgn WHERE x < -10;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%'; -- AQO ignores constants

-- Trivial JOIN push-down.
SELECT str FROM expln('
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;
') AS str WHERE str NOT LIKE '%Sort Method%';
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE)
SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;
SELECT str AS result
FROM expln('SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;', FALSE) AS str
WHERE str NOT LIKE 'Query Identifier%';
SELECT str AS result
FROM expln('SELECT * FROM frgn AS a, frgn AS b WHERE a.x=b.x;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';

-- TODO: Non-mergejoinable join condition.
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
SELECT * FROM frgn AS a, frgn AS b WHERE a.x<b.x;
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF, VERBOSE)
SELECT * FROM frgn AS a, frgn AS b WHERE a.x<b.x;
SELECT str AS result
FROM expln('SELECT * FROM frgn AS a, frgn AS b WHERE a.x<b.x;', FALSE) AS str
WHERE str NOT LIKE 'Query Identifier%';
SELECT str AS result
FROM expln('SELECT * FROM frgn AS a, frgn AS b WHERE a.x<b.x;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';

DROP EXTENSION aqo CASCADE;
DROP EXTENSION postgres_fdw CASCADE;
Expand Down
25 changes: 21 additions & 4 deletions sql/gucs.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,31 @@ CREATE EXTENSION aqo;
SET aqo.mode = 'learn';
SET aqo.show_details = true;

--
-- Returns string-by-string explain of a query. Made for removing some strings
-- from the explain output.
--
CREATE OR REPLACE FUNCTION expln(query_string text default 'select * from table', verbose_p boolean default TRUE) RETURNS SETOF text AS $$
BEGIN
IF verbose_p=TRUE THEN
RETURN QUERY EXECUTE format('EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF) %s', query_string);
else
RETURN QUERY EXECUTE format('EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF, SUMMARY OFF) %s', query_string);
END IF;
Return;
END;
$$ LANGUAGE PLPGSQL;

CREATE TABLE t(x int);
INSERT INTO t (x) (SELECT * FROM generate_series(1, 100) AS gs);
ANALYZE t;

EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF)
SELECT x FROM t;
EXPLAIN (ANALYZE, VERBOSE, COSTS OFF, TIMING OFF, SUMMARY OFF)
SELECT x FROM t;
SELECT str AS result
FROM expln('SELECT x FROM t;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';
SELECT str AS result
FROM expln('SELECT x FROM t;', TRUE) AS str
WHERE str NOT LIKE 'Query Identifier%';

DROP EXTENSION aqo;

Expand Down
Loading