Commit d27c28fd authored by Bryan Henderson's avatar Bryan Henderson

Allow only superuser to do backend copy.

parent c9b05e55
...@@ -6,99 +6,92 @@ ...@@ -6,99 +6,92 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.10 1996/10/23 07:39:53 scrappy Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.11 1996/11/02 02:01:47 bryanh Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include <postgres.h>
#include "catalog/pg_attribute.h" #include <catalog/pg_attribute.h>
#include "access/attnum.h" #include <access/attnum.h>
#include "nodes/pg_list.h" #include <nodes/pg_list.h>
#include "access/tupdesc.h" #include <access/tupdesc.h>
#include "storage/fd.h" #include <storage/fd.h>
#include "catalog/pg_am.h" #include <catalog/pg_am.h>
#include "catalog/pg_class.h" #include <catalog/pg_class.h>
#include "nodes/nodes.h" #include <nodes/nodes.h>
#include "rewrite/prs2lock.h" #include <rewrite/prs2lock.h>
#include "access/skey.h" #include <access/skey.h>
#include "access/strat.h" #include <access/strat.h>
#include "utils/rel.h" #include <utils/rel.h>
#include "storage/block.h" #include <storage/block.h>
#include "storage/off.h" #include <storage/off.h>
#include "storage/itemptr.h" #include <storage/itemptr.h>
#include <time.h> #include <time.h>
#include "utils/nabstime.h" #include <utils/nabstime.h>
#include "access/htup.h" #include <access/htup.h>
#include "utils/tqual.h" #include <utils/tqual.h>
#include "storage/buf.h" #include <storage/buf.h>
#include "access/relscan.h" #include <access/relscan.h>
#include "access/heapam.h" #include <access/heapam.h>
#include "access/itup.h" #include <access/itup.h>
#include <stdio.h> #include <stdio.h>
#include "tcop/dest.h" #include <tcop/dest.h>
#include "fmgr.h" #include <fmgr.h>
#include "utils/palloc.h" #include <utils/palloc.h>
#include "miscadmin.h" #include <miscadmin.h>
#include "utils/geo-decls.h" #include <utils/geo-decls.h>
#include "utils/builtins.h" #include <utils/builtins.h>
#include <sys/stat.h> #include <sys/stat.h>
#include "access/funcindex.h" #include <access/funcindex.h>
#include "catalog/pg_index.h" #include <catalog/pg_index.h>
#include "utils/syscache.h" #include <utils/syscache.h>
#include "nodes/params.h" #include <nodes/params.h>
#include "access/sdir.h" #include <access/sdir.h>
#include "executor/hashjoin.h" #include <executor/hashjoin.h>
#include "nodes/primnodes.h" #include <nodes/primnodes.h>
#include "nodes/memnodes.h" #include <nodes/memnodes.h>
#include "executor/tuptable.h" #include <executor/tuptable.h>
#include "nodes/execnodes.h" #include <nodes/execnodes.h>
#include "utils/memutils.h" #include <utils/memutils.h>
#include "nodes/plannodes.h" #include <nodes/plannodes.h>
#include "nodes/parsenodes.h" #include <nodes/parsenodes.h>
#include "executor/execdesc.h" #include <executor/execdesc.h>
#include "executor/executor.h" #include <executor/executor.h>
#include "storage/ipc.h" #include <storage/ipc.h>
#include "storage/bufmgr.h" #include <storage/bufmgr.h>
#include "access/transam.h" #include <access/transam.h>
#include "catalog/index.h" #include <catalog/index.h>
#include "access/genam.h" #include <access/genam.h>
#include "catalog/pg_type.h" #include <catalog/pg_type.h>
#include "catalog/catname.h" #include <catalog/catname.h>
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
#define VALUE(c) ((c) - '0')
/* #define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
* New copy code. #define VALUE(c) ((c) - '0')
*
* This code "knows" the following about tuples:
*
*/
static bool reading_from_input = false;
/* non-export function prototypes */ /* non-export function prototypes */
static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim); static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim);
...@@ -108,61 +101,112 @@ static Oid GetTypeElement(Oid type); ...@@ -108,61 +101,112 @@ static Oid GetTypeElement(Oid type);
static Oid GetInputFunction(Oid type); static Oid GetInputFunction(Oid type);
static Oid IsTypeByVal(Oid type); static Oid IsTypeByVal(Oid type);
static void GetIndexRelations(Oid main_relation_oid, static void GetIndexRelations(Oid main_relation_oid,
int *n_indices, int *n_indices,
Relation **index_rels); Relation **index_rels);
static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim); static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim);
static void CopyAttributeOut(FILE *fp, char *string, char *delim); static void CopyAttributeOut(FILE *fp, char *string, char *delim);
static int CountTuples(Relation relation); static int CountTuples(Relation relation);
extern FILE *Pfout, *Pfin; extern FILE *Pfout, *Pfin;
/*
* DoCopy executes a the SQL COPY statement.
*/
void void
DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe, char *filename, DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
char *delim) char *filename, char *delim) {
{ /*----------------------------------------------------------------------------
Either unload or reload contents of class <relname>, depending on <from>.
If <pipe> is false, transfer is between the class and the file named
<filename>. Otherwise, transfer is between the class and our regular
input/output stream. The latter could be either stdin/stdout or a
socket, depending on whether we're running under Postmaster control.
Iff <binary>, unload or reload in the binary format, as opposed to the
more wasteful but more robust and portable text format.
If in the text format, delimit columns with delimiter <delim>.
When loading in the text format from an input stream (as opposed to
a file), recognize a "." on a line by itself as EOF. Also recognize
a stream EOF. When unloading in the text format to an output stream,
write a "." on a line by itself at the end of the data.
Iff <oids>, unload or reload the format that includes OID information.
Do not allow a Postgres user without superuser privilege to read from
or write to a file.
Do not allow the copy if user doesn't have proper permission to access
the class.
----------------------------------------------------------------------------*/
FILE *fp; FILE *fp;
Relation rel; Relation rel;
reading_from_input = pipe; extern char *UserName; /* defined in global.c */
const AclMode required_access = from ? ACL_WR : ACL_RD;
rel = heap_openr(relname); rel = heap_openr(relname);
if (rel == NULL) elog(WARN, "Copy: class %s does not exist.", relname); if (rel == NULL) elog(WARN, "COPY command failed. Class %s "
"does not exist.", relname);
if (from) {
if (pipe && IsUnderPostmaster) ReceiveCopyBegin(); if (!pg_aclcheck(relname, UserName, required_access))
if (IsUnderPostmaster) { elog(WARN, "%s %s", relname, ACL_NO_PRIV_WARNING);
fp = pipe ? Pfin : fopen(filename, "r"); /* Above should not return */
}else { else if (!superuser() && !pipe)
fp = pipe ? stdin : fopen(filename, "r"); elog(WARN, "You must have Postgres superuser privilege to do a COPY "
} "directly to or from a file. Anyone can COPY to stdout or "
if (fp == NULL) { "from stdin. Psql's \\copy command also works for anyone.");
elog(WARN, "COPY: file %s could not be open for reading", filename); /* Above should not return. */
} else {
CopyFrom(rel, binary, oids, fp, delim); if (from) { /* copy from file to database */
}else { if (pipe) {
if (IsUnderPostmaster) {
mode_t oumask = umask((mode_t) 0); ReceiveCopyBegin();
fp = Pfin;
if (pipe && IsUnderPostmaster) SendCopyBegin(); } else fp = stdin;
if (IsUnderPostmaster) { } else {
fp = pipe ? Pfout : fopen(filename, "w"); fp = fopen(filename, "r");
if (fp == NULL)
}else { elog(WARN, "COPY command, running in backend with "
fp = pipe ? stdout : fopen(filename, "w"); "effective uid %d, could not open file '%s' for ",
} "reading. Errno = %s (%d).",
(void) umask(oumask); geteuid(), filename, strerror(errno), errno);
if (fp == NULL) { /* Above should not return */
elog(WARN, "COPY: file %s could not be open for writing", filename); }
} CopyFrom(rel, binary, oids, fp, delim);
CopyTo(rel, binary, oids, fp, delim); } else { /* copy from database to file */
} if (pipe) {
if (!pipe) { if (IsUnderPostmaster) {
fclose(fp); SendCopyBegin();
}else if (!from && !binary) { fp = Pfout;
fputs("\\.\n", fp); } else fp = stdout;
if (IsUnderPostmaster) fflush(Pfout); } else {
mode_t oumask; /* Pre-existing umask value */
(void) umask((mode_t) 0);
fp = fopen(filename, "w");
(void) umask(oumask);
if (fp == NULL)
elog(WARN, "COPY command, running in backend with "
"effective uid %d, could not open file '%s' for ",
"writing. Errno = %s (%d).",
geteuid(), filename, strerror(errno), errno);
/* Above should not return */
}
CopyTo(rel, binary, oids, fp, delim);
}
if (!pipe) fclose(fp);
else if (!from && !binary) {
fputs("\\.\n", fp);
if (IsUnderPostmaster) fflush(Pfout);
}
} }
} }
static void static void
CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim) CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
{ {
...@@ -176,8 +220,14 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim) ...@@ -176,8 +220,14 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
Oid out_func_oid; Oid out_func_oid;
Oid *elements; Oid *elements;
Datum value; Datum value;
bool isnull = (bool) true; bool isnull; /* The attribute we are copying is null */
char *nulls = NULL; char *nulls;
/* <nulls> is a (dynamically allocated) array with one character
per attribute in the instance being copied. nulls[I-1] is
'n' if Attribute Number I is null, and ' ' otherwise.
<nulls> is meaningful only if we are doing a binary copy.
*/
char *string; char *string;
int32 ntuples; int32 ntuples;
TupleDesc tupDesc; TupleDesc tupDesc;
...@@ -189,23 +239,24 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim) ...@@ -189,23 +239,24 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
tupDesc = rel->rd_att; tupDesc = rel->rd_att;
if (!binary) { if (!binary) {
out_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr)); out_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr));
elements = (Oid *) palloc(attr_count * sizeof(Oid)); elements = (Oid *) palloc(attr_count * sizeof(Oid));
for (i = 0; i < attr_count; i++) { for (i = 0; i < attr_count; i++) {
out_func_oid = (Oid) GetOutputFunction(attr[i]->atttypid); out_func_oid = (Oid) GetOutputFunction(attr[i]->atttypid);
fmgr_info(out_func_oid, &out_functions[i], &dummy); fmgr_info(out_func_oid, &out_functions[i], &dummy);
elements[i] = GetTypeElement(attr[i]->atttypid); elements[i] = GetTypeElement(attr[i]->atttypid);
} }
nulls = NULL; /* meaningless, but compiler doesn't know that */
}else { }else {
elements = NULL; elements = NULL;
out_functions = NULL; out_functions = NULL;
nulls = (char *) palloc(attr_count); nulls = (char *) palloc(attr_count);
for (i = 0; i < attr_count; i++) nulls[i] = ' '; for (i = 0; i < attr_count; i++) nulls[i] = ' ';
/* XXX expensive */ /* XXX expensive */
ntuples = CountTuples(rel); ntuples = CountTuples(rel);
fwrite(&ntuples, sizeof(int32), 1, fp); fwrite(&ntuples, sizeof(int32), 1, fp);
} }
for (tuple = heap_getnext(scandesc, 0, NULL); for (tuple = heap_getnext(scandesc, 0, NULL);
...@@ -213,69 +264,69 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim) ...@@ -213,69 +264,69 @@ CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
tuple = heap_getnext(scandesc, 0, NULL)) { tuple = heap_getnext(scandesc, 0, NULL)) {
if (oids && !binary) { if (oids && !binary) {
fputs(oidout(tuple->t_oid),fp); fputs(oidout(tuple->t_oid),fp);
fputc(delim[0], fp); fputc(delim[0], fp);
} }
for (i = 0; i < attr_count; i++) { for (i = 0; i < attr_count; i++) {
value = (Datum) value = (Datum)
heap_getattr(tuple, InvalidBuffer, i+1, tupDesc, &isnull); heap_getattr(tuple, InvalidBuffer, i+1, tupDesc, &isnull);
if (!binary) { if (!binary) {
if (!isnull) { if (!isnull) {
string = (char *) (out_functions[i]) (value, elements[i]); string = (char *) (out_functions[i]) (value, elements[i]);
CopyAttributeOut(fp, string, delim); CopyAttributeOut(fp, string, delim);
pfree(string); pfree(string);
} }
else else
fputs("\\N", fp); /* null indicator */ fputs("\\N", fp); /* null indicator */
if (i == attr_count - 1) { if (i == attr_count - 1) {
fputc('\n', fp); fputc('\n', fp);
}else { }else {
/* when copying out, only use the first char of the delim /* when copying out, only use the first char of the delim
string */ string */
fputc(delim[0], fp); fputc(delim[0], fp);
} }
}else { }else {
/* /*
* only interesting thing heap_getattr tells us in this case * only interesting thing heap_getattr tells us in this case
* is if we have a null attribute or not. * is if we have a null attribute or not.
*/ */
if (isnull) nulls[i] = 'n'; if (isnull) nulls[i] = 'n';
} }
} }
if (binary) { if (binary) {
int32 null_ct = 0, length; int32 null_ct = 0, length;
for (i = 0; i < attr_count; i++) { for (i = 0; i < attr_count; i++) {
if (nulls[i] == 'n') null_ct++; if (nulls[i] == 'n') null_ct++;
} }
length = tuple->t_len - tuple->t_hoff; length = tuple->t_len - tuple->t_hoff;
fwrite(&length, sizeof(int32), 1, fp); fwrite(&length, sizeof(int32), 1, fp);
if (oids) if (oids)
fwrite((char *) &tuple->t_oid, sizeof(int32), 1, fp); fwrite((char *) &tuple->t_oid, sizeof(int32), 1, fp);
fwrite(&null_ct, sizeof(int32), 1, fp); fwrite(&null_ct, sizeof(int32), 1, fp);
if (null_ct > 0) { if (null_ct > 0) {
for (i = 0; i < attr_count; i++) { for (i = 0; i < attr_count; i++) {
if (nulls[i] == 'n') { if (nulls[i] == 'n') {
fwrite(&i, sizeof(int32), 1, fp); fwrite(&i, sizeof(int32), 1, fp);
nulls[i] = ' '; nulls[i] = ' ';
} }
} }
} }
fwrite((char *) tuple + tuple->t_hoff, length, 1, fp); fwrite((char *) tuple + tuple->t_hoff, length, 1, fp);
} }
} }
heap_endscan(scandesc); heap_endscan(scandesc);
if (binary) { if (binary) {
pfree(nulls); pfree(nulls);
}else { }else {
pfree(out_functions); pfree(out_functions);
pfree(elements); pfree(elements);
} }
heap_close(rel); heap_close(rel);
...@@ -337,93 +388,93 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim) ...@@ -337,93 +388,93 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
if (rel->rd_rel->relhasindex) { if (rel->rd_rel->relhasindex) {
GetIndexRelations(rel->rd_id, &n_indices, &index_rels); GetIndexRelations(rel->rd_id, &n_indices, &index_rels);
if (n_indices > 0) { if (n_indices > 0) {
has_index = true; has_index = true;
itupdescArr = itupdescArr =
(TupleDesc *)palloc(n_indices * sizeof(TupleDesc)); (TupleDesc *)palloc(n_indices * sizeof(TupleDesc));
pgIndexP = pgIndexP =
(IndexTupleForm *)palloc(n_indices * sizeof(IndexTupleForm)); (IndexTupleForm *)palloc(n_indices * sizeof(IndexTupleForm));
indexNatts = (int *) palloc(n_indices * sizeof(int)); indexNatts = (int *) palloc(n_indices * sizeof(int));
finfo = (FuncIndexInfo *) palloc(n_indices * sizeof(FuncIndexInfo)); finfo = (FuncIndexInfo *) palloc(n_indices * sizeof(FuncIndexInfo));
finfoP = (FuncIndexInfo **) palloc(n_indices * sizeof(FuncIndexInfo *)); finfoP = (FuncIndexInfo **) palloc(n_indices * sizeof(FuncIndexInfo *));
indexPred = (Node **) palloc(n_indices * sizeof(Node*)); indexPred = (Node **) palloc(n_indices * sizeof(Node*));
econtext = NULL; econtext = NULL;
for (i = 0; i < n_indices; i++) { for (i = 0; i < n_indices; i++) {
itupdescArr[i] = RelationGetTupleDescriptor(index_rels[i]); itupdescArr[i] = RelationGetTupleDescriptor(index_rels[i]);
pgIndexTup = pgIndexTup =
SearchSysCacheTuple(INDEXRELID, SearchSysCacheTuple(INDEXRELID,
ObjectIdGetDatum(index_rels[i]->rd_id), ObjectIdGetDatum(index_rels[i]->rd_id),
0,0,0); 0,0,0);
Assert(pgIndexTup); Assert(pgIndexTup);
pgIndexP[i] = (IndexTupleForm)GETSTRUCT(pgIndexTup); pgIndexP[i] = (IndexTupleForm)GETSTRUCT(pgIndexTup);
for (attnumP = &(pgIndexP[i]->indkey[0]), natts = 0; for (attnumP = &(pgIndexP[i]->indkey[0]), natts = 0;
*attnumP != InvalidAttrNumber; *attnumP != InvalidAttrNumber;
attnumP++, natts++); attnumP++, natts++);
if (pgIndexP[i]->indproc != InvalidOid) { if (pgIndexP[i]->indproc != InvalidOid) {
FIgetnArgs(&finfo[i]) = natts; FIgetnArgs(&finfo[i]) = natts;
natts = 1; natts = 1;
FIgetProcOid(&finfo[i]) = pgIndexP[i]->indproc; FIgetProcOid(&finfo[i]) = pgIndexP[i]->indproc;
*(FIgetname(&finfo[i])) = '\0'; *(FIgetname(&finfo[i])) = '\0';
finfoP[i] = &finfo[i]; finfoP[i] = &finfo[i];
} else } else
finfoP[i] = (FuncIndexInfo *) NULL; finfoP[i] = (FuncIndexInfo *) NULL;
indexNatts[i] = natts; indexNatts[i] = natts;
if (VARSIZE(&pgIndexP[i]->indpred) != 0) { if (VARSIZE(&pgIndexP[i]->indpred) != 0) {
predString = fmgr(F_TEXTOUT, &pgIndexP[i]->indpred); predString = fmgr(F_TEXTOUT, &pgIndexP[i]->indpred);
indexPred[i] = stringToNode(predString); indexPred[i] = stringToNode(predString);
pfree(predString); pfree(predString);
/* make dummy ExprContext for use by ExecQual */ /* make dummy ExprContext for use by ExecQual */
if (econtext == NULL) { if (econtext == NULL) {
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
tupleTable = ExecCreateTupleTable(1); tupleTable = ExecCreateTupleTable(1);
slot = ExecAllocTableSlot(tupleTable); slot = ExecAllocTableSlot(tupleTable);
econtext = makeNode(ExprContext); econtext = makeNode(ExprContext);
econtext->ecxt_scantuple = slot; econtext->ecxt_scantuple = slot;
rtupdesc = RelationGetTupleDescriptor(rel); rtupdesc = RelationGetTupleDescriptor(rel);
slot->ttc_tupleDescriptor = rtupdesc; slot->ttc_tupleDescriptor = rtupdesc;
/* /*
* There's no buffer associated with heap tuples here, * There's no buffer associated with heap tuples here,
* so I set the slot's buffer to NULL. Currently, it * so I set the slot's buffer to NULL. Currently, it
* appears that the only way a buffer could be needed * appears that the only way a buffer could be needed
* would be if the partial index predicate referred to * would be if the partial index predicate referred to
* the "lock" system attribute. If it did, then * the "lock" system attribute. If it did, then
* heap_getattr would call HeapTupleGetRuleLock, which * heap_getattr would call HeapTupleGetRuleLock, which
* uses the buffer's descriptor to get the relation id. * uses the buffer's descriptor to get the relation id.
* Rather than try to fix this, I'll just disallow * Rather than try to fix this, I'll just disallow
* partial indexes on "lock", which wouldn't be useful * partial indexes on "lock", which wouldn't be useful
* anyway. --Nels, Nov '92 * anyway. --Nels, Nov '92
*/ */
/* SetSlotBuffer(slot, (Buffer) NULL); */ /* SetSlotBuffer(slot, (Buffer) NULL); */
/* SetSlotShouldFree(slot, false); */ /* SetSlotShouldFree(slot, false); */
slot->ttc_buffer = (Buffer)NULL; slot->ttc_buffer = (Buffer)NULL;
slot->ttc_shouldFree = false; slot->ttc_shouldFree = false;
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
} }
} else { } else {
indexPred[i] = NULL; indexPred[i] = NULL;
} }
} }
} }
} }
if (!binary) if (!binary)
{ {
in_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr)); in_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr));
elements = (Oid *) palloc(attr_count * sizeof(Oid)); elements = (Oid *) palloc(attr_count * sizeof(Oid));
for (i = 0; i < attr_count; i++) for (i = 0; i < attr_count; i++)
{ {
in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid); in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
fmgr_info(in_func_oid, &in_functions[i], &dummy); fmgr_info(in_func_oid, &in_functions[i], &dummy);
elements[i] = GetTypeElement(attr[i]->atttypid); elements[i] = GetTypeElement(attr[i]->atttypid);
} }
} }
else else
{ {
in_functions = NULL; in_functions = NULL;
elements = NULL; elements = NULL;
fread(&ntuples, sizeof(int32), 1, fp); fread(&ntuples, sizeof(int32), 1, fp);
if (ntuples != 0) reading_to_eof = false; if (ntuples != 0) reading_to_eof = false;
} }
values = (Datum *) palloc(sizeof(Datum) * attr_count); values = (Datum *) palloc(sizeof(Datum) * attr_count);
nulls = (char *) palloc(attr_count); nulls = (char *) palloc(attr_count);
...@@ -431,175 +482,175 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim) ...@@ -431,175 +482,175 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
byval = (bool *) palloc(attr_count * sizeof(bool)); byval = (bool *) palloc(attr_count * sizeof(bool));
for (i = 0; i < attr_count; i++) { for (i = 0; i < attr_count; i++) {
nulls[i] = ' '; nulls[i] = ' ';
index_nulls[i] = ' '; index_nulls[i] = ' ';
byval[i] = (bool) IsTypeByVal(attr[i]->atttypid); byval[i] = (bool) IsTypeByVal(attr[i]->atttypid);
} }
while (!done) { while (!done) {
if (!binary) { if (!binary) {
if (oids) { if (oids) {
string = CopyReadAttribute(fp, &isnull, delim); string = CopyReadAttribute(fp, &isnull, delim);
if (string == NULL) if (string == NULL)
done = 1; done = 1;
else { else {
loaded_oid = oidin(string); loaded_oid = oidin(string);
if (loaded_oid < BootstrapObjectIdData) if (loaded_oid < BootstrapObjectIdData)
elog(WARN, "COPY TEXT: Invalid Oid"); elog(WARN, "COPY TEXT: Invalid Oid");
} }
} }
for (i = 0; i < attr_count && !done; i++) { for (i = 0; i < attr_count && !done; i++) {
string = CopyReadAttribute(fp, &isnull, delim); string = CopyReadAttribute(fp, &isnull, delim);
if (isnull) { if (isnull) {
values[i] = PointerGetDatum(NULL); values[i] = PointerGetDatum(NULL);
nulls[i] = 'n'; nulls[i] = 'n';
}else if (string == NULL) { }else if (string == NULL) {
done = 1; done = 1;
}else { }else {
values[i] = values[i] =
(Datum)(in_functions[i])(string, (Datum)(in_functions[i])(string,
elements[i], elements[i],
attr[i]->attlen); attr[i]->attlen);
/* /*
* Sanity check - by reference attributes cannot return * Sanity check - by reference attributes cannot return
* NULL * NULL
*/ */
if (!PointerIsValid(values[i]) && if (!PointerIsValid(values[i]) &&
!(rel->rd_att->attrs[i]->attbyval)) { !(rel->rd_att->attrs[i]->attbyval)) {
elog(WARN, "copy from: Bad file format"); elog(WARN, "copy from: Bad file format");
} }
} }
} }
}else { /* binary */ }else { /* binary */
fread(&len, sizeof(int32), 1, fp); fread(&len, sizeof(int32), 1, fp);
if (feof(fp)) { if (feof(fp)) {
done = 1; done = 1;
}else { }else {
if (oids) { if (oids) {
fread(&loaded_oid, sizeof(int32), 1, fp); fread(&loaded_oid, sizeof(int32), 1, fp);
if (loaded_oid < BootstrapObjectIdData) if (loaded_oid < BootstrapObjectIdData)
elog(WARN, "COPY BINARY: Invalid Oid"); elog(WARN, "COPY BINARY: Invalid Oid");
} }
fread(&null_ct, sizeof(int32), 1, fp); fread(&null_ct, sizeof(int32), 1, fp);
if (null_ct > 0) { if (null_ct > 0) {
for (i = 0; i < null_ct; i++) { for (i = 0; i < null_ct; i++) {
fread(&null_id, sizeof(int32), 1, fp); fread(&null_id, sizeof(int32), 1, fp);
nulls[null_id] = 'n'; nulls[null_id] = 'n';
} }
} }
string = (char *) palloc(len); string = (char *) palloc(len);
fread(string, len, 1, fp); fread(string, len, 1, fp);
ptr = string; ptr = string;
for (i = 0; i < attr_count; i++) { for (i = 0; i < attr_count; i++) {
if (byval[i] && nulls[i] != 'n') { if (byval[i] && nulls[i] != 'n') {
switch(attr[i]->attlen) { switch(attr[i]->attlen) {
case sizeof(char): case sizeof(char):
values[i] = (Datum) *(unsigned char *) ptr; values[i] = (Datum) *(unsigned char *) ptr;
ptr += sizeof(char); ptr += sizeof(char);
break; break;
case sizeof(short): case sizeof(short):
ptr = (char *) SHORTALIGN(ptr); ptr = (char *) SHORTALIGN(ptr);
values[i] = (Datum) *(unsigned short *) ptr; values[i] = (Datum) *(unsigned short *) ptr;
ptr += sizeof(short); ptr += sizeof(short);
break; break;
case sizeof(int32): case sizeof(int32):
ptr = (char *) INTALIGN(ptr); ptr = (char *) INTALIGN(ptr);
values[i] = (Datum) *(uint32 *) ptr; values[i] = (Datum) *(uint32 *) ptr;
ptr += sizeof(int32); ptr += sizeof(int32);
break; break;
default: default:
elog(WARN, "COPY BINARY: impossible size!"); elog(WARN, "COPY BINARY: impossible size!");
break; break;
} }
}else if (nulls[i] != 'n') { }else if (nulls[i] != 'n') {
switch (attr[i]->attlen) { switch (attr[i]->attlen) {
case -1: case -1:
if (attr[i]->attalign == 'd') if (attr[i]->attalign == 'd')
ptr = (char *)DOUBLEALIGN(ptr); ptr = (char *)DOUBLEALIGN(ptr);
else else
ptr = (char *)INTALIGN(ptr); ptr = (char *)INTALIGN(ptr);
values[i] = (Datum) ptr; values[i] = (Datum) ptr;
ptr += * (uint32 *) ptr; ptr += * (uint32 *) ptr;
break; break;
case sizeof(char): case sizeof(char):
values[i] = (Datum)ptr; values[i] = (Datum)ptr;
ptr += attr[i]->attlen; ptr += attr[i]->attlen;
break; break;
case sizeof(short): case sizeof(short):
ptr = (char*)SHORTALIGN(ptr); ptr = (char*)SHORTALIGN(ptr);
values[i] = (Datum)ptr; values[i] = (Datum)ptr;
ptr += attr[i]->attlen; ptr += attr[i]->attlen;
break; break;
case sizeof(int32): case sizeof(int32):
ptr = (char*)INTALIGN(ptr); ptr = (char*)INTALIGN(ptr);
values[i] = (Datum)ptr; values[i] = (Datum)ptr;
ptr += attr[i]->attlen; ptr += attr[i]->attlen;
break; break;
default: default:
if (attr[i]->attalign == 'd') if (attr[i]->attalign == 'd')
ptr = (char *)DOUBLEALIGN(ptr); ptr = (char *)DOUBLEALIGN(ptr);
else else
ptr = (char *)LONGALIGN(ptr); ptr = (char *)LONGALIGN(ptr);
values[i] = (Datum) ptr; values[i] = (Datum) ptr;
ptr += attr[i]->attlen; ptr += attr[i]->attlen;
} }
} }
} }
} }
} }
if (done) continue; if (done) continue;
tupDesc = CreateTupleDesc(attr_count, attr); tupDesc = CreateTupleDesc(attr_count, attr);
tuple = heap_formtuple(tupDesc, values, nulls); tuple = heap_formtuple(tupDesc, values, nulls);
if (oids) if (oids)
tuple->t_oid = loaded_oid; tuple->t_oid = loaded_oid;
heap_insert(rel, tuple); heap_insert(rel, tuple);
if (has_index) { if (has_index) {
for (i = 0; i < n_indices; i++) { for (i = 0; i < n_indices; i++) {
if (indexPred[i] != NULL) { if (indexPred[i] != NULL) {
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* if tuple doesn't satisfy predicate, /* if tuple doesn't satisfy predicate,
* don't update index * don't update index
*/ */
slot->val = tuple; slot->val = tuple;
/*SetSlotContents(slot, tuple); */ /*SetSlotContents(slot, tuple); */
if (ExecQual((List*)indexPred[i], econtext) == false) if (ExecQual((List*)indexPred[i], econtext) == false)
continue; continue;
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
} }
FormIndexDatum(indexNatts[i], FormIndexDatum(indexNatts[i],
(AttrNumber *)&(pgIndexP[i]->indkey[0]), (AttrNumber *)&(pgIndexP[i]->indkey[0]),
tuple, tuple,
tupDesc, tupDesc,
InvalidBuffer, InvalidBuffer,
&idatum, &idatum,
index_nulls, index_nulls,
finfoP[i]); finfoP[i]);
indexRes = index_insert(index_rels[i], &idatum, index_nulls, indexRes = index_insert(index_rels[i], &idatum, index_nulls,
&(tuple->t_ctid)); &(tuple->t_ctid));
if (indexRes) pfree(indexRes); if (indexRes) pfree(indexRes);
} }
} }
if (binary) pfree(string); if (binary) pfree(string);
for (i = 0; i < attr_count; i++) { for (i = 0; i < attr_count; i++) {
if (!byval[i] && nulls[i] != 'n') { if (!byval[i] && nulls[i] != 'n') {
if (!binary) pfree((void*)values[i]); if (!binary) pfree((void*)values[i]);
}else if (nulls[i] == 'n') { }else if (nulls[i] == 'n') {
nulls[i] = ' '; nulls[i] = ' ';
} }
} }
pfree(tuple); pfree(tuple);
tuples_read++; tuples_read++;
if (!reading_to_eof && ntuples == tuples_read) done = true; if (!reading_to_eof && ntuples == tuples_read) done = true;
} }
pfree(values); pfree(values);
if (!binary) pfree(in_functions); if (!binary) pfree(in_functions);
...@@ -608,17 +659,19 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim) ...@@ -608,17 +659,19 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
heap_close(rel); heap_close(rel);
} }
static Oid static Oid
GetOutputFunction(Oid type) GetOutputFunction(Oid type)
{ {
HeapTuple typeTuple; HeapTuple typeTuple;
typeTuple = SearchSysCacheTuple(TYPOID, typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type), ObjectIdGetDatum(type),
0,0,0); 0,0,0);
if (HeapTupleIsValid(typeTuple)) if (HeapTupleIsValid(typeTuple))
return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput); return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput);
elog(WARN, "GetOutputFunction: Cache lookup of type %d failed", type); elog(WARN, "GetOutputFunction: Cache lookup of type %d failed", type);
return(InvalidOid); return(InvalidOid);
...@@ -630,12 +683,12 @@ GetTypeElement(Oid type) ...@@ -630,12 +683,12 @@ GetTypeElement(Oid type)
HeapTuple typeTuple; HeapTuple typeTuple;
typeTuple = SearchSysCacheTuple(TYPOID, typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type), ObjectIdGetDatum(type),
0,0,0); 0,0,0);
if (HeapTupleIsValid(typeTuple)) if (HeapTupleIsValid(typeTuple))
return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem); return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem);
elog(WARN, "GetOutputFunction: Cache lookup of type %d failed", type); elog(WARN, "GetOutputFunction: Cache lookup of type %d failed", type);
return(InvalidOid); return(InvalidOid);
...@@ -647,11 +700,11 @@ GetInputFunction(Oid type) ...@@ -647,11 +700,11 @@ GetInputFunction(Oid type)
HeapTuple typeTuple; HeapTuple typeTuple;
typeTuple = SearchSysCacheTuple(TYPOID, typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type), ObjectIdGetDatum(type),
0,0,0); 0,0,0);
if (HeapTupleIsValid(typeTuple)) if (HeapTupleIsValid(typeTuple))
return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typinput); return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typinput);
elog(WARN, "GetInputFunction: Cache lookup of type %d failed", type); elog(WARN, "GetInputFunction: Cache lookup of type %d failed", type);
return(InvalidOid); return(InvalidOid);
...@@ -663,8 +716,8 @@ IsTypeByVal(Oid type) ...@@ -663,8 +716,8 @@ IsTypeByVal(Oid type)
HeapTuple typeTuple; HeapTuple typeTuple;
typeTuple = SearchSysCacheTuple(TYPOID, typeTuple = SearchSysCacheTuple(TYPOID,
ObjectIdGetDatum(type), ObjectIdGetDatum(type),
0,0,0); 0,0,0);
if (HeapTupleIsValid(typeTuple)) if (HeapTupleIsValid(typeTuple))
return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typbyval); return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typbyval);
...@@ -689,8 +742,8 @@ typedef struct rel_list { ...@@ -689,8 +742,8 @@ typedef struct rel_list {
static void static void
GetIndexRelations(Oid main_relation_oid, GetIndexRelations(Oid main_relation_oid,
int *n_indices, int *n_indices,
Relation **index_rels) Relation **index_rels)
{ {
RelationList *head, *scan; RelationList *head, *scan;
Relation pg_index_rel; Relation pg_index_rel;
...@@ -714,19 +767,19 @@ GetIndexRelations(Oid main_relation_oid, ...@@ -714,19 +767,19 @@ GetIndexRelations(Oid main_relation_oid,
for (tuple = heap_getnext(scandesc, 0, NULL); for (tuple = heap_getnext(scandesc, 0, NULL);
tuple != NULL; tuple != NULL;
tuple = heap_getnext(scandesc, 0, NULL)) { tuple = heap_getnext(scandesc, 0, NULL)) {
index_relation_oid = index_relation_oid =
(Oid) DatumGetInt32(heap_getattr(tuple, InvalidBuffer, 2, (Oid) DatumGetInt32(heap_getattr(tuple, InvalidBuffer, 2,
tupDesc, &isnull)); tupDesc, &isnull));
if (index_relation_oid == main_relation_oid) { if (index_relation_oid == main_relation_oid) {
scan->index_rel_oid = scan->index_rel_oid =
(Oid) DatumGetInt32(heap_getattr(tuple, InvalidBuffer, (Oid) DatumGetInt32(heap_getattr(tuple, InvalidBuffer,
Anum_pg_index_indexrelid, Anum_pg_index_indexrelid,
tupDesc, &isnull)); tupDesc, &isnull));
(*n_indices)++; (*n_indices)++;
scan->next = (RelationList *) palloc(sizeof(RelationList)); scan->next = (RelationList *) palloc(sizeof(RelationList));
scan = scan->next; scan = scan->next;
} }
} }
heap_endscan(scandesc); heap_endscan(scandesc);
...@@ -739,13 +792,13 @@ GetIndexRelations(Oid main_relation_oid, ...@@ -739,13 +792,13 @@ GetIndexRelations(Oid main_relation_oid,
*index_rels = (Relation *) palloc(*n_indices * sizeof(Relation)); *index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next) { for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next) {
(*index_rels)[i] = index_open(scan->index_rel_oid); (*index_rels)[i] = index_open(scan->index_rel_oid);
} }
for (i = 0, scan = head; i < *n_indices + 1; i++) { for (i = 0, scan = head; i < *n_indices + 1; i++) {
scan = head->next; scan = head->next;
pfree(head); pfree(head);
head = scan; head = scan;
} }
} }
...@@ -760,12 +813,12 @@ inString(char c, char* s) ...@@ -760,12 +813,12 @@ inString(char c, char* s)
int i; int i;
if (s) { if (s) {
i = 0; i = 0;
while (s[i] != '\0') { while (s[i] != '\0') {
if (s[i] == c) if (s[i] == c)
return 1; return 1;
i++; i++;
} }
} }
return 0; return 0;
} }
...@@ -785,17 +838,17 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim) ...@@ -785,17 +838,17 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
int done = 0; int done = 0;
int i = 0; int i = 0;
*isnull = (bool) false; /* set default */ *isnull = (bool) false; /* set default */
if (feof(fp)) if (feof(fp))
return(NULL); return(NULL);
while (!done) { while (!done) {
c = getc(fp); c = getc(fp);
if (feof(fp)) if (feof(fp))
return(NULL); return(NULL);
else if (c == '\\') { else if (c == '\\') {
c = getc(fp); c = getc(fp);
if (feof(fp)) if (feof(fp))
return(NULL); return(NULL);
switch (c) { switch (c) {
...@@ -847,22 +900,22 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim) ...@@ -847,22 +900,22 @@ CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
c = '\v'; c = '\v';
break; break;
case 'N': case 'N':
attribute[0] = '\0'; /* just to be safe */ attribute[0] = '\0'; /* just to be safe */
*isnull = (bool) true; *isnull = (bool) true;
break; break;
case '.': case '.':
c = getc(fp); c = getc(fp);
if (c != '\n') if (c != '\n')
elog(WARN, "CopyReadAttribute - end of record marker corrupted"); elog(WARN, "CopyReadAttribute - end of record marker corrupted");
return(NULL); return(NULL);
break; break;
} }
}else if (inString(c,delim) || c == '\n') { }else if (inString(c,delim) || c == '\n') {
done = 1; done = 1;
} }
if (!done) attribute[i++] = c; if (!done) attribute[i++] = c;
if (i == EXT_ATTLEN - 1) if (i == EXT_ATTLEN - 1)
elog(WARN, "CopyReadAttribute - attribute length too long"); elog(WARN, "CopyReadAttribute - attribute length too long");
} }
attribute[i] = '\0'; attribute[i] = '\0';
return(&attribute[0]); return(&attribute[0]);
...@@ -879,7 +932,7 @@ CopyAttributeOut(FILE *fp, char *string, char *delim) ...@@ -879,7 +932,7 @@ CopyAttributeOut(FILE *fp, char *string, char *delim)
if (len && (string[0] == '{') && (string[len-1] == '}')) if (len && (string[0] == '{') && (string[len-1] == '}'))
is_array = true; is_array = true;
for ( ; (c = *string) != 0; string++) { for ( ; (c = *string) != '\0'; string++) {
if (c == delim[0] || c == '\n' || if (c == delim[0] || c == '\n' ||
(c == '\\' && !is_array)) (c == '\\' && !is_array))
fputc('\\', fp); fputc('\\', fp);
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.3 1996/10/31 09:07:41 bryanh Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/define.c,v 1.4 1996/11/02 02:01:48 bryanh Exp $
* *
* DESCRIPTION * DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the * The "DefineFoo" routines take the parse tree and pick out the
...@@ -34,19 +34,16 @@ ...@@ -34,19 +34,16 @@
*/ */
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#include <math.h>
#include <postgres.h> #include <postgres.h>
#include <access/heapam.h> #include <access/heapam.h>
#include <access/htup.h>
#include <utils/tqual.h> #include <utils/tqual.h>
#include <catalog/catname.h> #include <catalog/catname.h>
#include <catalog/pg_aggregate.h> #include <catalog/pg_aggregate.h>
#include <catalog/pg_operator.h> #include <catalog/pg_operator.h>
#include <catalog/pg_proc.h> #include <catalog/pg_proc.h>
#include <catalog/pg_type.h> #include <catalog/pg_type.h>
#include <catalog/pg_user.h> /* superuser() uses this */
#include <utils/syscache.h> #include <utils/syscache.h>
#include <nodes/pg_list.h> #include <nodes/pg_list.h>
#include <nodes/parsenodes.h> #include <nodes/parsenodes.h>
...@@ -66,24 +63,6 @@ static int defGetTypeLength(DefElem *def); ...@@ -66,24 +63,6 @@ static int defGetTypeLength(DefElem *def);
#define DEFAULT_TYPDELIM ',' #define DEFAULT_TYPDELIM ','
bool
superuser(void) {
/*--------------------------------------------------------------------------
The Postgres user running this command has Postgres superuser
privileges.
--------------------------------------------------------------------------*/
HeapTuple utup;
char *userName;
userName = GetPgUserName();
utup = SearchSysCacheTuple(USENAME, PointerGetDatum(userName),
0,0,0);
Assert(utup != NULL);
return ((Form_pg_user)GETSTRUCT(utup))->usesuper;
}
void void
case_translate_language_name(const char *input, char *output) { case_translate_language_name(const char *input, char *output) {
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment