Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4f405c8

Browse files
committed
Add a HINT for client-vs-server COPY failure cases.
Users often get confused between COPY and \copy and try to use client-side paths with COPY. The server then cannot find the file (if remote), or sees a permissions problem (if local), or some variant of that. Emit a hint about this in the most common cases. In future we might want to expand the set of errnos for which the hint gets printed, but be conservative for now. Craig Ringer, reviewed by Christoph Berg and Tom Lane Discussion: <CAMsr+YEqtD97qPEzQDqrCt5QiqPbWP_X4hmvy2pQzWC0GWiyPA@mail.gmail.com>
1 parent 49eb0fd commit 4f405c8

File tree

1 file changed

+20
-4
lines changed

1 file changed

+20
-4
lines changed

src/backend/commands/copy.c

+20-4
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
280280

281281
/* non-export function prototypes */
282282
static CopyState BeginCopy(ParseState *pstate, bool is_from, Relation rel, Node *raw_query,
283-
const Oid queryRelId, List *attnamelist,
283+
const Oid queryRelId, List *attnamelist,
284284
List *options);
285285
static void EndCopy(CopyState cstate);
286286
static void ClosePipeToProgram(CopyState cstate);
@@ -1175,7 +1175,7 @@ ProcessCopyOptions(ParseState *pstate,
11751175
(errcode(ERRCODE_SYNTAX_ERROR),
11761176
errmsg("option \"%s\" not recognized",
11771177
defel->defname),
1178-
parser_errposition(pstate, defel->location)));
1178+
parser_errposition(pstate, defel->location)));
11791179
}
11801180

11811181
/*
@@ -1785,10 +1785,18 @@ BeginCopyTo(ParseState *pstate,
17851785
cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_W);
17861786
umask(oumask);
17871787
if (cstate->copy_file == NULL)
1788+
{
1789+
/* copy errno because ereport subfunctions might change it */
1790+
int save_errno = errno;
1791+
17881792
ereport(ERROR,
17891793
(errcode_for_file_access(),
17901794
errmsg("could not open file \"%s\" for writing: %m",
1791-
cstate->filename)));
1795+
cstate->filename),
1796+
(save_errno == ENOENT || save_errno == EACCES) ?
1797+
errhint("COPY TO instructs the PostgreSQL server process to write a file. "
1798+
"You may want a client-side facility such as psql's \\copy.") : 0));
1799+
}
17921800

17931801
if (fstat(fileno(cstate->copy_file), &st))
17941802
ereport(ERROR,
@@ -2810,10 +2818,18 @@ BeginCopyFrom(ParseState *pstate,
28102818

28112819
cstate->copy_file = AllocateFile(cstate->filename, PG_BINARY_R);
28122820
if (cstate->copy_file == NULL)
2821+
{
2822+
/* copy errno because ereport subfunctions might change it */
2823+
int save_errno = errno;
2824+
28132825
ereport(ERROR,
28142826
(errcode_for_file_access(),
28152827
errmsg("could not open file \"%s\" for reading: %m",
2816-
cstate->filename)));
2828+
cstate->filename),
2829+
(save_errno == ENOENT || save_errno == EACCES) ?
2830+
errhint("COPY FROM instructs the PostgreSQL server process to read a file. "
2831+
"You may want a client-side facility such as psql's \\copy.") : 0));
2832+
}
28172833

28182834
if (fstat(fileno(cstate->copy_file), &st))
28192835
ereport(ERROR,

0 commit comments

Comments
 (0)