I have extracted the COPY \x part of your patch, and have attached it
for later application to CVS for 8.1.
---------------------------------------------------------------------------
Sergey Ten wrote:
> Hello all,
>
> Thank you to all who replied for suggestions and help. Enclosed please find
> code changes for the following items:
> - Allow COPY to understand \x as a hex byte, and
> - Add XML output to COPY
> The changes include implementation of the features as well as modification
> of the copy regression test.
>
> After a careful consideration we decided to
> - put XML implementation in the backend and
> - use XML format described below, with justification of our decision.
>
> The XML schema used by the COPY TO command was designed for ease of use and
> to avoid the problem of column names appearing in XML element names.
> XML doesn't allow spaces and punctuation in element names but Postgres does
> allow these characters in column names; therefore, a direct mapping would be
> problematic.
>
> The solution selected places the column names into attribute fields where
> any special characters they contain can be properly escaped using XML
> entities. An additional attribute is used to distinguish null fields from
> empty ones.
>
> The example below is taken from the test suite. It demonstrates some basic
> XML escaping in row 2. Row 3 demonstrates the difference between an empty
> string (in col2) and a null string (in col3). If a field is null it will
> always be empty but a field which is empty may or may not be null.
> Always check the value of the 'null' attribute to be sure when a field is
> truly null.
>
> <?xml version='1.0'?>
> <table>
> <row>
> <col name='col1' null='n'>Jackson, Sam</col>
> <col name='col2' null='n'>\h</col>
> </row>
> <row>
> <col name='col1' null='n'>It is "perfect".</col>
> <col name='col2' null='n'> </col>
> </row>
> <row>
> <col name='col1' null='n'></col>
> <col name='col2' null='y'></col>
> </row>
> </table>
>
> Please let us know if about any concerns, objections the proposed change may
> cause.
>
> Best regards,
> Jason Lucas, Sergey Ten
> SourceLabs
>
> > -----Original Message-----
> > From: Bruce Momjian [mailto:pgman@candle.pha.pa.us]
> > Sent: Wednesday, May 11, 2005 7:11 PM
> > To: Sergey Ten
> > Cc: pgsql-hackers@postgresql.org; jason@sourcelabs.com
> > Subject: Re: [HACKERS] patches for items from TODO list
> >
> > Sergey Ten wrote:
> > > Hello all,
> > >
> > > We would like to contribute to the Postgresql community by implementing
> > > the following items from the TODO list
> > > (http://developer.postgresql.org/todo.php):
> > > . Allow COPY to understand \x as a hex byte . Allow COPY to optionally
> > > include column headings in the first line . Add XML output to COPY
> > >
> > > The changes are straightforward and include implementation of the
> > > features as well as modification of the regression tests and
> > documentation.
> > >
> > > Before sending a diff file with the changes, we would like to know if
> > > these features have been already implemented.
> >
> > Please check the web site version. Someone has already implemented
> > "Allow COPY to optionally include column headings in the first line".
> >
> > As far as XML, there has been discussion on where that should be done?
> > In the backend, libpq, or psql. It will need discussion on hackers. I
> > assume you have read the developer's FAQ too.
> >
> > --
> > Bruce Momjian | http://candle.pha.pa.us
> > pgman@candle.pha.pa.us | (610) 359-1001
> > + If your life is a hard drive, | 13 Roberts Road
> > + Christ can be your backup. | Newtown Square, Pennsylvania
> > 19073
[ Attachment, skipping... ]
>
> ---------------------------(end of broadcast)---------------------------
> TIP 6: Have you searched our list archives?
>
> http://archives.postgresql.org
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Index: doc/src/sgml/ref/copy.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/ref/copy.sgml,v
retrieving revision 1.65
diff -c -c -r1.65 copy.sgml
*** doc/src/sgml/ref/copy.sgml 7 May 2005 02:22:45 -0000 1.65
--- doc/src/sgml/ref/copy.sgml 28 May 2005 03:49:10 -0000
***************
*** 424,436 ****
<entry>Backslash followed by one to three octal digits specifies
the character with that numeric code</entry>
</row>
</tbody>
</tgroup>
</informaltable>
! Presently, <command>COPY TO</command> will never emit an octal-digits
! backslash sequence, but it does use the other sequences listed above
! for those control characters.
</para>
<para>
--- 424,441 ----
<entry>Backslash followed by one to three octal digits specifies
the character with that numeric code</entry>
</row>
+ <row>
+ <entry><literal>\x</><replaceable>digits</></entry>
+ <entry>Backslash <literal>x</> followed by one or two hex digits specifies
+ the character with that numeric code</entry>
+ </row>
</tbody>
</tgroup>
</informaltable>
! Presently, <command>COPY TO</command> will never emit an octal or
! hex-digits backslash sequence, but it does use the other sequences
! listed above for those control characters.
</para>
<para>
Index: src/backend/commands/copy.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/commands/copy.c,v
retrieving revision 1.244
diff -c -c -r1.244 copy.c
*** src/backend/commands/copy.c 7 May 2005 02:22:46 -0000 1.244
--- src/backend/commands/copy.c 28 May 2005 03:49:12 -0000
***************
*** 2274,2279 ****
--- 2274,2294 ----
return result;
}
+ /*
+ * Return decimal value for a hexadecimal digit
+ */
+ static
+ int GetDecimalFromHex(char hex)
+ {
+ if (isdigit(hex))
+ return hex - '0';
+ else
+ {
+ hex = tolower(hex);
+ return hex - 'a' + 10;
+ }
+ }
+
/*----------
* Read the value of a single attribute, performing de-escaping as needed.
*
***************
*** 2335,2340 ****
--- 2350,2356 ----
case '5':
case '6':
case '7':
+ /* handle \013 */
{
int val;
***************
*** 2360,2365 ****
--- 2376,2405 ----
c = val & 0377;
}
break;
+ case 'x':
+ /* Handle \x3F */
+ if (line_buf.cursor < line_buf.len)
+ {
+ char hexchar = line_buf.data[line_buf.cursor];
+
+ if (isxdigit(hexchar))
+ {
+ int val = GetDecimalFromHex(hexchar);
+
+ line_buf.cursor++;
+ if (line_buf.cursor < line_buf.len)
+ {
+ hexchar = line_buf.data[line_buf.cursor];
+ if (isxdigit(hexchar))
+ {
+ line_buf.cursor++;
+ val = (val << 4) + GetDecimalFromHex(hexchar);
+ }
+ }
+ c = val & 0xff;
+ }
+ }
+ break;
case 'b':
c = '\b';
break;