Skip to content

Commit d75e4e4

Browse files
committed
Avoid crash on RHS functions by not eval'ing Param during explain
1 parent 045b3de commit d75e4e4

File tree

5 files changed

+139
-118
lines changed

5 files changed

+139
-118
lines changed

src/python.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -948,11 +948,17 @@ execute(ForeignScanState *node, ExplainState *es)
948948
newqual->base.isArray = qual->isArray;
949949
newqual->base.useOr = qual->useOr;
950950

951-
#if PG_VERSION_NUM >= 100000
952-
newqual->value = ExecEvalExpr(expr_state, econtext, &isNull);
953-
#else
954-
newqual->value = ExecEvalExpr(expr_state, econtext, &isNull, NULL);
955-
#endif
951+
// Don't attempt to evaluate the expression if we're running an EXPLAIN
952+
if (es == NULL)
953+
{
954+
expr_state = ExecInitExpr(((MulticornParamQual *) qual)->expr,
955+
(PlanState *) node);
956+
#if PG_VERSION_NUM >= 100000
957+
newqual->value = ExecEvalExpr(expr_state, econtext, &isNull);
958+
#else
959+
newqual->value = ExecEvalExpr(expr_state, econtext, &isNull, NULL);
960+
#endif
961+
}
956962
newqual->base.typeoid = ((Param*) ((MulticornParamQual *) qual)->expr)->paramtype;
957963
newqual->isnull = isNull;
958964
break;

