Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit223ae69

Browse files
committed
Support binary COPY through psql. Also improve detection of write errors
during COPY OUT. Andreas Pflug, some editorialization by moi.
1 parentaadd8a2 commit223ae69

File tree

4 files changed

+100
-57
lines changed

4 files changed

+100
-57
lines changed

‎doc/src/sgml/ref/psql-ref.sgml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.161 2006/04/02 20:08:20 neilc Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.162 2006/05/26 19:51:29 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -744,13 +744,16 @@ testdb=&gt;
744744
{ <literal>from</literal> | <literal>to</literal> }
745745
{ <replaceable class="parameter">filename</replaceable> | stdin | stdout | pstdin | pstdout }
746746
[ with ]
747+
[ binary ]
747748
[ oids ]
748749
[ delimiter [ as ] '<replaceable class="parameter">character</replaceable>' ]
749750
[ null [ as ] '<replaceable class="parameter">string</replaceable>' ]
750-
[ csv [ quote [ as ] '<replaceable class="parameter">character</replaceable>' ]
751-
[ escape [ as ] '<replaceable class="parameter">character</replaceable>' ]
752-
[ force quote <replaceable class="parameter">column_list</replaceable> ]
753-
[ force not null <replaceable class="parameter">column_list</replaceable> ] ]</literal>
751+
[ csv
752+
[ header ]
753+
[ quote [ as ] '<replaceable class="parameter">character</replaceable>' ]
754+
[ escape [ as ] '<replaceable class="parameter">character</replaceable>' ]
755+
[ force quote <replaceable class="parameter">column_list</replaceable> ]
756+
[ force not null <replaceable class="parameter">column_list</replaceable> ] ]</literal>
754757
</term>
755758

756759
<listitem>

‎src/bin/psql/common.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.117 2006/05/11 19:15:35 tgl Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/common.c,v 1.118 2006/05/26 19:51:29 tgl Exp $
77
*/
88
#include"postgres_fe.h"
99
#include"common.h"
@@ -652,7 +652,8 @@ ProcessCopyResult(PGresult *results)
652652
break;
653653

654654
casePGRES_COPY_IN:
655-
success=handleCopyIn(pset.db,pset.cur_cmd_source);
655+
success=handleCopyIn(pset.db,pset.cur_cmd_source,
656+
PQbinaryTuples(results));
656657
break;
657658

658659
default:

‎src/bin/psql/copy.c

Lines changed: 87 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
*
44
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.60 2006/03/05 15:58:51 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/copy.c,v 1.61 2006/05/26 19:51:29 tgl Exp $
77
*/
88
#include"postgres_fe.h"
99
#include"copy.h"
1010

11-
#include<errno.h>
1211
#include<signal.h>
1312
#include<sys/stat.h>
1413
#ifndefWIN32
@@ -37,11 +36,10 @@
3736
*
3837
* The documented preferred syntax is:
3938
*\copy tablename [(columnlist)] from|to filename
40-
*[ with ] [ oids ] [ delimiter [as] char ] [ null [as] string ]
41-
* (binary is not here yet)
39+
* [ with ] [ binary ] [ oids ] [ delimiter [as] char ] [ null [as] string ]
4240
*
4341
* The pre-7.3 syntax was:
44-
*\copy tablename [(columnlist)] [with oids] from|to filename
42+
*\copy[ binary ]tablename [(columnlist)] [with oids] from|to filename
4543
*[ [using] delimiters char ] [ with null as string ]
4644
*
4745
* The actual accepted syntax is a rather unholy combination of these,
@@ -131,8 +129,6 @@ parse_slash_copy(const char *args)
131129
if (!token)
132130
gotoerror;
133131

134-
#ifdefNOT_USED
135-
/* this is not implemented yet */
136132
if (pg_strcasecmp(token,"binary")==0)
137133
{
138134
result->binary= true;
@@ -141,7 +137,6 @@ parse_slash_copy(const char *args)
141137
if (!token)
142138
gotoerror;
143139
}
144-
#endif
145140

