aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/copy.c205
-rw-r--r--src/backend/libpq/pqcomm.c27
-rw-r--r--src/backend/utils/error/elog.c11
-rw-r--r--src/include/libpq/libpq-be.h4
-rw-r--r--src/include/libpq/libpq.h4
5 files changed, 179 insertions, 72 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 61151ef6aad..a9e22ec40be 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -6,7 +6,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.65 1998/12/15 12:45:53 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.66 1999/01/11 03:56:05 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,6 +36,7 @@
#include <commands/copy.h>
#include "commands/trigger.h"
#include <storage/fd.h>
+#include <libpq/libpq.h>
#ifdef MULTIBYTE
#include "mb/pg_wchar.h"
@@ -67,11 +68,106 @@ static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim);
static void CopyAttributeOut(FILE *fp, char *string, char *delim, int is_array);
static int CountTuples(Relation relation);
-extern FILE *Pfout,
- *Pfin;
-
static int lineno;
+/*
+ * Internal communications functions
+ */
+inline void CopySendData(void *databuf, int datasize, FILE *fp);
+inline void CopySendString(char *str, FILE *fp);
+inline void CopySendChar(char c, FILE *fp);
+inline void CopyGetData(void *databuf, int datasize, FILE *fp);
+inline int CopyGetChar(FILE *fp);
+inline int CopyGetEof(FILE *fp);
+inline int CopyPeekChar(FILE *fp);
+inline void CopyDonePeek(FILE *fp, int c, int pickup);
+
+/*
+ * CopySendData sends output data either to the file
+ * specified by fp or, if fp is NULL, using the standard
+ * backend->frontend functions
+ *
+ * CopySendString does the same for null-terminated strings
+ * CopySendChar does the same for single characters
+ */
+inline void CopySendData(void *databuf, int datasize, FILE *fp) {
+ if (!fp)
+ pq_putnchar(databuf, datasize);
+ else
+ fwrite(databuf, datasize, 1, fp);
+}
+
+inline void CopySendString(char *str, FILE *fp) {
+ CopySendData(str,strlen(str),fp);
+}
+
+inline void CopySendChar(char c, FILE *fp) {
+ CopySendData(&c,1,fp);
+}
+
+/*
+ * CopyGetData reads output data either from the file
+ * specified by fp or, if fp is NULL, using the standard
+ * backend->frontend functions
+ *
+ * CopyGetChar does the same for single characters
+ * CopyGetEof checks if it's EOF on the input
+ */
+inline void CopyGetData(void *databuf, int datasize, FILE *fp) {
+ if (!fp)
+ pq_getnchar(databuf, 0, datasize);
+ else
+ fread(databuf, datasize, 1, fp);
+}
+
+inline int CopyGetChar(FILE *fp) {
+ if (!fp)
+ return pq_getchar();
+ else
+ return getc(fp);
+}
+
+inline int CopyGetEof(FILE *fp) {
+ if (!fp)
+ return 0; /* Never return EOF when talking to frontend ? */
+ else
+ return feof(fp);
+}
+
+/*
+ * CopyPeekChar reads a byte in "peekable" mode.
+ * after each call to CopyPeekChar, a call to CopyDonePeek _must_
+ * follow.
+ * CopyDonePeek will either take the peeked char off the steam
+ * (if pickup is != 0) or leave it on the stream (if pickup == 0)
+ */
+inline int CopyPeekChar(FILE *fp) {
+ if (!fp)
+ return pq_peekchar();
+ else
+ return getc(fp);
+}
+
+inline void CopyDonePeek(FILE *fp, int c, int pickup) {
+ if (!fp) {
+ if (pickup) {
+ /* We want to pick it up - just receive again into dummy buffer */
+ char c;
+ pq_getnchar(&c, 0, 1);
+ }
+ /* If we didn't want to pick it up, just leave it where it sits */
+ }
+ else {
+ if (!pickup) {
+ /* We don't want to pick it up - so put it back in there */
+ ungetc(c,fp);
+ }
+ /* If we wanted to pick it up, it's already there */
+ }
+}
+
+
+
/*
* DoCopy executes a the SQL COPY statement.
*/
@@ -147,7 +243,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
if (IsUnderPostmaster)
{
ReceiveCopyBegin();
- fp = Pfin;
+ fp = NULL;
}
else
fp = stdin;
@@ -171,7 +267,7 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
if (IsUnderPostmaster)
{
SendCopyBegin();
- fp = Pfout;
+ fp = NULL;
}
else
fp = stdout;
@@ -199,9 +295,9 @@ DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
}
else if (!from && !binary)
{
- fputs("\\.\n", fp);
+ CopySendData("\\.\n",3,fp);
if (IsUnderPostmaster)
- fflush(Pfout);
+ pq_flush();
}
}
}
@@ -269,7 +365,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
/* XXX expensive */
ntuples = CountTuples(rel);
- fwrite(&ntuples, sizeof(int32), 1, fp);
+ CopySendData(&ntuples, sizeof(int32), fp);
}
while (HeapTupleIsValid(tuple = heap_getnext(scandesc, 0)))
@@ -277,8 +373,8 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
if (oids && !binary)
{
- fputs(oidout(tuple->t_data->t_oid), fp);
- fputc(delim[0], fp);
+ CopySendString(oidout(tuple->t_data->t_oid),fp);
+ CopySendChar(delim[0],fp);
}
for (i = 0; i < attr_count; i++)
@@ -294,10 +390,10 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
pfree(string);
}
else
- fputs("\\N", fp); /* null indicator */
+ CopySendString("\\N", fp); /* null indicator */
if (i == attr_count - 1)
- fputc('\n', fp);
+ CopySendChar('\n', fp);
else
{
@@ -305,7 +401,7 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
* when copying out, only use the first char of the
* delim string
*/
- fputc(delim[0], fp);
+ CopySendChar(delim[0], fp);
}
}
else
@@ -332,24 +428,24 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
}
length = tuple->t_len - tuple->t_data->t_hoff;
- fwrite(&length, sizeof(int32), 1, fp);
+ CopySendData(&length, sizeof(int32), fp);
if (oids)
- fwrite((char *) &tuple->t_data->t_oid, sizeof(int32), 1, fp);
+ CopySendData((char *) &tuple->t_data->t_oid, sizeof(int32), fp);
- fwrite(&null_ct, sizeof(int32), 1, fp);
+ CopySendData(&null_ct, sizeof(int32), fp);
if (null_ct > 0)
{
for (i = 0; i < attr_count; i++)
{
if (nulls[i] == 'n')
{
- fwrite(&i, sizeof(int32), 1, fp);
+ CopySendData(&i, sizeof(int32), fp);
nulls[i] = ' ';
}
}
}
- fwrite((char *) tuple->t_data + tuple->t_data->t_hoff,
- length, 1, fp);
+ CopySendData((char *) tuple->t_data + tuple->t_data->t_hoff,
+ length, fp);
}
}
@@ -527,7 +623,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
in_functions = NULL;
elements = NULL;
typmod = NULL;
- fread(&ntuples, sizeof(int32), 1, fp);
+ CopyGetData(&ntuples, sizeof(int32), fp);
if (ntuples != 0)
reading_to_eof = false;
}
@@ -544,10 +640,12 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
index_nulls[i] = ' ';
byval[i] = (bool) IsTypeByVal(attr[i]->atttypid);
}
+ values = (Datum *) palloc(sizeof(Datum) * attr_count);
lineno = 0;
while (!done)
{
+ values = (Datum *) palloc(sizeof(Datum) * attr_count);
if (!binary)
{
#ifdef COPY_PATCH
@@ -608,29 +706,29 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
}
else
{ /* binary */
- fread(&len, sizeof(int32), 1, fp);
- if (feof(fp))
+ CopyGetData(&len, sizeof(int32), fp);
+ if (CopyGetEof(fp))
done = 1;
else
{
if (oids)
{
- fread(&loaded_oid, sizeof(int32), 1, fp);
+ CopyGetData(&loaded_oid, sizeof(int32), fp);
if (loaded_oid < BootstrapObjectIdData)
elog(ERROR, "COPY BINARY: Invalid Oid line: %d", lineno);
}
- fread(&null_ct, sizeof(int32), 1, fp);
+ CopyGetData(&null_ct, sizeof(int32), fp);
if (null_ct > 0)
{
for (i = 0; i < null_ct; i++)
{
- fread(&null_id, sizeof(int32), 1, fp);
+ CopyGetData(&null_id, sizeof(int32), fp);
nulls[null_id] = 'n';
}
}
string = (char *) palloc(len);
- fread(string, len, 1, fp);
+ CopyGetData(string, len, fp);
ptr = string;
@@ -979,7 +1077,7 @@ CopyReadNewline(FILE *fp, int *newline)
if (!*newline)
{
elog(NOTICE, "CopyReadNewline: line %d - extra fields ignored", lineno);
- while (!feof(fp) && (getc(fp) != '\n'));
+ while (!CopyGetEof(fp) && (CopyGetChar(fp) != '\n'));
}
*newline = 0;
}
@@ -1028,19 +1126,19 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
#endif
*isnull = (bool) false; /* set default */
- if (feof(fp))
+ if (CopyGetEof(fp))
return NULL;
while (!done)
{
- c = getc(fp);
+ c = CopyGetChar(fp);
- if (feof(fp))
+ if (CopyGetEof(fp))
return NULL;
else if (c == '\\')
{
- c = getc(fp);
- if (feof(fp))
+ c = CopyGetChar(fp);
+ if (CopyGetEof(fp))
return NULL;
switch (c)
{
@@ -1056,25 +1154,30 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
int val;
val = VALUE(c);
- c = getc(fp);
+ c = CopyPeekChar(fp);
if (ISOCTAL(c))
{
val = (val << 3) + VALUE(c);
- c = getc(fp);
- if (ISOCTAL(c))
+ CopyDonePeek(fp, c, 1); /* Pick up the character! */
+ c = CopyPeekChar(fp);
+ if (ISOCTAL(c)) {
+ CopyDonePeek(fp,c,1); /* pick up! */
val = (val << 3) + VALUE(c);
+ }
else
{
- if (feof(fp))
+ if (CopyGetEof(fp)) {
+ CopyDonePeek(fp,c,1); /* pick up */
return NULL;
- ungetc(c, fp);
+ }
+ CopyDonePeek(fp,c,0); /* Return to stream! */
}
}
else
{
- if (feof(fp))
+ if (CopyGetEof(fp))
return NULL;
- ungetc(c, fp);
+ CopyDonePeek(fp,c,0); /* Return to stream! */
}
c = val & 0377;
}
@@ -1102,7 +1205,7 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
*isnull = (bool) true;
break;
case '.':
- c = getc(fp);
+ c = CopyGetChar(fp);
if (c != '\n')
elog(ERROR, "CopyReadAttribute - end of record marker corrupted. line: %d", lineno);
return NULL;
@@ -1125,8 +1228,8 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
mblen--;
for (j = 0; j < mblen; j++)
{
- c = getc(fp);
- if (feof(fp))
+ c = CopyGetChar(fp);
+ if (CopyGetEof(fp))
return NULL;
attribute[i++] = c;
}
@@ -1171,29 +1274,29 @@ CopyAttributeOut(FILE *fp, char *server_string, char *delim, int is_array)
{
if (c == delim[0] || c == '\n' ||
(c == '\\' && !is_array))
- fputc('\\', fp);
+ CopySendChar('\\', fp);
else if (c == '\\' && is_array)
{
if (*(string + 1) == '\\')
{
/* translate \\ to \\\\ */
- fputc('\\', fp);
- fputc('\\', fp);
- fputc('\\', fp);
+ CopySendChar('\\', fp);
+ CopySendChar('\\', fp);
+ CopySendChar('\\', fp);
string++;
}
else if (*(string + 1) == '"')
{
/* translate \" to \\\" */
- fputc('\\', fp);
- fputc('\\', fp);
+ CopySendChar('\\', fp);
+ CopySendChar('\\', fp);
}
}
#ifdef MULTIBYTE
for (i = 0; i < mblen; i++)
- fputc(*(string + i), fp);
+ CopySendChar(*(string + i), fp);
#else
- fputc(*string, fp);
+ CopySendChar(*string, fp);
#endif
}
}
diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c
index b4bab9c8991..9fe835d8b7c 100644
--- a/src/backend/libpq/pqcomm.c
+++ b/src/backend/libpq/pqcomm.c
@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: pqcomm.c,v 1.59 1998/12/14 06:50:27 scrappy Exp $
+ * $Id: pqcomm.c,v 1.60 1999/01/11 03:56:06 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -75,7 +75,7 @@
* declarations
* ----------------
*/
-FILE *Pfout,
+static FILE *Pfout,
*Pfin,
*Pfdebug; /* debugging libpq */
@@ -98,7 +98,7 @@ pq_init(int fd)
}
/* -------------------------
- * pq_getc(File* fin)
+ * pq_getchar()
*
* get a character from the input file,
*
@@ -107,20 +107,29 @@ pq_init(int fd)
* used for debugging libpq
*/
-#if 0 /* not used anymore */
-
-static int
-pq_getc(FILE *fin)
+int
+pq_getchar(void)
{
int c;
- c = getc(fin);
+ c = getc(Pfin);
if (Pfdebug && c != EOF)
putc(c, Pfdebug);
return c;
}
-#endif
+/*
+ * --------------------------------
+ * pq_peekchar - get 1 character from connection, but leave it in the stream
+ */
+int
+pq_peekchar(void) {
+ char c = getc(Pfin);
+ ungetc(c,Pfin);
+ return c;
+}
+
+
/* --------------------------------
* pq_gettty - return the name of the tty in the given buffer
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index e965cd2ad38..4e68c1e24a8 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.36 1999/01/01 04:48:45 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/error/elog.c,v 1.37 1999/01/11 03:56:07 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -67,11 +67,6 @@ elog(int lev, const char *fmt,...)
extern int errno,
sys_nerr;
-#ifndef PG_STANDALONE
- extern FILE *Pfout;
-
-#endif
-
#ifdef USE_SYSLOG
int log_level;
@@ -190,7 +185,7 @@ elog(int lev, const char *fmt,...)
#ifndef PG_STANDALONE
/* Send IPC message to the front-end program */
- if (Pfout != NULL && lev > DEBUG)
+ if (IsUnderPostmaster && lev > DEBUG)
{
/* notices are not exactly errors, handle it differently */
if (lev == NOTICE)
@@ -201,7 +196,7 @@ elog(int lev, const char *fmt,...)
pq_putstr(line + TIMESTAMP_SIZE); /* don't show timestamps */
pq_flush();
}
- if (Pfout == NULL)
+ if (!IsUnderPostmaster)
{
/*
diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h
index bad77383c98..4c65e7769b8 100644
--- a/src/include/libpq/libpq-be.h
+++ b/src/include/libpq/libpq-be.h
@@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: libpq-be.h,v 1.12 1998/09/01 04:36:27 momjian Exp $
+ * $Id: libpq-be.h,v 1.13 1999/01/11 03:56:11 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -131,8 +131,6 @@ typedef struct Port
} Port;
-extern FILE *Pfout,
- *Pfin;
extern ProtocolVersion FrontendProtocol;
diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h
index ef7ec5d2cfd..4fca9623aa9 100644
--- a/src/include/libpq/libpq.h
+++ b/src/include/libpq/libpq.h
@@ -6,7 +6,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
- * $Id: libpq.h,v 1.21 1998/09/01 04:36:29 momjian Exp $
+ * $Id: libpq.h,v 1.22 1999/01/11 03:56:11 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@@ -258,6 +258,8 @@ extern void pq_flush(void);
extern int pq_getstr(char *s, int maxlen);
extern int PQgetline(char *s, int maxlen);
extern int PQputline(char *s);
+extern int pq_getchar(void);
+extern int pq_peekchar(void);
extern int pq_getnchar(char *s, int off, int maxlen);
extern int pq_getint(int b);
extern void pq_putstr(char *s);