diff options
Diffstat (limited to 'src/backend/commands/copy.c')
-rw-r--r-- | src/backend/commands/copy.c | 77 |
1 files changed, 69 insertions, 8 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c index 16c23d320e..cfc8a5c070 100644 --- a/src/backend/commands/copy.c +++ b/src/backend/commands/copy.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.156 2002/05/21 22:59:00 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.157 2002/06/20 16:00:43 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -261,18 +261,79 @@ CopyDonePeek(FILE *fp, int c, bool pickup) * the table. */ void -DoCopy(const RangeVar *relation, bool binary, bool oids, bool from, bool pipe, - char *filename, char *delim, char *null_print) +DoCopy(const CopyStmt *stmt) { + RangeVar *relation = stmt->relation; + char *filename = stmt->filename; + bool is_from = stmt->is_from; + bool pipe = (stmt->filename == NULL); + List *option; + DefElem *dbinary = NULL; + DefElem *doids = NULL; + DefElem *ddelim = NULL; + DefElem *dnull = NULL; + bool binary = false; + bool oids = false; + char *delim = "\t"; + char *null_print = "\\N"; FILE *fp; Relation rel; - AclMode required_access = (from ? ACL_INSERT : ACL_SELECT); + AclMode required_access = (is_from ? ACL_INSERT : ACL_SELECT); AclResult aclresult; + /* Extract options from the statement node tree */ + foreach(option, stmt->options) + { + DefElem *defel = (DefElem *) lfirst(option); + + if (strcmp(defel->defname, "binary") == 0) + { + if (dbinary) + elog(ERROR, "COPY: conflicting options"); + dbinary = defel; + } + else if (strcmp(defel->defname, "oids") == 0) + { + if (doids) + elog(ERROR, "COPY: conflicting options"); + doids = defel; + } + else if (strcmp(defel->defname, "delimiter") == 0) + { + if (ddelim) + elog(ERROR, "COPY: conflicting options"); + ddelim = defel; + } + else if (strcmp(defel->defname, "null") == 0) + { + if (dnull) + elog(ERROR, "COPY: conflicting options"); + dnull = defel; + } + else + elog(ERROR, "COPY: option \"%s\" not recognized", + defel->defname); + } + + if (dbinary) + binary = intVal(dbinary->arg); + if (doids) + oids = intVal(doids->arg); + if (ddelim) + delim = strVal(ddelim->arg); + if (dnull) + null_print = strVal(dnull->arg); + + if (binary && ddelim) + elog(ERROR, "You can not specify the DELIMITER in BINARY mode."); + + if (binary && dnull) + elog(ERROR, "You can not specify NULL in BINARY mode."); + /* * Open and lock the relation, using the appropriate lock type. */ - rel = heap_openrv(relation, (from ? RowExclusiveLock : AccessShareLock)); + rel = heap_openrv(relation, (is_from ? RowExclusiveLock : AccessShareLock)); /* Check permissions. */ aclresult = pg_class_aclcheck(RelationGetRelid(rel), GetUserId(), @@ -306,7 +367,7 @@ DoCopy(const RangeVar *relation, bool binary, bool oids, bool from, bool pipe, server_encoding = GetDatabaseEncoding(); #endif - if (from) + if (is_from) { /* copy from file to database */ if (rel->rd_rel->relkind != RELKIND_RELATION) { @@ -410,7 +471,7 @@ DoCopy(const RangeVar *relation, bool binary, bool oids, bool from, bool pipe, if (!pipe) FreeFile(fp); - else if (!from) + else if (!is_from) { if (!binary) CopySendData("\\.\n", 3, fp); @@ -425,7 +486,7 @@ DoCopy(const RangeVar *relation, bool binary, bool oids, bool from, bool pipe, * transaction to ensure that updates will be committed before lock is * released. */ - heap_close(rel, (from ? NoLock : AccessShareLock)); + heap_close(rel, (is_from ? NoLock : AccessShareLock)); } |