? pg_dump_copy.diff Index: doc/src/sgml/ref/pg_dump.sgml =================================================================== RCS file: /projects/cvsroot/pgsql/doc/src/sgml/ref/pg_dump.sgml,v retrieving revision 1.81 diff -c -r1.81 pg_dump.sgml *** doc/src/sgml/ref/pg_dump.sgml 1 Nov 2005 21:09:50 -0000 1.81 --- doc/src/sgml/ref/pg_dump.sgml 27 Jan 2006 02:22:41 -0000 *************** *** 163,168 **** --- 163,188 ---- + + + + Use delimiter + instead of the default tab character in COPY statements. + + + + + + + + + Use string_for_nulls instead of the + default \N in COPY statements. + + + + + Index: src/bin/pg_dump/pg_dump.c =================================================================== RCS file: /projects/cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v retrieving revision 1.427 diff -c -r1.427 pg_dump.c *** src/bin/pg_dump/pg_dump.c 21 Jan 2006 02:16:20 -0000 1.427 --- src/bin/pg_dump/pg_dump.c 27 Jan 2006 02:22:48 -0000 *************** *** 111,116 **** --- 111,121 ---- /* flag to turn on/off dollar quoting */ static int disable_dollar_quoting = 0; + /* Things used when caller invokes COPY options. */ + const char *copy_delimiter_default = "\t"; + const char *copy_delimiter = "\t"; + const char *copy_null_default = "\\N"; + const char *copy_null = "\\N"; static void help(const char *progname); static NamespaceInfo *findNamespace(Oid nsoid, Oid objoid); *************** *** 246,251 **** --- 251,265 ---- {"disable-triggers", no_argument, &disable_triggers, 1}, {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, + /* + * The following options don't have an equivalent short option + * letter, and are not available as -X long-name. Use the + * long form instead. + */ + + {"copy-delimiter", required_argument, NULL, 2}, + {"copy-null", required_argument, NULL, 3}, + {NULL, 0, NULL, 0} }; int optindex; *************** *** 414,419 **** --- 428,453 ---- break; /* This covers the long options equivalent to -X xxx. */ + case 2: + copy_delimiter = strdup(optarg); + if (strlen(copy_delimiter) != 1) + { + fprintf(stderr, _("In %s, copy-delimiter must be exactly one byte long, not %d\n"), + progname, strlen(copy_delimiter)); + exit(1); + } + if ( (*copy_delimiter == '\r') || (*copy_delimiter == '\n') ) + { + fprintf(stderr, _("In %s, copy-delimiter may not be \\r or \\n.\n"), + progname); + exit(1); + } + break; + + case 3: + copy_null = strdup(optarg); + break; + case 0: break; *************** *** 816,836 **** column_list = fmtCopyColumnList(tbinfo); else column_list = ""; /* can't select columns in COPY */ - if (oids && hasoids) - { - appendPQExpBuffer(q, "COPY %s %s WITH OIDS TO stdout;", - fmtQualifiedId(tbinfo->dobj.namespace->dobj.name, - classname), - column_list); - } - else - { - appendPQExpBuffer(q, "COPY %s %s TO stdout;", - fmtQualifiedId(tbinfo->dobj.namespace->dobj.name, - classname), - column_list); - } res = PQexec(g_conn, q->data); check_sql_result(res, g_conn, q->data, PGRES_COPY_OUT); --- 850,869 ---- column_list = fmtCopyColumnList(tbinfo); else column_list = ""; /* can't select columns in COPY */ + appendPQExpBuffer(q, "COPY %s %s %sTO stdout", + fmtQualifiedId(tbinfo->dobj.namespace->dobj.name, classname), + column_list, + /* dump OIDs if requested */ + (oids && hasoids) ? "WITH OIDS " : "" + ); + /* Add a DELIMITER if copy_delimiter is not the default */ + if (strcmp(copy_delimiter, copy_delimiter_default) != 0) + appendPQExpBuffer(q, " DELIMITER AS '%s'", copy_delimiter); + /* Add a NULL AS stanza if copy_null is not the default */ + if (strcmp(copy_null,copy_null_default) != 0) + appendPQExpBuffer(q, " NULL AS '%s'", copy_null); + appendPQExpBuffer(q, ";"); res = PQexec(g_conn, q->data); check_sql_result(res, g_conn, q->data, PGRES_COPY_OUT); *************** *** 1085,1093 **** /* must use 2 steps here 'cause fmtId is nonreentrant */ appendPQExpBuffer(copyBuf, "COPY %s ", fmtId(tbinfo->dobj.name)); ! appendPQExpBuffer(copyBuf, "%s %sFROM stdin;\n", ! fmtCopyColumnList(tbinfo), ! (tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : ""); copyStmt = copyBuf->data; } else --- 1118,1135 ---- /* must use 2 steps here 'cause fmtId is nonreentrant */ appendPQExpBuffer(copyBuf, "COPY %s ", fmtId(tbinfo->dobj.name)); ! appendPQExpBuffer(copyBuf, "%s %sFROM stdin", ! fmtCopyColumnList(tbinfo), ! (tdinfo->oids && tbinfo->hasoids) ? "WITH OIDS " : "" ! ); ! /* Add DELIMITER AS stanza if not the default */ ! if (strcmp(copy_delimiter, copy_delimiter_default) != 0) ! appendPQExpBuffer(copyBuf, " DELIMITER AS '%s'", copy_delimiter); ! /* Add NULL AS stanza if not the default */ ! if (strcmp(copy_null, copy_null_default) != 0) ! appendPQExpBuffer(copyBuf, " NULL AS '%s'", copy_null); ! appendPQExpBuffer(copyBuf, ";\n"); ! copyStmt = copyBuf->data; } else