Skip to content

Commit dc34c2d

Browse files
committed
Do not push expressions having mutable functions to the remote server.
If an expression that includes a mutable function is sent on the remote server via remote query its result may not be stable. Instead, check if the expression has a mutable function, if yes do not send that expression to the remote MySQL server. Reported on GitHub as issue #226 by user robins. FDW-411, Suraj Kharage, reviewed by Vaibhav Dalvi.
1 parent 011c499 commit dc34c2d

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

deparse.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,6 +1871,16 @@ mysql_is_foreign_expr(PlannerInfo *root, RelOptInfo *baserel, Expr *expr,
18711871
Assert(loc_cxt.collation == InvalidOid);
18721872
Assert(loc_cxt.state == FDW_COLLATE_NONE);
18731873

1874+
/*
1875+
* An expression which includes any mutable functions can't be sent over
1876+
* because its result is not stable. For example, sending now() remote
1877+
* side could cause confusion from clock offsets. Future versions might
1878+
* be able to make this choice with more granularity. (We check this last
1879+
* because it requires a lot of expensive catalog lookups.)
1880+
*/
1881+
if (contain_mutable_functions((Node *) expr))
1882+
return false;
1883+
18741884
/* OK to evaluate on the remote server */
18751885
return true;
18761886
}

expected/select.out

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,6 +1402,35 @@ SELECT c1, sum(c7) FROM f_test_tbl1 t1
14021402
(14 rows)
14031403

14041404
ALTER SERVER mysql_svr options (SET use_remote_estimate 'false');
1405+
-- FDW-411: Volatile/immutable functions should not get pushed down to remote
1406+
-- MySQL server.
1407+
EXPLAIN (VERBOSE, COSTS OFF)
1408+
SELECT c1, c2, c3 FROM f_test_tbl1 WHERE pg_catalog.timeofday() IS NOT NULL
1409+
ORDER BY 1 limit 5;
1410+
QUERY PLAN
1411+
------------------------------------------------------------------------------------------
1412+
Limit
1413+
Output: c1, c2, c3
1414+
-> Sort
1415+
Output: c1, c2, c3
1416+
Sort Key: f_test_tbl1.c1
1417+
-> Foreign Scan on public.f_test_tbl1
1418+
Output: c1, c2, c3
1419+
Filter: (timeofday() IS NOT NULL)
1420+
Remote query: SELECT `c1`, `c2`, `c3` FROM `mysql_fdw_regress`.`test_tbl1`
1421+
(9 rows)
1422+
1423+
SELECT c1, c2, c3 FROM f_test_tbl1 WHERE pg_catalog.timeofday() IS NOT NULL
1424+
ORDER BY 1 limit 5;
1425+
c1 | c2 | c3
1426+
-----+------+----------
1427+
100 | EMP1 | ADMIN
1428+
200 | EMP2 | SALESMAN
1429+
300 | EMP3 | SALESMAN
1430+
400 | EMP4 | MANAGER
1431+
500 | EMP5 | SALESMAN
1432+
(5 rows)
1433+
14051434
-- Cleanup
14061435
DROP TABLE l_test_tbl1;
14071436
DROP TABLE l_test_tbl2;

sql/select.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,14 @@ SELECT c1, sum(c7) FROM f_test_tbl1 t1
411411
ORDER BY 1,2;
412412
ALTER SERVER mysql_svr options (SET use_remote_estimate 'false');
413413

414+
-- FDW-411: Volatile/immutable functions should not get pushed down to remote
415+
-- MySQL server.
416+
EXPLAIN (VERBOSE, COSTS OFF)
417+
SELECT c1, c2, c3 FROM f_test_tbl1 WHERE pg_catalog.timeofday() IS NOT NULL
418+
ORDER BY 1 limit 5;
419+
SELECT c1, c2, c3 FROM f_test_tbl1 WHERE pg_catalog.timeofday() IS NOT NULL
420+
ORDER BY 1 limit 5;
421+
414422
-- Cleanup
415423
DROP TABLE l_test_tbl1;
416424
DROP TABLE l_test_tbl2;

0 commit comments

Comments
 (0)