mirror of
https://github.com/postgres/postgres.git
synced 2026-10-23 13:29:09 +03:00
Fix COPY FROM ... WHERE for negated operators.
COPY FROM runs its WHERE clause through eval_const_expressions(),
which among other things replaces NOT above an operator with the
operator's negator, if it has one (e.g., NOT (a > 0) becomes
a <= 0). The node it builds for the negator has no opfuncid, and
since COPY FROM never calls fix_opfuncids() on the clause, nothing
fills it in before the executor needs it. So
COPY tab FROM stdin WHERE NOT (a > 0)
fails with "cache lookup failed for function 0".
To fix, call fix_opfuncids() on the clause, as the relcache does
for index predicates.
Oversight in commit 31f3817402.
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/asPZRTci4oBvxR9A%40nathan
Backpatch-through: 14
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include "mb/pg_wchar.h"
|
||||
#include "miscadmin.h"
|
||||
#include "nodes/makefuncs.h"
|
||||
#include "nodes/nodeFuncs.h"
|
||||
#include "optimizer/optimizer.h"
|
||||
#include "parser/parse_coerce.h"
|
||||
#include "parser/parse_collate.h"
|
||||
@@ -187,6 +188,7 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
|
||||
|
||||
whereClause = (Node *) canonicalize_qual((Expr *) whereClause, false);
|
||||
whereClause = (Node *) make_ands_implicit((Expr *) whereClause);
|
||||
fix_opfuncids(whereClause);
|
||||
}
|
||||
|
||||
tupDesc = RelationGetDescr(rel);
|
||||
|
||||
@@ -155,6 +155,7 @@ LINE 1: COPY x TO stdout WHERE a = 1;
|
||||
^
|
||||
COPY x from stdin WHERE a = 50004;
|
||||
COPY x from stdin WHERE a > 60003;
|
||||
COPY x from stdin WHERE NOT (a < 70003);
|
||||
COPY x from stdin WHERE f > 60003;
|
||||
ERROR: column "f" does not exist
|
||||
LINE 1: COPY x from stdin WHERE f > 60003;
|
||||
@@ -202,12 +203,13 @@ SELECT * FROM x;
|
||||
50004 | 25 | 35 | 45 | before trigger fired
|
||||
60004 | 25 | 35 | 45 | before trigger fired
|
||||
60005 | 26 | 36 | 46 | before trigger fired
|
||||
70003 | 24 | 34 | 44 | before trigger fired
|
||||
1 | 1 | stuff | test_1 | after trigger fired
|
||||
2 | 2 | stuff | test_2 | after trigger fired
|
||||
3 | 3 | stuff | test_3 | after trigger fired
|
||||
4 | 4 | stuff | test_4 | after trigger fired
|
||||
5 | 5 | stuff | test_5 | after trigger fired
|
||||
(28 rows)
|
||||
(29 rows)
|
||||
|
||||
-- check copy out
|
||||
COPY x TO stdout;
|
||||
@@ -234,6 +236,7 @@ COPY x TO stdout;
|
||||
50004 25 35 45 before trigger fired
|
||||
60004 25 35 45 before trigger fired
|
||||
60005 26 36 46 before trigger fired
|
||||
70003 24 34 44 before trigger fired
|
||||
1 1 stuff test_1 after trigger fired
|
||||
2 2 stuff test_2 after trigger fired
|
||||
3 3 stuff test_3 after trigger fired
|
||||
@@ -263,6 +266,7 @@ Delimiter before trigger fired
|
||||
35 before trigger fired
|
||||
35 before trigger fired
|
||||
36 before trigger fired
|
||||
34 before trigger fired
|
||||
stuff after trigger fired
|
||||
stuff after trigger fired
|
||||
stuff after trigger fired
|
||||
@@ -292,6 +296,7 @@ I'm null before trigger fired
|
||||
25 before trigger fired
|
||||
25 before trigger fired
|
||||
26 before trigger fired
|
||||
24 before trigger fired
|
||||
1 after trigger fired
|
||||
2 after trigger fired
|
||||
3 after trigger fired
|
||||
|
||||
@@ -175,6 +175,12 @@ COPY x from stdin WHERE a > 60003;
|
||||
60005 26 36 46 56
|
||||
\.
|
||||
|
||||
COPY x from stdin WHERE NOT (a < 70003);
|
||||
70001 22 32 42 52
|
||||
70002 23 33 43 53
|
||||
70003 24 34 44 54
|
||||
\.
|
||||
|
||||
COPY x from stdin WHERE f > 60003;
|
||||
\.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user