146141
result->table=pg_strdup(token);
147142

@@ -284,9 +279,10 @@ parse_slash_copy(const char *args)
284279

285280
fetch_next= true;
286281

287-
/* someday allow BINARY here */
288282
if (pg_strcasecmp(token,"oids")==0)
289283
result->oids= true;
284+
elseif (pg_strcasecmp(token,"binary")==0)
285+
result->binary= true;
290286
elseif (pg_strcasecmp(token,"csv")==0)
291287
result->csv_mode= true;
292288
elseif (pg_strcasecmp(token,"header")==0)
@@ -442,6 +438,8 @@ do_copy(const char *args)
442438
initPQExpBuffer(&query);
443439

444440
printfPQExpBuffer(&query,"COPY ");
441+
442+
/* Uses old COPY syntax for backward compatibility 2002-06-19 */
445443
if (options->binary)
446444
appendPQExpBuffer(&query,"BINARY ");
447445

@@ -523,7 +521,8 @@ do_copy(const char *args)
523521
else
524522
{
525523
if (options->file)
526-
copystream=fopen(options->file,"w");
524+
copystream=fopen(options->file,
525+
options->binary ?PG_BINARY_W :"w");
527526
elseif (!options->psql_inout)
528527
copystream=pset.queryFout;
529528
else
@@ -558,7 +557,8 @@ do_copy(const char *args)
558557
success=handleCopyOut(pset.db,copystream);
559558
break;
560559
casePGRES_COPY_IN:
561-
success=handleCopyIn(pset.db,copystream);
560+
success=handleCopyIn(pset.db,copystream,
561+
PQbinaryTuples(result));
562562
break;
563563
casePGRES_NONFATAL_ERROR:
564564
casePGRES_FATAL_ERROR:
@@ -622,12 +622,23 @@ handleCopyOut(PGconn *conn, FILE *copystream)
622622

623623
if (buf)
624624
{
625-
fputs(buf,copystream);
625+
if (fwrite(buf,1,ret,copystream)!=ret)
626+
{
627+
if (OK)/* complain only once, keep reading data */
628+
psql_error("could not write COPY data: %s\n",
629+
strerror(errno));
630+
OK= false;
631+
}
626632
PQfreemem(buf);
627633
}
628634
}
629635

630-
fflush(copystream);
636+
if (OK&&fflush(copystream))
637+
{
638+
psql_error("could not write COPY data: %s\n",
639+
strerror(errno));
640+
OK= false;
641+
}
631642

