aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/copy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/copy.c')
-rw-r--r--src/backend/commands/copy.c1884
1 files changed, 1017 insertions, 867 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 687cd1eb12e..795e9f5584f 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.29 1997/09/04 13:18:59 vadim Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.30 1997/09/07 04:40:40 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,736 +42,857 @@
/* non-export function prototypes */
-static void CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim);
-static void CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim);
-static Oid GetOutputFunction(Oid type);
-static Oid GetTypeElement(Oid type);
-static Oid GetInputFunction(Oid type);
-static Oid IsTypeByVal(Oid type);
-static void GetIndexRelations(Oid main_relation_oid,
- int *n_indices,
- Relation **index_rels);
+static void CopyTo(Relation rel, bool binary, bool oids, FILE * fp, char *delim);
+static void CopyFrom(Relation rel, bool binary, bool oids, FILE * fp, char *delim);
+static Oid GetOutputFunction(Oid type);
+static Oid GetTypeElement(Oid type);
+static Oid GetInputFunction(Oid type);
+static Oid IsTypeByVal(Oid type);
+static void
+GetIndexRelations(Oid main_relation_oid,
+ int *n_indices,
+ Relation ** index_rels);
+
#ifdef COPY_PATCH
-static void CopyReadNewline(FILE *fp, int *newline);
-static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline);
+static void CopyReadNewline(FILE * fp, int *newline);
+static char *CopyReadAttribute(FILE * fp, bool * isnull, char *delim, int *newline);
+
#else
-static char *CopyReadAttribute(FILE *fp, bool *isnull, char *delim);
+static char *CopyReadAttribute(FILE * fp, bool * isnull, char *delim);
+
#endif
-static void CopyAttributeOut(FILE *fp, char *string, char *delim);
-static int CountTuples(Relation relation);
+static void CopyAttributeOut(FILE * fp, char *string, char *delim);
+static int CountTuples(Relation relation);
-extern FILE *Pfout, *Pfin;
+extern FILE *Pfout,
+ *Pfin;
#ifdef COPY_DEBUG
-static int lineno;
+static int lineno;
+
#endif
-
+
/*
- * DoCopy executes a the SQL COPY statement.
+ * DoCopy executes a the SQL COPY statement.
*/
void
-DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
- char *filename, char *delim) {
+DoCopy(char *relname, bool binary, bool oids, bool from, bool pipe,
+ 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
+ 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.
+ more wasteful but more robust and portable text format.
- If in the text format, delimit columns with delimiter <delim>.
+ 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 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.
+ or write to a file.
Do not allow the copy if user doesn't have proper permission to access
the class.
----------------------------------------------------------------------------*/
- FILE *fp;
- Relation rel;
- extern char *UserName; /* defined in global.c */
- const AclMode required_access = from ? ACL_WR : ACL_RD;
- int result;
-
- rel = heap_openr(relname);
- if (rel == NULL) elog(WARN, "COPY command failed. Class %s "
- "does not exist.", relname);
-
- result = pg_aclcheck(relname, UserName, required_access);
- if(result != ACLCHECK_OK)
- elog(WARN, "%s: %s", relname, aclcheck_error_strings[result]);
- /* Above should not return */
- else if (!superuser() && !pipe)
- elog(WARN, "You must have Postgres superuser privilege to do a COPY "
- "directly to or from a file. Anyone can COPY to stdout or "
- "from stdin. Psql's \\copy command also works for anyone.");
- /* Above should not return. */
- else {
- if (from) { /* copy from file to database */
- if ( rel->rd_rel->relkind == RELKIND_SEQUENCE )
- elog (WARN, "You can't change sequence relation %s", relname);
- if (pipe) {
- if (IsUnderPostmaster) {
- ReceiveCopyBegin();
- fp = Pfin;
- } else fp = stdin;
- } else {
- fp = AllocateFile(filename, "r");
- if (fp == NULL)
- elog(WARN, "COPY command, running in backend with "
- "effective uid %d, could not open file '%s' for "
- "reading. Errno = %s (%d).",
- geteuid(), filename, strerror(errno), errno);
- /* Above should not return */
- }
- CopyFrom(rel, binary, oids, fp, delim);
- } else { /* copy from database to file */
- if (pipe) {
- if (IsUnderPostmaster) {
- SendCopyBegin();
- fp = Pfout;
- } else fp = stdout;
- } else {
- mode_t oumask; /* Pre-existing umask value */
- oumask = umask((mode_t) 0);
- fp = AllocateFile(filename, "w");
- 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)
- FreeFile(fp);
- else if (!from && !binary) {
- fputs("\\.\n", fp);
- if (IsUnderPostmaster) fflush(Pfout);
- }
- }
+ FILE *fp;
+ Relation rel;
+ extern char *UserName; /* defined in global.c */
+ const AclMode required_access = from ? ACL_WR : ACL_RD;
+ int result;
+
+ rel = heap_openr(relname);
+ if (rel == NULL)
+ elog(WARN, "COPY command failed. Class %s "
+ "does not exist.", relname);
+
+ result = pg_aclcheck(relname, UserName, required_access);
+ if (result != ACLCHECK_OK)
+ elog(WARN, "%s: %s", relname, aclcheck_error_strings[result]);
+ /* Above should not return */
+ else if (!superuser() && !pipe)
+ elog(WARN, "You must have Postgres superuser privilege to do a COPY "
+ "directly to or from a file. Anyone can COPY to stdout or "
+ "from stdin. Psql's \\copy command also works for anyone.");
+ /* Above should not return. */
+ else
+ {
+ if (from)
+ { /* copy from file to database */
+ if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
+ elog(WARN, "You can't change sequence relation %s", relname);
+ if (pipe)
+ {
+ if (IsUnderPostmaster)
+ {
+ ReceiveCopyBegin();
+ fp = Pfin;
+ }
+ else
+ fp = stdin;
+ }
+ else
+ {
+ fp = AllocateFile(filename, "r");
+ if (fp == NULL)
+ elog(WARN, "COPY command, running in backend with "
+ "effective uid %d, could not open file '%s' for "
+ "reading. Errno = %s (%d).",
+ geteuid(), filename, strerror(errno), errno);
+ /* Above should not return */
+ }
+ CopyFrom(rel, binary, oids, fp, delim);
+ }
+ else
+ { /* copy from database to file */
+ if (pipe)
+ {
+ if (IsUnderPostmaster)
+ {
+ SendCopyBegin();
+ fp = Pfout;
+ }
+ else
+ fp = stdout;
+ }
+ else
+ {
+ mode_t oumask; /* Pre-existing umask value */
+
+ oumask = umask((mode_t) 0);
+ fp = AllocateFile(filename, "w");
+ 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)
+ FreeFile(fp);
+ else if (!from && !binary)
+ {
+ fputs("\\.\n", fp);
+ if (IsUnderPostmaster)
+ fflush(Pfout);
+ }
+ }
}
static void
-CopyTo(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
+CopyTo(Relation rel, bool binary, bool oids, FILE * fp, char *delim)
{
- HeapTuple tuple;
- HeapScanDesc scandesc;
-
- int32 attr_count, i;
- AttributeTupleForm *attr;
- func_ptr *out_functions;
- int dummy;
- Oid out_func_oid;
- Oid *elements;
- Datum value;
- bool isnull; /* The attribute we are copying is 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;
- int32 ntuples;
- TupleDesc tupDesc;
-
- scandesc = heap_beginscan(rel, 0, NULL, 0, NULL);
-
- attr_count = rel->rd_att->natts;
- attr = rel->rd_att->attrs;
- tupDesc = rel->rd_att;
-
- if (!binary) {
- out_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr));
- elements = (Oid *) palloc(attr_count * sizeof(Oid));
- for (i = 0; i < attr_count; i++) {
- out_func_oid = (Oid) GetOutputFunction(attr[i]->atttypid);
- fmgr_info(out_func_oid, &out_functions[i], &dummy);
- elements[i] = GetTypeElement(attr[i]->atttypid);
- }
- nulls = NULL; /* meaningless, but compiler doesn't know that */
- }else {
- elements = NULL;
- out_functions = NULL;
- nulls = (char *) palloc(attr_count);
- for (i = 0; i < attr_count; i++) nulls[i] = ' ';
-
- /* XXX expensive */
-
- ntuples = CountTuples(rel);
- fwrite(&ntuples, sizeof(int32), 1, fp);
- }
-
- for (tuple = heap_getnext(scandesc, 0, NULL);
- tuple != NULL;
- tuple = heap_getnext(scandesc, 0, NULL)) {
-
- if (oids && !binary) {
- fputs(oidout(tuple->t_oid),fp);
- fputc(delim[0], fp);
- }
-
- for (i = 0; i < attr_count; i++) {
- value = (Datum)
- heap_getattr(tuple, InvalidBuffer, i+1, tupDesc, &isnull);
- if (!binary) {
- if (!isnull) {
- string = (char *) (out_functions[i]) (value, elements[i]);
- CopyAttributeOut(fp, string, delim);
- pfree(string);
- }
- else
- fputs("\\N", fp); /* null indicator */
-
- if (i == attr_count - 1) {
- fputc('\n', fp);
- }else {
- /* when copying out, only use the first char of the delim
- string */
- fputc(delim[0], fp);
- }
- }else {
- /*
- * only interesting thing heap_getattr tells us in this case
- * is if we have a null attribute or not.
- */
- if (isnull) nulls[i] = 'n';
- }
- }
-
- if (binary) {
- int32 null_ct = 0, length;
-
- for (i = 0; i < attr_count; i++) {
- if (nulls[i] == 'n') null_ct++;
- }
-
- length = tuple->t_len - tuple->t_hoff;
- fwrite(&length, sizeof(int32), 1, fp);
- if (oids)
- fwrite((char *) &tuple->t_oid, sizeof(int32), 1, fp);
-
- fwrite(&null_ct, sizeof(int32), 1, fp);
- if (null_ct > 0) {
- for (i = 0; i < attr_count; i++) {
- if (nulls[i] == 'n') {
- fwrite(&i, sizeof(int32), 1, fp);
- nulls[i] = ' ';
- }
- }
- }
- fwrite((char *) tuple + tuple->t_hoff, length, 1, fp);
- }
- }
-
- heap_endscan(scandesc);
- if (binary) {
- pfree(nulls);
- }else {
- pfree(out_functions);
- pfree(elements);
- }
-
- heap_close(rel);
+ HeapTuple tuple;
+ HeapScanDesc scandesc;
+
+ int32 attr_count,
+ i;
+ AttributeTupleForm *attr;
+ func_ptr *out_functions;
+ int dummy;
+ Oid out_func_oid;
+ Oid *elements;
+ Datum value;
+ bool isnull; /* The attribute we are copying is 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;
+ int32 ntuples;
+ TupleDesc tupDesc;
+
+ scandesc = heap_beginscan(rel, 0, NULL, 0, NULL);
+
+ attr_count = rel->rd_att->natts;
+ attr = rel->rd_att->attrs;
+ tupDesc = rel->rd_att;
+
+ if (!binary)
+ {
+ out_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr));
+ elements = (Oid *) palloc(attr_count * sizeof(Oid));
+ for (i = 0; i < attr_count; i++)
+ {
+ out_func_oid = (Oid) GetOutputFunction(attr[i]->atttypid);
+ fmgr_info(out_func_oid, &out_functions[i], &dummy);
+ elements[i] = GetTypeElement(attr[i]->atttypid);
+ }
+ nulls = NULL; /* meaningless, but compiler doesn't know
+ * that */
+ }
+ else
+ {
+ elements = NULL;
+ out_functions = NULL;
+ nulls = (char *) palloc(attr_count);
+ for (i = 0; i < attr_count; i++)
+ nulls[i] = ' ';
+
+ /* XXX expensive */
+
+ ntuples = CountTuples(rel);
+ fwrite(&ntuples, sizeof(int32), 1, fp);
+ }
+
+ for (tuple = heap_getnext(scandesc, 0, NULL);
+ tuple != NULL;
+ tuple = heap_getnext(scandesc, 0, NULL))
+ {
+
+ if (oids && !binary)
+ {
+ fputs(oidout(tuple->t_oid), fp);
+ fputc(delim[0], fp);
+ }
+
+ for (i = 0; i < attr_count; i++)
+ {
+ value = (Datum)
+ heap_getattr(tuple, InvalidBuffer, i + 1, tupDesc, &isnull);
+ if (!binary)
+ {
+ if (!isnull)
+ {
+ string = (char *) (out_functions[i]) (value, elements[i]);
+ CopyAttributeOut(fp, string, delim);
+ pfree(string);
+ }
+ else
+ fputs("\\N", fp); /* null indicator */
+
+ if (i == attr_count - 1)
+ {
+ fputc('\n', fp);
+ }
+ else
+ {
+
+ /*
+ * when copying out, only use the first char of the
+ * delim string
+ */
+ fputc(delim[0], fp);
+ }
+ }
+ else
+ {
+
+ /*
+ * only interesting thing heap_getattr tells us in this
+ * case is if we have a null attribute or not.
+ */
+ if (isnull)
+ nulls[i] = 'n';
+ }
+ }
+
+ if (binary)
+ {
+ int32 null_ct = 0,
+ length;
+
+ for (i = 0; i < attr_count; i++)
+ {
+ if (nulls[i] == 'n')
+ null_ct++;
+ }
+
+ length = tuple->t_len - tuple->t_hoff;
+ fwrite(&length, sizeof(int32), 1, fp);
+ if (oids)
+ fwrite((char *) &tuple->t_oid, sizeof(int32), 1, fp);
+
+ fwrite(&null_ct, sizeof(int32), 1, fp);
+ if (null_ct > 0)
+ {
+ for (i = 0; i < attr_count; i++)
+ {
+ if (nulls[i] == 'n')
+ {
+ fwrite(&i, sizeof(int32), 1, fp);
+ nulls[i] = ' ';
+ }
+ }
+ }
+ fwrite((char *) tuple + tuple->t_hoff, length, 1, fp);
+ }
+ }
+
+ heap_endscan(scandesc);
+ if (binary)
+ {
+ pfree(nulls);
+ }
+ else
+ {
+ pfree(out_functions);
+ pfree(elements);
+ }
+
+ heap_close(rel);
}
static void
-CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
+CopyFrom(Relation rel, bool binary, bool oids, FILE * fp, char *delim)
{
- HeapTuple tuple;
- AttrNumber attr_count;
- AttributeTupleForm *attr;
- func_ptr *in_functions;
- int i, dummy;
- Oid in_func_oid;
- Datum *values;
- char *nulls, *index_nulls;
- bool *byval;
- bool isnull;
- bool has_index;
- int done = 0;
- char *string = NULL, *ptr;
- Relation *index_rels;
- int32 len, null_ct, null_id;
- int32 ntuples, tuples_read = 0;
- bool reading_to_eof = true;
- Oid *elements;
- FuncIndexInfo *finfo, **finfoP = NULL;
- TupleDesc *itupdescArr;
- HeapTuple pgIndexTup;
- IndexTupleForm *pgIndexP = NULL;
- int *indexNatts = NULL;
- char *predString;
- Node **indexPred = NULL;
- TupleDesc rtupdesc;
- ExprContext *econtext = NULL;
+ HeapTuple tuple;
+ AttrNumber attr_count;
+ AttributeTupleForm *attr;
+ func_ptr *in_functions;
+ int i,
+ dummy;
+ Oid in_func_oid;
+ Datum *values;
+ char *nulls,
+ *index_nulls;
+ bool *byval;
+ bool isnull;
+ bool has_index;
+ int done = 0;
+ char *string = NULL,
+ *ptr;
+ Relation *index_rels;
+ int32 len,
+ null_ct,
+ null_id;
+ int32 ntuples,
+ tuples_read = 0;
+ bool reading_to_eof = true;
+ Oid *elements;
+ FuncIndexInfo *finfo,
+ **finfoP = NULL;
+ TupleDesc *itupdescArr;
+ HeapTuple pgIndexTup;
+ IndexTupleForm *pgIndexP = NULL;
+ int *indexNatts = NULL;
+ char *predString;
+ Node **indexPred = NULL;
+ TupleDesc rtupdesc;
+ ExprContext *econtext = NULL;
+
#ifndef OMIT_PARTIAL_INDEX
- TupleTable tupleTable;
- TupleTableSlot *slot = NULL;
+ TupleTable tupleTable;
+ TupleTableSlot *slot = NULL;
+
#endif
- int natts;
- AttrNumber *attnumP;
- Datum *idatum;
- int n_indices;
- InsertIndexResult indexRes;
- TupleDesc tupDesc;
- Oid loaded_oid;
- bool skip_tuple = false;
-
- tupDesc = RelationGetTupleDescriptor(rel);
- attr = tupDesc->attrs;
- attr_count = tupDesc->natts;
-
- has_index = false;
-
- /*
- * This may be a scalar or a functional index. We initialize all
- * kinds of arrays here to avoid doing extra work at every tuple
- * copy.
- */
-
- if (rel->rd_rel->relhasindex) {
- GetIndexRelations(rel->rd_id, &n_indices, &index_rels);
- if (n_indices > 0) {
- has_index = true;
- itupdescArr =
- (TupleDesc *)palloc(n_indices * sizeof(TupleDesc));
- pgIndexP =
- (IndexTupleForm *)palloc(n_indices * sizeof(IndexTupleForm));
- indexNatts = (int *) palloc(n_indices * sizeof(int));
- finfo = (FuncIndexInfo *) palloc(n_indices * sizeof(FuncIndexInfo));
- finfoP = (FuncIndexInfo **) palloc(n_indices * sizeof(FuncIndexInfo *));
- indexPred = (Node **) palloc(n_indices * sizeof(Node*));
- econtext = NULL;
- for (i = 0; i < n_indices; i++) {
- itupdescArr[i] = RelationGetTupleDescriptor(index_rels[i]);
- pgIndexTup =
- SearchSysCacheTuple(INDEXRELID,
- ObjectIdGetDatum(index_rels[i]->rd_id),
- 0,0,0);
- Assert(pgIndexTup);
- pgIndexP[i] = (IndexTupleForm)GETSTRUCT(pgIndexTup);
- for (attnumP = &(pgIndexP[i]->indkey[0]), natts = 0;
- *attnumP != InvalidAttrNumber;
- attnumP++, natts++);
- if (pgIndexP[i]->indproc != InvalidOid) {
- FIgetnArgs(&finfo[i]) = natts;
- natts = 1;
- FIgetProcOid(&finfo[i]) = pgIndexP[i]->indproc;
- *(FIgetname(&finfo[i])) = '\0';
- finfoP[i] = &finfo[i];
- } else
- finfoP[i] = (FuncIndexInfo *) NULL;
- indexNatts[i] = natts;
- if (VARSIZE(&pgIndexP[i]->indpred) != 0) {
- predString = fmgr(F_TEXTOUT, &pgIndexP[i]->indpred);
- indexPred[i] = stringToNode(predString);
- pfree(predString);
- /* make dummy ExprContext for use by ExecQual */
- if (econtext == NULL) {
+ int natts;
+ AttrNumber *attnumP;
+ Datum *idatum;
+ int n_indices;
+ InsertIndexResult indexRes;
+ TupleDesc tupDesc;
+ Oid loaded_oid;
+ bool skip_tuple = false;
+
+ tupDesc = RelationGetTupleDescriptor(rel);
+ attr = tupDesc->attrs;
+ attr_count = tupDesc->natts;
+
+ has_index = false;
+
+ /*
+ * This may be a scalar or a functional index. We initialize all
+ * kinds of arrays here to avoid doing extra work at every tuple copy.
+ */
+
+ if (rel->rd_rel->relhasindex)
+ {
+ GetIndexRelations(rel->rd_id, &n_indices, &index_rels);
+ if (n_indices > 0)
+ {
+ has_index = true;
+ itupdescArr =
+ (TupleDesc *) palloc(n_indices * sizeof(TupleDesc));
+ pgIndexP =
+ (IndexTupleForm *) palloc(n_indices * sizeof(IndexTupleForm));
+ indexNatts = (int *) palloc(n_indices * sizeof(int));
+ finfo = (FuncIndexInfo *) palloc(n_indices * sizeof(FuncIndexInfo));
+ finfoP = (FuncIndexInfo **) palloc(n_indices * sizeof(FuncIndexInfo *));
+ indexPred = (Node **) palloc(n_indices * sizeof(Node *));
+ econtext = NULL;
+ for (i = 0; i < n_indices; i++)
+ {
+ itupdescArr[i] = RelationGetTupleDescriptor(index_rels[i]);
+ pgIndexTup =
+ SearchSysCacheTuple(INDEXRELID,
+ ObjectIdGetDatum(index_rels[i]->rd_id),
+ 0, 0, 0);
+ Assert(pgIndexTup);
+ pgIndexP[i] = (IndexTupleForm) GETSTRUCT(pgIndexTup);
+ for (attnumP = &(pgIndexP[i]->indkey[0]), natts = 0;
+ *attnumP != InvalidAttrNumber;
+ attnumP++, natts++);
+ if (pgIndexP[i]->indproc != InvalidOid)
+ {
+ FIgetnArgs(&finfo[i]) = natts;
+ natts = 1;
+ FIgetProcOid(&finfo[i]) = pgIndexP[i]->indproc;
+ *(FIgetname(&finfo[i])) = '\0';
+ finfoP[i] = &finfo[i];
+ }
+ else
+ finfoP[i] = (FuncIndexInfo *) NULL;
+ indexNatts[i] = natts;
+ if (VARSIZE(&pgIndexP[i]->indpred) != 0)
+ {
+ predString = fmgr(F_TEXTOUT, &pgIndexP[i]->indpred);
+ indexPred[i] = stringToNode(predString);
+ pfree(predString);
+ /* make dummy ExprContext for use by ExecQual */
+ if (econtext == NULL)
+ {
#ifndef OMIT_PARTIAL_INDEX
- tupleTable = ExecCreateTupleTable(1);
- slot = ExecAllocTableSlot(tupleTable);
- econtext = makeNode(ExprContext);
- econtext->ecxt_scantuple = slot;
- rtupdesc = RelationGetTupleDescriptor(rel);
- slot->ttc_tupleDescriptor = rtupdesc;
- /*
- * There's no buffer associated with heap tuples here,
- * so I set the slot's buffer to NULL. Currently, it
- * appears that the only way a buffer could be needed
- * would be if the partial index predicate referred to
- * the "lock" system attribute. If it did, then
- * heap_getattr would call HeapTupleGetRuleLock, which
- * uses the buffer's descriptor to get the relation id.
- * Rather than try to fix this, I'll just disallow
- * partial indexes on "lock", which wouldn't be useful
- * anyway. --Nels, Nov '92
- */
- /* SetSlotBuffer(slot, (Buffer) NULL); */
- /* SetSlotShouldFree(slot, false); */
- slot->ttc_buffer = (Buffer)NULL;
- slot->ttc_shouldFree = false;
-#endif /* OMIT_PARTIAL_INDEX */
- }
- } else {
- indexPred[i] = NULL;
- }
- }
- }
- }
-
- if (!binary)
- {
- in_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr));
- elements = (Oid *) palloc(attr_count * sizeof(Oid));
- for (i = 0; i < attr_count; i++)
- {
- in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
- fmgr_info(in_func_oid, &in_functions[i], &dummy);
- elements[i] = GetTypeElement(attr[i]->atttypid);
- }
- }
- else
- {
- in_functions = NULL;
- elements = NULL;
- fread(&ntuples, sizeof(int32), 1, fp);
- if (ntuples != 0) reading_to_eof = false;
- }
-
- values = (Datum *) palloc(sizeof(Datum) * attr_count);
- nulls = (char *) palloc(attr_count);
- index_nulls = (char *) palloc(attr_count);
- idatum = (Datum *) palloc(sizeof(Datum) * attr_count);
- byval = (bool *) palloc(attr_count * sizeof(bool));
-
- for (i = 0; i < attr_count; i++) {
- nulls[i] = ' ';
- index_nulls[i] = ' ';
- byval[i] = (bool) IsTypeByVal(attr[i]->atttypid);
- }
-
+ tupleTable = ExecCreateTupleTable(1);
+ slot = ExecAllocTableSlot(tupleTable);
+ econtext = makeNode(ExprContext);
+ econtext->ecxt_scantuple = slot;
+ rtupdesc = RelationGetTupleDescriptor(rel);
+ slot->ttc_tupleDescriptor = rtupdesc;
+
+ /*
+ * There's no buffer associated with heap tuples
+ * here, so I set the slot's buffer to NULL.
+ * Currently, it appears that the only way a
+ * buffer could be needed would be if the partial
+ * index predicate referred to the "lock" system
+ * attribute. If it did, then heap_getattr would
+ * call HeapTupleGetRuleLock, which uses the
+ * buffer's descriptor to get the relation id.
+ * Rather than try to fix this, I'll just disallow
+ * partial indexes on "lock", which wouldn't be
+ * useful anyway. --Nels, Nov '92
+ */
+ /* SetSlotBuffer(slot, (Buffer) NULL); */
+ /* SetSlotShouldFree(slot, false); */
+ slot->ttc_buffer = (Buffer) NULL;
+ slot->ttc_shouldFree = false;
+#endif /* OMIT_PARTIAL_INDEX */
+ }
+ }
+ else
+ {
+ indexPred[i] = NULL;
+ }
+ }
+ }
+ }
+
+ if (!binary)
+ {
+ in_functions = (func_ptr *) palloc(attr_count * sizeof(func_ptr));
+ elements = (Oid *) palloc(attr_count * sizeof(Oid));
+ for (i = 0; i < attr_count; i++)
+ {
+ in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
+ fmgr_info(in_func_oid, &in_functions[i], &dummy);
+ elements[i] = GetTypeElement(attr[i]->atttypid);
+ }
+ }
+ else
+ {
+ in_functions = NULL;
+ elements = NULL;
+ fread(&ntuples, sizeof(int32), 1, fp);
+ if (ntuples != 0)
+ reading_to_eof = false;
+ }
+
+ values = (Datum *) palloc(sizeof(Datum) * attr_count);
+ nulls = (char *) palloc(attr_count);
+ index_nulls = (char *) palloc(attr_count);
+ idatum = (Datum *) palloc(sizeof(Datum) * attr_count);
+ byval = (bool *) palloc(attr_count * sizeof(bool));
+
+ for (i = 0; i < attr_count; i++)
+ {
+ nulls[i] = ' ';
+ index_nulls[i] = ' ';
+ byval[i] = (bool) IsTypeByVal(attr[i]->atttypid);
+ }
+
#ifdef COPY_DEBUG
- lineno = 0;
+ lineno = 0;
#endif
- while (!done) {
- if (!binary) {
+ while (!done)
+ {
+ if (!binary)
+ {
#ifdef COPY_PATCH
- int newline = 0;
+ int newline = 0;
+
#endif
#ifdef COPY_DEBUG
- lineno++;
- elog(DEBUG, "line %d", lineno);
+ lineno++;
+ elog(DEBUG, "line %d", lineno);
#endif
- if (oids) {
+ if (oids)
+ {
#ifdef COPY_PATCH
- string = CopyReadAttribute(fp, &isnull, delim, &newline);
+ string = CopyReadAttribute(fp, &isnull, delim, &newline);
#else
- string = CopyReadAttribute(fp, &isnull, delim);
+ string = CopyReadAttribute(fp, &isnull, delim);
#endif
- if (string == NULL)
- done = 1;
- else {
- loaded_oid = oidin(string);
- if (loaded_oid < BootstrapObjectIdData)
- elog(WARN, "COPY TEXT: Invalid Oid");
- }
- }
- for (i = 0; i < attr_count && !done; i++) {
+ if (string == NULL)
+ done = 1;
+ else
+ {
+ loaded_oid = oidin(string);
+ if (loaded_oid < BootstrapObjectIdData)
+ elog(WARN, "COPY TEXT: Invalid Oid");
+ }
+ }
+ for (i = 0; i < attr_count && !done; i++)
+ {
#ifdef COPY_PATCH
- string = CopyReadAttribute(fp, &isnull, delim, &newline);
+ string = CopyReadAttribute(fp, &isnull, delim, &newline);
#else
- string = CopyReadAttribute(fp, &isnull, delim);
+ string = CopyReadAttribute(fp, &isnull, delim);
#endif
- if (isnull) {
- values[i] = PointerGetDatum(NULL);
- nulls[i] = 'n';
- }else if (string == NULL) {
- done = 1;
- }else {
- values[i] =
- (Datum)(in_functions[i])(string,
- elements[i],
- attr[i]->attlen);
- /*
- * Sanity check - by reference attributes cannot return
- * NULL
- */
- if (!PointerIsValid(values[i]) &&
- !(rel->rd_att->attrs[i]->attbyval)) {
+ if (isnull)
+ {
+ values[i] = PointerGetDatum(NULL);
+ nulls[i] = 'n';
+ }
+ else if (string == NULL)
+ {
+ done = 1;
+ }
+ else
+ {
+ values[i] =
+ (Datum) (in_functions[i]) (string,
+ elements[i],
+ attr[i]->attlen);
+
+ /*
+ * Sanity check - by reference attributes cannot
+ * return NULL
+ */
+ if (!PointerIsValid(values[i]) &&
+ !(rel->rd_att->attrs[i]->attbyval))
+ {
#ifdef COPY_DEBUG
- elog(WARN,
- "copy from: line %d - Bad file format", lineno);
+ elog(WARN,
+ "copy from: line %d - Bad file format", lineno);
#else
- elog(WARN, "copy from: Bad file format");
+ elog(WARN, "copy from: Bad file format");
#endif
- }
- }
- }
+ }
+ }
+ }
#ifdef COPY_PATCH
- if (!done) {
- CopyReadNewline(fp, &newline);
- }
+ if (!done)
+ {
+ CopyReadNewline(fp, &newline);
+ }
#endif
- }else { /* binary */
- fread(&len, sizeof(int32), 1, fp);
- if (feof(fp)) {
- done = 1;
- }else {
- if (oids) {
- fread(&loaded_oid, sizeof(int32), 1, fp);
- if (loaded_oid < BootstrapObjectIdData)
- elog(WARN, "COPY BINARY: Invalid Oid");
- }
- fread(&null_ct, sizeof(int32), 1, fp);
- if (null_ct > 0) {
- for (i = 0; i < null_ct; i++) {
- fread(&null_id, sizeof(int32), 1, fp);
- nulls[null_id] = 'n';
- }
- }
-
- string = (char *) palloc(len);
- fread(string, len, 1, fp);
-
- ptr = string;
-
- for (i = 0; i < attr_count; i++) {
- if (byval[i] && nulls[i] != 'n') {
-
- switch(attr[i]->attlen) {
- case sizeof(char):
- values[i] = (Datum) *(unsigned char *) ptr;
- ptr += sizeof(char);
- break;
- case sizeof(short):
- ptr = (char *) SHORTALIGN(ptr);
- values[i] = (Datum) *(unsigned short *) ptr;
- ptr += sizeof(short);
- break;
- case sizeof(int32):
- ptr = (char *) INTALIGN(ptr);
- values[i] = (Datum) *(uint32 *) ptr;
- ptr += sizeof(int32);
- break;
- default:
- elog(WARN, "COPY BINARY: impossible size!");
- break;
- }
- }else if (nulls[i] != 'n') {
- switch (attr[i]->attlen) {
- case -1:
- if (attr[i]->attalign == 'd')
- ptr = (char *)DOUBLEALIGN(ptr);
- else
- ptr = (char *)INTALIGN(ptr);
- values[i] = (Datum) ptr;
- ptr += * (uint32 *) ptr;
- break;
- case sizeof(char):
- values[i] = (Datum)ptr;
- ptr += attr[i]->attlen;
- break;
- case sizeof(short):
- ptr = (char*)SHORTALIGN(ptr);
- values[i] = (Datum)ptr;
- ptr += attr[i]->attlen;
- break;
- case sizeof(int32):
- ptr = (char*)INTALIGN(ptr);
- values[i] = (Datum)ptr;
- ptr += attr[i]->attlen;
- break;
- default:
- if (attr[i]->attalign == 'd')
- ptr = (char *)DOUBLEALIGN(ptr);
- else
- ptr = (char *)LONGALIGN(ptr);
- values[i] = (Datum) ptr;
- ptr += attr[i]->attlen;
- }
- }
- }
- }
- }
- if (done) continue;
+ }
+ else
+ { /* binary */
+ fread(&len, sizeof(int32), 1, fp);
+ if (feof(fp))
+ {
+ done = 1;
+ }
+ else
+ {
+ if (oids)
+ {
+ fread(&loaded_oid, sizeof(int32), 1, fp);
+ if (loaded_oid < BootstrapObjectIdData)
+ elog(WARN, "COPY BINARY: Invalid Oid");
+ }
+ fread(&null_ct, sizeof(int32), 1, fp);
+ if (null_ct > 0)
+ {
+ for (i = 0; i < null_ct; i++)
+ {
+ fread(&null_id, sizeof(int32), 1, fp);
+ nulls[null_id] = 'n';
+ }
+ }
- /*
- * Does it have any sence ? - vadim 12/14/96
- *
- tupDesc = CreateTupleDesc(attr_count, attr);
- */
- tuple = heap_formtuple(tupDesc, values, nulls);
- if (oids)
- tuple->t_oid = loaded_oid;
-
- skip_tuple = false;
- /* BEFORE ROW INSERT Triggers */
- if ( rel->trigdesc &&
- rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0 )
- {
- HeapTuple newtuple;
-
- newtuple = ExecBRInsertTriggers (rel, tuple);
-
- if ( newtuple == NULL ) /* "do nothing" */
- skip_tuple = true;
- else if ( newtuple != tuple ) /* modified by Trigger(s) */
- {
- pfree (tuple);
- tuple = newtuple;
- }
- }
-
- if ( !skip_tuple )
- {
- /* ----------------
- * Check the constraints of a tuple
- * ----------------
- */
-
- if ( rel->rd_att->constr )
- {
- HeapTuple newtuple;
-
- newtuple = ExecConstraints ("CopyFrom", rel, tuple);
-
- if ( newtuple != tuple )
- {
- pfree (tuple);
- tuple = newtuple;
- }
- }
-
- heap_insert(rel, tuple);
-
- if (has_index)
- {
- for (i = 0; i < n_indices; i++)
- {
- if (indexPred[i] != NULL)
- {
+ string = (char *) palloc(len);
+ fread(string, len, 1, fp);
+
+ ptr = string;
+
+ for (i = 0; i < attr_count; i++)
+ {
+ if (byval[i] && nulls[i] != 'n')
+ {
+
+ switch (attr[i]->attlen)
+ {
+ case sizeof(char):
+ values[i] = (Datum) * (unsigned char *) ptr;
+ ptr += sizeof(char);
+ break;
+ case sizeof(short):
+ ptr = (char *) SHORTALIGN(ptr);
+ values[i] = (Datum) * (unsigned short *) ptr;
+ ptr += sizeof(short);
+ break;
+ case sizeof(int32):
+ ptr = (char *) INTALIGN(ptr);
+ values[i] = (Datum) * (uint32 *) ptr;
+ ptr += sizeof(int32);
+ break;
+ default:
+ elog(WARN, "COPY BINARY: impossible size!");
+ break;
+ }
+ }
+ else if (nulls[i] != 'n')
+ {
+ switch (attr[i]->attlen)
+ {
+ case -1:
+ if (attr[i]->attalign == 'd')
+ ptr = (char *) DOUBLEALIGN(ptr);
+ else
+ ptr = (char *) INTALIGN(ptr);
+ values[i] = (Datum) ptr;
+ ptr += *(uint32 *) ptr;
+ break;
+ case sizeof(char):
+ values[i] = (Datum) ptr;
+ ptr += attr[i]->attlen;
+ break;
+ case sizeof(short):
+ ptr = (char *) SHORTALIGN(ptr);
+ values[i] = (Datum) ptr;
+ ptr += attr[i]->attlen;
+ break;
+ case sizeof(int32):
+ ptr = (char *) INTALIGN(ptr);
+ values[i] = (Datum) ptr;
+ ptr += attr[i]->attlen;
+ break;
+ default:
+ if (attr[i]->attalign == 'd')
+ ptr = (char *) DOUBLEALIGN(ptr);
+ else
+ ptr = (char *) LONGALIGN(ptr);
+ values[i] = (Datum) ptr;
+ ptr += attr[i]->attlen;
+ }
+ }
+ }
+ }
+ }
+ if (done)
+ continue;
+
+ /*
+ * Does it have any sence ? - vadim 12/14/96
+ *
+ * tupDesc = CreateTupleDesc(attr_count, attr);
+ */
+ tuple = heap_formtuple(tupDesc, values, nulls);
+ if (oids)
+ tuple->t_oid = loaded_oid;
+
+ skip_tuple = false;
+ /* BEFORE ROW INSERT Triggers */
+ if (rel->trigdesc &&
+ rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0)
+ {
+ HeapTuple newtuple;
+
+ newtuple = ExecBRInsertTriggers(rel, tuple);
+
+ if (newtuple == NULL) /* "do nothing" */
+ skip_tuple = true;
+ else if (newtuple != tuple) /* modified by Trigger(s) */
+ {
+ pfree(tuple);
+ tuple = newtuple;
+ }
+ }
+
+ if (!skip_tuple)
+ {
+ /* ----------------
+ * Check the constraints of a tuple
+ * ----------------
+ */
+
+ if (rel->rd_att->constr)
+ {
+ HeapTuple newtuple;
+
+ newtuple = ExecConstraints("CopyFrom", rel, tuple);
+
+ if (newtuple != tuple)
+ {
+ pfree(tuple);
+ tuple = newtuple;
+ }
+ }
+
+ heap_insert(rel, tuple);
+
+ if (has_index)
+ {
+ for (i = 0; i < n_indices; i++)
+ {
+ if (indexPred[i] != NULL)
+ {
#ifndef OMIT_PARTIAL_INDEX
- /*
- * if tuple doesn't satisfy predicate,
- * don't update index
- */
- slot->val = tuple;
- /*SetSlotContents(slot, tuple); */
- if (ExecQual((List*)indexPred[i], econtext) == false)
- continue;
-#endif /* OMIT_PARTIAL_INDEX */
- }
- FormIndexDatum(indexNatts[i],
- (AttrNumber *)&(pgIndexP[i]->indkey[0]),
- tuple,
- tupDesc,
- InvalidBuffer,
- idatum,
- index_nulls,
- finfoP[i]);
- indexRes = index_insert(index_rels[i], idatum, index_nulls,
- &(tuple->t_ctid), rel);
- if (indexRes) pfree(indexRes);
- }
- }
- /* AFTER ROW INSERT Triggers */
- if ( rel->trigdesc &&
- rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0 )
- ExecARInsertTriggers (rel, tuple);
- }
-
- if (binary) pfree(string);
-
- for (i = 0; i < attr_count; i++) {
- if (!byval[i] && nulls[i] != 'n') {
- if (!binary) pfree((void*)values[i]);
- }else if (nulls[i] == 'n') {
- nulls[i] = ' ';
- }
- }
-
- pfree(tuple);
- tuples_read++;
-
- if (!reading_to_eof && ntuples == tuples_read) done = true;
- }
- pfree(values);
- if (!binary) pfree(in_functions);
- pfree(nulls);
- pfree(byval);
- heap_close(rel);
+
+ /*
+ * if tuple doesn't satisfy predicate, don't
+ * update index
+ */
+ slot->val = tuple;
+ /* SetSlotContents(slot, tuple); */
+ if (ExecQual((List *) indexPred[i], econtext) == false)
+ continue;
+#endif /* OMIT_PARTIAL_INDEX */
+ }
+ FormIndexDatum(indexNatts[i],
+ (AttrNumber *) & (pgIndexP[i]->indkey[0]),
+ tuple,
+ tupDesc,
+ InvalidBuffer,
+ idatum,
+ index_nulls,
+ finfoP[i]);
+ indexRes = index_insert(index_rels[i], idatum, index_nulls,
+ &(tuple->t_ctid), rel);
+ if (indexRes)
+ pfree(indexRes);
+ }
+ }
+ /* AFTER ROW INSERT Triggers */
+ if (rel->trigdesc &&
+ rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
+ ExecARInsertTriggers(rel, tuple);
+ }
+
+ if (binary)
+ pfree(string);
+
+ for (i = 0; i < attr_count; i++)
+ {
+ if (!byval[i] && nulls[i] != 'n')
+ {
+ if (!binary)
+ pfree((void *) values[i]);
+ }
+ else if (nulls[i] == 'n')
+ {
+ nulls[i] = ' ';
+ }
+ }
+
+ pfree(tuple);
+ tuples_read++;
+
+ if (!reading_to_eof && ntuples == tuples_read)
+ done = true;
+ }
+ pfree(values);
+ if (!binary)
+ pfree(in_functions);
+ pfree(nulls);
+ pfree(byval);
+ heap_close(rel);
}
-static Oid
+static Oid
GetOutputFunction(Oid type)
{
- HeapTuple typeTuple;
-
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type),
- 0,0,0);
-
- if (HeapTupleIsValid(typeTuple))
- return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput);
-
- elog(WARN, "GetOutputFunction: Cache lookup of type %d failed", type);
- return(InvalidOid);
+ HeapTuple typeTuple;
+
+ typeTuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type),
+ 0, 0, 0);
+
+ if (HeapTupleIsValid(typeTuple))
+ return ((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput);
+
+ elog(WARN, "GetOutputFunction: Cache lookup of type %d failed", type);
+ return (InvalidOid);
}
-static Oid
+static Oid
GetTypeElement(Oid type)
{
- HeapTuple typeTuple;
-
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type),
- 0,0,0);
-
-
- if (HeapTupleIsValid(typeTuple))
- return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem);
-
- elog(WARN, "GetOutputFunction: Cache lookup of type %d failed", type);
- return(InvalidOid);
+ HeapTuple typeTuple;
+
+ typeTuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type),
+ 0, 0, 0);
+
+
+ if (HeapTupleIsValid(typeTuple))
+ return ((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem);
+
+ elog(WARN, "GetOutputFunction: Cache lookup of type %d failed", type);
+ return (InvalidOid);
}
-static Oid
+static Oid
GetInputFunction(Oid type)
{
- HeapTuple typeTuple;
-
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type),
- 0,0,0);
-
- if (HeapTupleIsValid(typeTuple))
- return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typinput);
-
- elog(WARN, "GetInputFunction: Cache lookup of type %d failed", type);
- return(InvalidOid);
+ HeapTuple typeTuple;
+
+ typeTuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type),
+ 0, 0, 0);
+
+ if (HeapTupleIsValid(typeTuple))
+ return ((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typinput);
+
+ elog(WARN, "GetInputFunction: Cache lookup of type %d failed", type);
+ return (InvalidOid);
}
-static Oid
+static Oid
IsTypeByVal(Oid type)
{
- HeapTuple typeTuple;
-
- typeTuple = SearchSysCacheTuple(TYPOID,
- ObjectIdGetDatum(type),
- 0,0,0);
-
- if (HeapTupleIsValid(typeTuple))
- return((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typbyval);
-
- elog(WARN, "GetInputFunction: Cache lookup of type %d failed", type);
-
- return(InvalidOid);
+ HeapTuple typeTuple;
+
+ typeTuple = SearchSysCacheTuple(TYPOID,
+ ObjectIdGetDatum(type),
+ 0, 0, 0);
+
+ if (HeapTupleIsValid(typeTuple))
+ return ((int) ((TypeTupleForm) GETSTRUCT(typeTuple))->typbyval);
+
+ elog(WARN, "GetInputFunction: Cache lookup of type %d failed", type);
+
+ return (InvalidOid);
}
-/*
+/*
* Given the OID of a relation, return an array of index relation descriptors
* and the number of index relations. These relation descriptors are open
* using heap_open().
@@ -779,71 +900,77 @@ IsTypeByVal(Oid type)
* Space for the array itself is palloc'ed.
*/
-typedef struct rel_list {
- Oid index_rel_oid;
- struct rel_list *next;
-} RelationList;
+typedef struct rel_list
+{
+ Oid index_rel_oid;
+ struct rel_list *next;
+} RelationList;
static void
GetIndexRelations(Oid main_relation_oid,
- int *n_indices,
- Relation **index_rels)
+ int *n_indices,
+ Relation ** index_rels)
{
- RelationList *head, *scan;
- Relation pg_index_rel;
- HeapScanDesc scandesc;
- Oid index_relation_oid;
- HeapTuple tuple;
- TupleDesc tupDesc;
- int i;
- bool isnull;
-
- pg_index_rel = heap_openr(IndexRelationName);
- scandesc = heap_beginscan(pg_index_rel, 0, NULL, 0, NULL);
- tupDesc = RelationGetTupleDescriptor(pg_index_rel);
-
- *n_indices = 0;
-
- head = (RelationList *) palloc(sizeof(RelationList));
- scan = head;
- head->next = NULL;
-
- for (tuple = heap_getnext(scandesc, 0, NULL);
- tuple != NULL;
- tuple = heap_getnext(scandesc, 0, NULL)) {
-
- index_relation_oid =
- (Oid) DatumGetInt32(heap_getattr(tuple, InvalidBuffer, 2,
- tupDesc, &isnull));
- if (index_relation_oid == main_relation_oid) {
- scan->index_rel_oid =
- (Oid) DatumGetInt32(heap_getattr(tuple, InvalidBuffer,
- Anum_pg_index_indexrelid,
- tupDesc, &isnull));
- (*n_indices)++;
- scan->next = (RelationList *) palloc(sizeof(RelationList));
- scan = scan->next;
- }
- }
-
- heap_endscan(scandesc);
- heap_close(pg_index_rel);
-
- /* We cannot trust to relhasindex of the main_relation now, so... */
- if ( *n_indices == 0 )
- return;
-
- *index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
-
- for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next) {
- (*index_rels)[i] = index_open(scan->index_rel_oid);
- }
-
- for (i = 0, scan = head; i < *n_indices + 1; i++) {
- scan = head->next;
- pfree(head);
- head = scan;
- }
+ RelationList *head,
+ *scan;
+ Relation pg_index_rel;
+ HeapScanDesc scandesc;
+ Oid index_relation_oid;
+ HeapTuple tuple;
+ TupleDesc tupDesc;
+ int i;
+ bool isnull;
+
+ pg_index_rel = heap_openr(IndexRelationName);
+ scandesc = heap_beginscan(pg_index_rel, 0, NULL, 0, NULL);
+ tupDesc = RelationGetTupleDescriptor(pg_index_rel);
+
+ *n_indices = 0;
+
+ head = (RelationList *) palloc(sizeof(RelationList));
+ scan = head;
+ head->next = NULL;
+
+ for (tuple = heap_getnext(scandesc, 0, NULL);
+ tuple != NULL;
+ tuple = heap_getnext(scandesc, 0, NULL))
+ {
+
+ index_relation_oid =
+ (Oid) DatumGetInt32(heap_getattr(tuple, InvalidBuffer, 2,
+ tupDesc, &isnull));
+ if (index_relation_oid == main_relation_oid)
+ {
+ scan->index_rel_oid =
+ (Oid) DatumGetInt32(heap_getattr(tuple, InvalidBuffer,
+ Anum_pg_index_indexrelid,
+ tupDesc, &isnull));
+ (*n_indices)++;
+ scan->next = (RelationList *) palloc(sizeof(RelationList));
+ scan = scan->next;
+ }
+ }
+
+ heap_endscan(scandesc);
+ heap_close(pg_index_rel);
+
+ /* We cannot trust to relhasindex of the main_relation now, so... */
+ if (*n_indices == 0)
+ return;
+
+ *index_rels = (Relation *) palloc(*n_indices * sizeof(Relation));
+
+ for (i = 0, scan = head; i < *n_indices; i++, scan = scan->next)
+ {
+ (*index_rels)[i] = index_open(scan->index_rel_oid);
+ }
+
+ for (i = 0, scan = head; i < *n_indices + 1; i++)
+ {
+ scan = head->next;
+ pfree(head);
+ head = scan;
+ }
}
#define EXT_ATTLEN 5*8192
@@ -851,20 +978,22 @@ GetIndexRelations(Oid main_relation_oid,
/*
returns 1 is c is in s
*/
-static bool
-inString(char c, char* s)
+static bool
+inString(char c, char *s)
{
- int i;
-
- if (s) {
- i = 0;
- while (s[i] != '\0') {
- if (s[i] == c)
- return 1;
- i++;
- }
- }
- return 0;
+ int i;
+
+ if (s)
+ {
+ i = 0;
+ while (s[i] != '\0')
+ {
+ if (s[i] == c)
+ return 1;
+ i++;
+ }
+ }
+ return 0;
}
#ifdef COPY_PATCH
@@ -873,19 +1002,21 @@ inString(char c, char* s)
*/
void
-CopyReadNewline(FILE *fp, int *newline)
+CopyReadNewline(FILE * fp, int *newline)
{
- if (!*newline) {
+ if (!*newline)
+ {
#ifdef COPY_DEBUG
- elog(NOTICE, "CopyReadNewline: line %d - extra fields ignored",
- lineno);
+ elog(NOTICE, "CopyReadNewline: line %d - extra fields ignored",
+ lineno);
#else
- elog(NOTICE, "CopyReadNewline: line - extra fields ignored");
+ elog(NOTICE, "CopyReadNewline: line - extra fields ignored");
#endif
- while (!feof(fp) && (getc(fp) != '\n'));
- }
- *newline = 0;
+ while (!feof(fp) && (getc(fp) != '\n'));
+ }
+ *newline = 0;
}
+
#endif
/*
@@ -895,148 +1026,167 @@ CopyReadNewline(FILE *fp, int *newline)
* can be used as standard input.
*/
-static char *
+static char *
#ifdef COPY_PATCH
-CopyReadAttribute(FILE *fp, bool *isnull, char *delim, int *newline)
+CopyReadAttribute(FILE * fp, bool * isnull, char *delim, int *newline)
#else
-CopyReadAttribute(FILE *fp, bool *isnull, char *delim)
+CopyReadAttribute(FILE * fp, bool * isnull, char *delim)
#endif
{
- static char attribute[EXT_ATTLEN];
- char c;
- int done = 0;
- int i = 0;
-
+ static char attribute[EXT_ATTLEN];
+ char c;
+ int done = 0;
+ int i = 0;
+
#ifdef COPY_PATCH
- /* if last delimiter was a newline return a NULL attribute */
- if (*newline) {
- *isnull = (bool) true;
- return(NULL);
- }
+ /* if last delimiter was a newline return a NULL attribute */
+ if (*newline)
+ {
+ *isnull = (bool) true;
+ return (NULL);
+ }
#endif
- *isnull = (bool) false; /* set default */
- if (feof(fp))
- return(NULL);
-
- while (!done) {
- c = getc(fp);
-
- if (feof(fp))
- return(NULL);
- else if (c == '\\') {
- c = getc(fp);
- if (feof(fp))
- return(NULL);
- switch (c) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': {
- int val;
- val = VALUE(c);
- c = getc(fp);
- if (ISOCTAL(c)) {
- val = (val<<3) + VALUE(c);
- c = getc(fp);
- if (ISOCTAL(c)) {
- val = (val<<3) + VALUE(c);
- } else {
- if (feof(fp))
- return(NULL);
- ungetc(c, fp);
- }
- } else {
- if (feof(fp))
- return(NULL);
- ungetc(c, fp);
- }
- c = val & 0377;
- }
- break;
- case 'b':
- c = '\b';
- break;
- case 'f':
- c = '\f';
- break;
- case 'n':
- c = '\n';
- break;
- case 'r':
- c = '\r';
- break;
- case 't':
- c = '\t';
- break;
- case 'v':
- c = '\v';
- break;
- case 'N':
- attribute[0] = '\0'; /* just to be safe */
- *isnull = (bool) true;
- break;
- case '.':
- c = getc(fp);
- if (c != '\n')
- elog(WARN, "CopyReadAttribute - end of record marker corrupted");
- return(NULL);
- break;
- }
- }else if (inString(c,delim) || c == '\n') {
+ *isnull = (bool) false; /* set default */
+ if (feof(fp))
+ return (NULL);
+
+ while (!done)
+ {
+ c = getc(fp);
+
+ if (feof(fp))
+ return (NULL);
+ else if (c == '\\')
+ {
+ c = getc(fp);
+ if (feof(fp))
+ return (NULL);
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ {
+ int val;
+
+ val = VALUE(c);
+ c = getc(fp);
+ if (ISOCTAL(c))
+ {
+ val = (val << 3) + VALUE(c);
+ c = getc(fp);
+ if (ISOCTAL(c))
+ {
+ val = (val << 3) + VALUE(c);
+ }
+ else
+ {
+ if (feof(fp))
+ return (NULL);
+ ungetc(c, fp);
+ }
+ }
+ else
+ {
+ if (feof(fp))
+ return (NULL);
+ ungetc(c, fp);
+ }
+ c = val & 0377;
+ }
+ break;
+ case 'b':
+ c = '\b';
+ break;
+ case 'f':
+ c = '\f';
+ break;
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case 't':
+ c = '\t';
+ break;
+ case 'v':
+ c = '\v';
+ break;
+ case 'N':
+ attribute[0] = '\0'; /* just to be safe */
+ *isnull = (bool) true;
+ break;
+ case '.':
+ c = getc(fp);
+ if (c != '\n')
+ elog(WARN, "CopyReadAttribute - end of record marker corrupted");
+ return (NULL);
+ break;
+ }
+ }
+ else if (inString(c, delim) || c == '\n')
+ {
#ifdef COPY_PATCH
- if (c == '\n') {
- *newline = 1;
- }
+ if (c == '\n')
+ {
+ *newline = 1;
+ }
#endif
- done = 1;
- }
- if (!done) attribute[i++] = c;
- if (i == EXT_ATTLEN - 1)
- elog(WARN, "CopyReadAttribute - attribute length too long");
- }
- attribute[i] = '\0';
- return(&attribute[0]);
+ done = 1;
+ }
+ if (!done)
+ attribute[i++] = c;
+ if (i == EXT_ATTLEN - 1)
+ elog(WARN, "CopyReadAttribute - attribute length too long");
+ }
+ attribute[i] = '\0';
+ return (&attribute[0]);
}
static void
-CopyAttributeOut(FILE *fp, char *string, char *delim)
+CopyAttributeOut(FILE * fp, char *string, char *delim)
{
- char c;
- int is_array = false;
- int len = strlen(string);
-
- /* XXX - This is a kludge, we should check the data type */
- if (len && (string[0] == '{') && (string[len-1] == '}'))
- is_array = true;
-
- for ( ; (c = *string) != '\0'; string++) {
- if (c == delim[0] || c == '\n' ||
- (c == '\\' && !is_array))
- fputc('\\', fp);
- else
- if (c == '\\' && is_array)
- if (*(string+1) == '\\') {
- /* translate \\ to \\\\ */
- fputc('\\', fp);
- fputc('\\', fp);
- fputc('\\', fp);
- string++;
- } else if (*(string+1) == '"') {
- /* translate \" to \\\" */
- fputc('\\', fp);
- fputc('\\', fp);
- }
- fputc(*string, fp);
- }
+ char c;
+ int is_array = false;
+ int len = strlen(string);
+
+ /* XXX - This is a kludge, we should check the data type */
+ if (len && (string[0] == '{') && (string[len - 1] == '}'))
+ is_array = true;
+
+ for (; (c = *string) != '\0'; string++)
+ {
+ if (c == delim[0] || c == '\n' ||
+ (c == '\\' && !is_array))
+ fputc('\\', fp);
+ else if (c == '\\' && is_array)
+ if (*(string + 1) == '\\')
+ {
+ /* translate \\ to \\\\ */
+ fputc('\\', fp);
+ fputc('\\', fp);
+ fputc('\\', fp);
+ string++;
+ }
+ else if (*(string + 1) == '"')
+ {
+ /* translate \" to \\\" */
+ fputc('\\', fp);
+ fputc('\\', fp);
+ }
+ fputc(*string, fp);
+ }
}
/*
- * Returns the number of tuples in a relation. Unfortunately, currently
+ * Returns the number of tuples in a relation. Unfortunately, currently
* must do a scan of the entire relation to determine this.
*
* relation is expected to be an open relation descriptor.
@@ -1044,17 +1194,17 @@ CopyAttributeOut(FILE *fp, char *string, char *delim)
static int
CountTuples(Relation relation)
{
- HeapScanDesc scandesc;
- HeapTuple tuple;
-
- int i;
-
- scandesc = heap_beginscan(relation, 0, NULL, 0, NULL);
-
- for (tuple = heap_getnext(scandesc, 0, NULL), i = 0;
- tuple != NULL;
- tuple = heap_getnext(scandesc, 0, NULL), i++)
- ;
- heap_endscan(scandesc);
- return(i);
+ HeapScanDesc scandesc;
+ HeapTuple tuple;
+
+ int i;
+
+ scandesc = heap_beginscan(relation, 0, NULL, 0, NULL);
+
+ for (tuple = heap_getnext(scandesc, 0, NULL), i = 0;
+ tuple != NULL;
+ tuple = heap_getnext(scandesc, 0, NULL), i++)
+ ;
+ heap_endscan(scandesc);
+ return (i);
}