test-3.9/expected/multicorn_planner_test.out

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ CREATE server multicorn_srv foreign data wrapper multicorn options (
1212
wrapper 'multicorn.testfdw.TestForeignDataWrapper'
1313
);
1414
CREATE user mapping FOR current_user server multicorn_srv options (usermapping 'test');
15-
-- Test for two thing: first, that when a low total row count,
15+
-- Test for two thing: first, that when a low total row count,
1616
-- a full seq scan is used on a join.
1717
CREATE foreign table testmulticorn (
1818
test1 character varying,
@@ -31,7 +31,7 @@ NOTICE: [('test1', 'character varying'), ('test2', 'character varying')]
3131
explain select * from testmulticorn m1 inner join testmulticorn m2 on m1.test1 = m2.test1;
3232
QUERY PLAN
3333
-------------------------------------------------------------------------------------
34-
Nested Loop (cost=20.00..806.05 rows=2 width=128)
34+
Nested Loop (cost=20.00..806.05 rows=20 width=128)
3535
Join Filter: ((m1.test1)::text = (m2.test1)::text)
3636
-> Foreign Scan on testmulticorn m1 (cost=10.00..400.00 rows=20 width=20)
3737
-> Materialize (cost=10.00..400.10 rows=20 width=20)
@@ -49,40 +49,92 @@ explain select * from testmulticorn m1 left outer join testmulticorn m2 on m1.te
4949
(5 rows)
5050

5151
DROP foreign table testmulticorn;
52-
-- Second, when a total row count is high
52+
-- Second, when a total row count is high
5353
-- a parameterized path is used on the test1 attribute.
5454
CREATE foreign table testmulticorn (
5555
test1 character varying,
5656
test2 character varying
5757
) server multicorn_srv options (
5858
option1 'option1',
59-
test_type 'planner'
59+
test_type 'planner',
60+
noisy_explain 'true'
6061
);
6162
explain select * from testmulticorn;
62-
NOTICE: [('option1', 'option1'), ('test_type', 'planner'), ('usermapping', 'test')]
63+
NOTICE: [('noisy_explain', 'true'), ('option1', 'option1'), ('test_type', 'planner'), ('usermapping', 'test')]
6364
NOTICE: [('test1', 'character varying'), ('test2', 'character varying')]
65+
NOTICE: EXPLAIN quals=[]
66+
NOTICE: EXPLAIN columns=['test1', 'test2']
67+
NOTICE: EXPLAIN sortkeys=None
68+
NOTICE: EXPLAIN verbose=False
6469
QUERY PLAN
6570
----------------------------------------------------------------------------------
6671
Foreign Scan on testmulticorn (cost=10.00..200000000.00 rows=10000000 width=20)
67-
(1 row)
72+
Multicorn: EXPLAIN ROW 1
73+
Multicorn: EXPLAIN ROW 2
74+
(3 rows)
6875

6976
explain select * from testmulticorn m1 inner join testmulticorn m2 on m1.test1 = m2.test1;
77+
NOTICE: EXPLAIN quals=[]
78+
NOTICE: EXPLAIN columns=['test1', 'test2']
79+
NOTICE: EXPLAIN sortkeys=None
80+
NOTICE: EXPLAIN verbose=False
81+
NOTICE: EXPLAIN quals=[test1 = ?]
82+
NOTICE: EXPLAIN columns=['test1', 'test2']
83+
NOTICE: EXPLAIN sortkeys=None
84+
NOTICE: EXPLAIN verbose=False
7085
QUERY PLAN
7186
-------------------------------------------------------------------------------------------
7287
Nested Loop (cost=20.00..400100000.00 rows=500000000000 width=128)
7388
-> Foreign Scan on testmulticorn m1 (cost=10.00..200000000.00 rows=10000000 width=20)
89+
Multicorn: EXPLAIN ROW 1
90+
Multicorn: EXPLAIN ROW 2
7491
-> Foreign Scan on testmulticorn m2 (cost=10.00..20.00 rows=1 width=20)
7592
Filter: ((m1.test1)::text = (test1)::text)
76-
(4 rows)
93+
Multicorn: EXPLAIN ROW 1
94+
Multicorn: EXPLAIN ROW 2
95+
(8 rows)
7796

7897
explain select * from testmulticorn m1 left outer join testmulticorn m2 on m1.test1 = m2.test1;
98+
NOTICE: EXPLAIN quals=[]
99+
NOTICE: EXPLAIN columns=['test1', 'test2']
100+
NOTICE: EXPLAIN sortkeys=None
101+
NOTICE: EXPLAIN verbose=False
102+
NOTICE: EXPLAIN quals=[test1 = ?]
103+
NOTICE: EXPLAIN columns=['test1', 'test2']
104+
NOTICE: EXPLAIN sortkeys=None
105+
NOTICE: EXPLAIN verbose=False
79106
QUERY PLAN
80107
-------------------------------------------------------------------------------------------
81108
Nested Loop Left Join (cost=20.00..400100000.00 rows=500000000000 width=128)
82109
-> Foreign Scan on testmulticorn m1 (cost=10.00..200000000.00 rows=10000000 width=20)
110+
Multicorn: EXPLAIN ROW 1
111+
Multicorn: EXPLAIN ROW 2
83112
-> Foreign Scan on testmulticorn m2 (cost=10.00..20.00 rows=1 width=20)
84113
Filter: ((m1.test1)::text = (test1)::text)
85-
(4 rows)
114+
Multicorn: EXPLAIN ROW 1
115+
Multicorn: EXPLAIN ROW 2
116+
(8 rows)
117+
118+
explain select * from testmulticorn m1 left outer join testmulticorn m2 on upper(m1.test1) = m2.test1;
119+
NOTICE: EXPLAIN quals=[]
120+
NOTICE: EXPLAIN columns=['test1', 'test2']
121+
NOTICE: EXPLAIN sortkeys=None
122+
NOTICE: EXPLAIN verbose=False
123+
NOTICE: EXPLAIN quals=[test1 = ?]
124+
NOTICE: EXPLAIN columns=['test1', 'test2']
125+
NOTICE: EXPLAIN sortkeys=None
126+
NOTICE: EXPLAIN verbose=False
127+
QUERY PLAN
128+
-------------------------------------------------------------------------------------------
129+
Nested Loop Left Join (cost=20.00..400100000.00 rows=500000000000 width=128)
130+
-> Foreign Scan on testmulticorn m1 (cost=10.00..200000000.00 rows=10000000 width=20)
131+
Multicorn: EXPLAIN ROW 1
132+
Multicorn: EXPLAIN ROW 2
133+
-> Foreign Scan on testmulticorn m2 (cost=10.00..20.00 rows=1 width=20)
134+
Filter: (upper((m1.test1)::text) = (test1)::text)
135+
Multicorn: EXPLAIN ROW 1
136+
Multicorn: EXPLAIN ROW 2
137+
(8 rows)
86138

87139
DROP USER MAPPING FOR current_user SERVER multicorn_srv;
88140
DROP EXTENSION multicorn cascade;

test-3.9/expected/multicorn_planner_test_1.out

Lines changed: 64 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ CREATE server multicorn_srv foreign data wrapper multicorn options (
1212
wrapper 'multicorn.testfdw.TestForeignDataWrapper'
1313
);
1414
CREATE user mapping FOR current_user server multicorn_srv options (usermapping 'test');
15-
-- Test for two thing: first, that when a low total row count,
15+
-- Test for two thing: first, that when a low total row count,
1616
-- a full seq scan is used on a join.
1717
CREATE foreign table testmulticorn (
1818
test1 character varying,
@@ -49,40 +49,95 @@ explain select * from testmulticorn m1 left outer join testmulticorn m2 on m1.te
4949
(5 rows)
5050

5151
DROP foreign table testmulticorn;
52-
-- Second, when a total row count is high
52+
-- Second, when a total row count is high
5353
-- a parameterized path is used on the test1 attribute.
5454
CREATE foreign table testmulticorn (
5555
test1 character varying,
5656
test2 character varying
5757
) server multicorn_srv options (
5858
option1 'option1',
59-
test_type 'planner'
59+
test_type 'planner',
60+
noisy_explain 'true'
6061
);
6162
explain select * from testmulticorn;
62-
NOTICE: [('option1', 'option1'), ('test_type', 'planner'), ('usermapping', 'test')]
63+
NOTICE: [('noisy_explain', 'true'), ('option1', 'option1'), ('test_type', 'planner'), ('usermapping', 'test')]
6364
NOTICE: [('test1', 'character varying'), ('test2', 'character varying')]
65+
NOTICE: EXPLAIN quals=[]
66+
NOTICE: EXPLAIN columns=['test1', 'test2']
67+
NOTICE: EXPLAIN sortkeys=None
68+
NOTICE: EXPLAIN verbose=False
6469
QUERY PLAN
6570
----------------------------------------------------------------------------------
6671
Foreign Scan on testmulticorn (cost=10.00..200000000.00 rows=10000000 width=20)
67-
(1 row)
72+
Multicorn: EXPLAIN ROW 1
73+
Multicorn: EXPLAIN ROW 2
74+
(3 rows)
6875

6976
explain select * from testmulticorn m1 inner join testmulticorn m2 on m1.test1 = m2.test1;
77+
NOTICE: EXPLAIN quals=[]
78+
NOTICE: EXPLAIN columns=['test1', 'test2']
79+
NOTICE: EXPLAIN sortkeys=None
80+
NOTICE: EXPLAIN verbose=False
81+
NOTICE: EXPLAIN quals=[test1 = ?]
82+
NOTICE: EXPLAIN columns=['test1', 'test2']
83+
NOTICE: EXPLAIN sortkeys=None
84+
NOTICE: EXPLAIN verbose=False
7085
QUERY PLAN
7186
-------------------------------------------------------------------------------------------
72-
Nested Loop (cost=20.00..400100000.00 rows=500000000000 width=128)
87+
Nested Loop (cost=20.00..400125000.00 rows=500000000000 width=128)
88+
Join Filter: ((m1.test1)::text = (m2.test1)::text)
7389
-> Foreign Scan on testmulticorn m1 (cost=10.00..200000000.00 rows=10000000 width=20)
90+
Multicorn: EXPLAIN ROW 1
91+
Multicorn: EXPLAIN ROW 2
7492
-> Foreign Scan on testmulticorn m2 (cost=10.00..20.00 rows=1 width=20)
7593
Filter: ((m1.test1)::text = (test1)::text)
76-
(4 rows)
94+
Multicorn: EXPLAIN ROW 1
95+
Multicorn: EXPLAIN ROW 2
96+
(9 rows)
7797

7898
explain select * from testmulticorn m1 left outer join testmulticorn m2 on m1.test1 = m2.test1;
99+
NOTICE: EXPLAIN quals=[]
100+
NOTICE: EXPLAIN columns=['test1', 'test2']
101+
NOTICE: EXPLAIN sortkeys=None
102+
NOTICE: EXPLAIN verbose=False
103+
NOTICE: EXPLAIN quals=[test1 = ?]
104+
NOTICE: EXPLAIN columns=['test1', 'test2']
105+
NOTICE: EXPLAIN sortkeys=None
106+
NOTICE: EXPLAIN verbose=False
79107
QUERY PLAN
80108
-------------------------------------------------------------------------------------------
81-
Nested Loop Left Join (cost=20.00..400100000.00 rows=500000000000 width=128)
109+
Nested Loop Left Join (cost=20.00..400125000.00 rows=500000000000 width=128)
110+
Join Filter: ((m1.test1)::text = (m2.test1)::text)
82111
-> Foreign Scan on testmulticorn m1 (cost=10.00..200000000.00 rows=10000000 width=20)
112+
Multicorn: EXPLAIN ROW 1
113+
Multicorn: EXPLAIN ROW 2
83114
-> Foreign Scan on testmulticorn m2 (cost=10.00..20.00 rows=1 width=20)
84115
Filter: ((m1.test1)::text = (test1)::text)
85-
(4 rows)
116+
Multicorn: EXPLAIN ROW 1
117+
Multicorn: EXPLAIN ROW 2
118+
(9 rows)
119+
120+
explain select * from testmulticorn m1 left outer join testmulticorn m2 on upper(m1.test1) = m2.test1;
121+
NOTICE: EXPLAIN quals=[]
122+
NOTICE: EXPLAIN columns=['test1', 'test2']
123+
NOTICE: EXPLAIN sortkeys=None
124+
NOTICE: EXPLAIN verbose=False
125+
NOTICE: EXPLAIN quals=[test1 = ?]
126+
NOTICE: EXPLAIN columns=['test1', 'test2']
127+
NOTICE: EXPLAIN sortkeys=None
128+
NOTICE: EXPLAIN verbose=False
129+
QUERY PLAN
130+
-------------------------------------------------------------------------------------------
131+
Nested Loop Left Join (cost=20.00..400150000.00 rows=500000000000 width=128)
132+
Join Filter: (upper((m1.test1)::text) = (m2.test1)::text)
133+
-> Foreign Scan on testmulticorn m1 (cost=10.00..200000000.00 rows=10000000 width=20)
134+
Multicorn: EXPLAIN ROW 1
135+
Multicorn: EXPLAIN ROW 2
136+
-> Foreign Scan on testmulticorn m2 (cost=10.00..20.00 rows=1 width=20)
137+
Filter: (upper((m1.test1)::text) = (test1)::text)
138+
Multicorn: EXPLAIN ROW 1
139+
Multicorn: EXPLAIN ROW 2
140+
(9 rows)
86141

87142
DROP USER MAPPING FOR current_user SERVER multicorn_srv;
88143
DROP EXTENSION multicorn cascade;

test-3.9/expected/multicorn_planner_test_2.out

Lines changed: 0 additions & 93 deletions
This file was deleted.

test-3.9/sql/multicorn_planner_test.sql

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ CREATE server multicorn_srv foreign data wrapper multicorn options (
66
);
77
CREATE user mapping FOR current_user server multicorn_srv options (usermapping 'test');
88

9-
-- Test for two thing: first, that when a low total row count,
9+
-- Test for two thing: first, that when a low total row count,
1010
-- a full seq scan is used on a join.
1111
CREATE foreign table testmulticorn (
1212
test1 character varying,
@@ -23,14 +23,15 @@ explain select * from testmulticorn m1 left outer join testmulticorn m2 on m1.te
2323

2424
DROP foreign table testmulticorn;
2525

26-
-- Second, when a total row count is high
26+
-- Second, when a total row count is high
2727
-- a parameterized path is used on the test1 attribute.
2828
CREATE foreign table testmulticorn (
2929
test1 character varying,
3030
test2 character varying
3131
) server multicorn_srv options (
3232
option1 'option1',
33-
test_type 'planner'
33+
test_type 'planner',
34+
noisy_explain 'true'
3435
);
3536

3637
explain select * from testmulticorn;

0 commit comments

Comments
 (0)