632643
if (ret==-2)
633644
{
@@ -657,6 +668,7 @@ handleCopyOut(PGconn *conn, FILE *copystream)
657668
* conn should be a database connection that you just issued COPY FROM on
658669
* and got back a PGRES_COPY_IN result.
659670
* copystream is the file stream to read the data from.
671+
* isbinary can be set from PQbinaryTuples().
660672
*
661673
* result is true if successful, false if not.
662674
*/
@@ -665,13 +677,10 @@ handleCopyOut(PGconn *conn, FILE *copystream)
665677
#defineCOPYBUFSIZ 8192
666678

667679
bool
668-
handleCopyIn(PGconn*conn,FILE*copystream)
680+
handleCopyIn(PGconn*conn,FILE*copystream,boolisbinary)
669681
{
670682
boolOK= true;
671683
constchar*prompt;
672-
boolcopydone= false;
673-
boolfirstload;
674-
boollinedone;
675684
charbuf[COPYBUFSIZ];
676685
PGresult*res;
677686

@@ -686,59 +695,89 @@ handleCopyIn(PGconn *conn, FILE *copystream)
686695
else
687696
prompt=NULL;
688697

689-
while (!copydone)
690-
{/* for each input line ... */
698+
if (isbinary)
699+
{
700+
intbuflen;
701+
702+
/* interactive input probably silly, but give one prompt anyway */
691703
if (prompt)
692704
{
693705
fputs(prompt,stdout);
694706
fflush(stdout);
695707
}
696-
697-
firstload= true;
698-
linedone= false;
699708

700-
while (!linedone)
701-
{/* for each bufferload in line ... */
702-
intlinelen;
703-
704-
if (!fgets(buf,COPYBUFSIZ,copystream))
709+
while ((buflen=fread(buf,1,COPYBUFSIZ,copystream))>0)
710+
{
711+
if (PQputCopyData(conn,buf,buflen) <=0)
705712
{
706-
if (ferror(copystream))
707-
OK= false;
708-
copydone= true;
713+
OK= false;
709714
break;
710715
}
716+
}
717+
}
718+
else
719+
{
720+
boolcopydone= false;
711721

712-
linelen=strlen(buf);
713-
714-
/* current line is done? */
715-
if (linelen>0&&buf[linelen-1]=='\n')
716-
linedone= true;
722+
while (!copydone)
723+
{/* for each input line ... */
724+
boolfirstload;
725+
boollinedone;
717726

718-
/* check for EOF marker, but not on a partial line */
719-
if (firstload)
727+
if (prompt)
720728
{
721-
if (strcmp(buf,"\\.\n")==0||
722-
strcmp(buf,"\\.\r\n")==0)
729+
fputs(prompt,stdout);
730+
fflush(stdout);
731+
}
732+
733+
firstload= true;
734+
linedone= false;
735+
736+
while (!linedone)
737+
{/* for each bufferload in line ... */
738+
intlinelen;
739+
740+
if (!fgets(buf,COPYBUFSIZ,copystream))
723741
{
724742
copydone= true;
725743
break;
726744
}
745+
746+
linelen=strlen(buf);
747+
748+
/* current line is done? */
749+
if (linelen>0&&buf[linelen-1]=='\n')
750+
linedone= true;
751+
752+
/* check for EOF marker, but not on a partial line */
753+
if (firstload)
754+
{
755+
if (strcmp(buf,"\\.\n")==0||
756+
strcmp(buf,"\\.\r\n")==0)
757+
{
758+
copydone= true;
759+
break;
760+
}
727761

728-
firstload= false;
729-
}
762+
firstload= false;
763+
}
730764

731-
if (PQputCopyData(conn,buf,linelen) <=0)
732-
{
733-
OK= false;
734-
copydone= true;
735-
break;
765+
if (PQputCopyData(conn,buf,linelen) <=0)
766+
{
767+
OK= false;
768+
copydone= true;
769+
break;
770+
}
736771
}
737-
}
738772

739-
pset.lineno++;
773+
pset.lineno++;
774+
}
740775
}
741776

777+
/* Check for read error */
778+
if (ferror(copystream))
779+
OK= false;
780+
742781
/* Terminate data transfer */
743782
if (PQputCopyEnd(conn,
744783
OK ?NULL :_("aborted due to read failure")) <=0)

‎src/bin/psql/copy.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*
44
* Copyright (c) 2000-2006, PostgreSQL Global Development Group
55
*
6-
* $PostgreSQL: pgsql/src/bin/psql/copy.h,v 1.18 2006/03/05 15:58:51 momjian Exp $
6+
* $PostgreSQL: pgsql/src/bin/psql/copy.h,v 1.19 2006/05/26 19:51:29 tgl Exp $
77
*/
88
#ifndefCOPY_H
99
#defineCOPY_H
@@ -17,6 +17,6 @@ booldo_copy(const char *args);
1717
/* lower level processors for copy in/out streams */
1818

1919
boolhandleCopyOut(PGconn*conn,FILE*copystream);
20-
boolhandleCopyIn(PGconn*conn,FILE*copystream);
20+
boolhandleCopyIn(PGconn*conn,FILE*copystream,boolisbinary);
2121

2222
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp