From de5db6eab258753bdb290990ff9a3e833ddccee9 Mon Sep 17 00:00:00 2001 From: Jeevan Chalke Date: Mon, 12 Oct 2020 11:13:11 +0530 Subject: [PATCH] Fix issue where casting target list produces 'NULL'. To check which columns are needed to be output, we create a column list from the target list. However, we are only adding the plain Var nodes appearing in the target list. Thus, if a target list has an explicit casting, then it won't appear as a plain Var node and thus not added in the column list, resulting in returning NULL for them. Fix that by correctly pulling out the Vars from the expression appearing in the target list by using pull_var_clause(). This enables us to give a correct result even if we have expressions other than an explicit cast like a function call or operators. Reported on GitHub through issues #133 by Maksim Volkau (dadhi). FDW-197, Vaibhav Dalvi, reviewed by Suraj Kharage --- expected/select.out | 68 +++++++++++++++++++++++++++++++++++++++++++ expected/select_1.out | 68 +++++++++++++++++++++++++++++++++++++++++++ mongo_query.c | 6 +++- sql/select.sql | 14 +++++++++ 4 files changed, 155 insertions(+), 1 deletion(-) diff --git a/expected/select.out b/expected/select.out index e7096f3..2ba4de5 100644 --- a/expected/select.out +++ b/expected/select.out @@ -1006,6 +1006,74 @@ SELECT c1, c8 FROM f_test_tbl1 ft1 200 | 30 (2 rows) +-- FDW-197: Casting target list should give correct result. +SELECT a::float FROM f_mongo_test ORDER BY a LIMIT 2; + a +--- + 0 + 1 +(2 rows) + +SELECT a, b::varchar FROM f_mongo_test ORDER BY a LIMIT 3; + a | b +---+----------------------- + 0 | mongo_test collection + 1 | One + 2 | Two +(3 rows) + +SELECT a::float, b::varchar FROM f_mongo_test ORDER BY a LIMIT 2; + a | b +---+----------------------- + 0 | mongo_test collection + 1 | One +(2 rows) + +SELECT c1, c2::text FROM f_test_tbl1 ORDER BY c1 LIMIT 2; + c1 | c2 +-----+------ + 100 | EMP1 + 200 | EMP2 +(2 rows) + +SELECT a, LENGTH(b) FROM f_mongo_test ORDER BY 1 LIMIT 2; + a | length +---+-------- + 0 | 21 + 1 | 3 +(2 rows) + +SELECT t1.c6::float, t1.c6::int, t1.c5::timestamptz, t1.c3::text, t2.c1::numeric, t2.c3 + FROM f_test_tbl1 t1, f_test_tbl2 t2 WHERE t1.c8 = t2.c1 + ORDER BY t2.c1, t1.c6 LIMIT 5; + c6 | c6 | c5 | c3 | c1 | c3 +---------+------+------------------------+---------+----+---------- + 1300 | 1300 | 1982-01-23 00:00:00-08 | ADMIN | 10 | PUNE + 2450.34 | 2450 | 1981-06-09 00:00:00-07 | MANAGER | 10 | PUNE + 5000 | 5000 | 1981-11-17 00:00:00-08 | HEAD | 10 | PUNE + 800.3 | 800 | 1980-12-17 00:00:00-08 | ADMIN | 20 | BANGLORE + 1100 | 1100 | 1987-05-23 00:00:00-07 | ADMIN | 20 | BANGLORE +(5 rows) + +SELECT SUM(a::float), SUM(a % 2), a % 2 AS "a % 2"FROM f_mongo_test + GROUP BY a % 2 ORDER BY 2; + sum | sum | a % 2 +-----+-----+------- + 30 | 0 | 0 + 25 | 5 | 1 +(2 rows) + +SELECT (c6::float + (c1 * length(c3::text))) AS "c1 + c6", c1, c6 + FROM f_test_tbl1 ORDER BY c1 LIMIT 5; + c1 + c6 | c1 | c6 +---------+-----+--------- + 1300.3 | 100 | 800.3 + 3200 | 200 | 1600 + 3650 | 300 | 1250 + 5775 | 400 | 2975 + 5250.23 | 500 | 1250.23 +(5 rows) + -- Cleanup DELETE FROM f_mongo_test WHERE a != 0; DROP TABLE l_test_tbl1; diff --git a/expected/select_1.out b/expected/select_1.out index d9d4eb9..47f712c 100644 --- a/expected/select_1.out +++ b/expected/select_1.out @@ -970,6 +970,74 @@ SELECT c1, c8 FROM f_test_tbl1 ft1 200 | 30 (2 rows) +-- FDW-197: Casting target list should give correct result. +SELECT a::float FROM f_mongo_test ORDER BY a LIMIT 2; + a +--- + 0 + 1 +(2 rows) + +SELECT a, b::varchar FROM f_mongo_test ORDER BY a LIMIT 3; + a | b +---+----------------------- + 0 | mongo_test collection + 1 | One + 2 | Two +(3 rows) + +SELECT a::float, b::varchar FROM f_mongo_test ORDER BY a LIMIT 2; + a | b +---+----------------------- + 0 | mongo_test collection + 1 | One +(2 rows) + +SELECT c1, c2::text FROM f_test_tbl1 ORDER BY c1 LIMIT 2; + c1 | c2 +-----+------ + 100 | EMP1 + 200 | EMP2 +(2 rows) + +SELECT a, LENGTH(b) FROM f_mongo_test ORDER BY 1 LIMIT 2; + a | length +---+-------- + 0 | 21 + 1 | 3 +(2 rows) + +SELECT t1.c6::float, t1.c6::int, t1.c5::timestamptz, t1.c3::text, t2.c1::numeric, t2.c3 + FROM f_test_tbl1 t1, f_test_tbl2 t2 WHERE t1.c8 = t2.c1 + ORDER BY t2.c1, t1.c6 LIMIT 5; + c6 | c6 | c5 | c3 | c1 | c3 +---------+------+------------------------+---------+----+---------- + 1300 | 1300 | 1982-01-23 00:00:00-08 | ADMIN | 10 | PUNE + 2450.34 | 2450 | 1981-06-09 00:00:00-07 | MANAGER | 10 | PUNE + 5000 | 5000 | 1981-11-17 00:00:00-08 | HEAD | 10 | PUNE + 800.3 | 800 | 1980-12-17 00:00:00-08 | ADMIN | 20 | BANGLORE + 1100 | 1100 | 1987-05-23 00:00:00-07 | ADMIN | 20 | BANGLORE +(5 rows) + +SELECT SUM(a::float), SUM(a % 2), a % 2 AS "a % 2"FROM f_mongo_test + GROUP BY a % 2 ORDER BY 2; + sum | sum | a % 2 +-----+-----+------- + 30 | 0 | 0 + 25 | 5 | 1 +(2 rows) + +SELECT (c6::float + (c1 * length(c3::text))) AS "c1 + c6", c1, c6 + FROM f_test_tbl1 ORDER BY c1 LIMIT 5; + c1 + c6 | c1 | c6 +---------+-----+--------- + 1300.3 | 100 | 800.3 + 3200 | 200 | 1600 + 3650 | 300 | 1250 + 5775 | 400 | 2975 + 5250.23 | 500 | 1250.23 +(5 rows) + -- Cleanup DELETE FROM f_mongo_test WHERE a != 0; DROP TABLE l_test_tbl1; diff --git a/mongo_query.c b/mongo_query.c index a4f3972..6680642 100644 --- a/mongo_query.c +++ b/mongo_query.c @@ -730,7 +730,11 @@ ColumnList(RelOptInfo *baserel) ListCell *restrictInfoCell; /* First add the columns used in joins and projections */ - neededColumnList = list_copy(targetColumnList); + neededColumnList = pull_var_clause((Node *)targetColumnList, +#if PG_VERSION_NUM < 90600 + PVC_RECURSE_AGGREGATES, +#endif + PVC_RECURSE_PLACEHOLDERS); /* Then walk over all restriction clauses, and pull up any used columns */ foreach(restrictInfoCell, restrictInfoList) diff --git a/sql/select.sql b/sql/select.sql index 539ddde..dc934c3 100644 --- a/sql/select.sql +++ b/sql/select.sql @@ -238,6 +238,20 @@ SELECT c1, c8 FROM f_test_tbl1 ft1 WHERE ft1.c8 = (SELECT c1 FROM f_test_tbl2 ft2 WHERE ft1.c8 = ft2.c1) ORDER BY c1 LIMIT 2; +-- FDW-197: Casting target list should give correct result. +SELECT a::float FROM f_mongo_test ORDER BY a LIMIT 2; +SELECT a, b::varchar FROM f_mongo_test ORDER BY a LIMIT 3; +SELECT a::float, b::varchar FROM f_mongo_test ORDER BY a LIMIT 2; +SELECT c1, c2::text FROM f_test_tbl1 ORDER BY c1 LIMIT 2; +SELECT a, LENGTH(b) FROM f_mongo_test ORDER BY 1 LIMIT 2; +SELECT t1.c6::float, t1.c6::int, t1.c5::timestamptz, t1.c3::text, t2.c1::numeric, t2.c3 + FROM f_test_tbl1 t1, f_test_tbl2 t2 WHERE t1.c8 = t2.c1 + ORDER BY t2.c1, t1.c6 LIMIT 5; +SELECT SUM(a::float), SUM(a % 2), a % 2 AS "a % 2"FROM f_mongo_test + GROUP BY a % 2 ORDER BY 2; +SELECT (c6::float + (c1 * length(c3::text))) AS "c1 + c6", c1, c6 + FROM f_test_tbl1 ORDER BY c1 LIMIT 5; + -- Cleanup DELETE FROM f_mongo_test WHERE a != 0; DROP TABLE l_test_tbl1;