📄 copy.c
字号:
{ int32 null_ct = 0, length; for (i = 0; i < attr_count; i++) { if (nulls[i] == 'n') null_ct++; } length = tuple->t_len - tuple->t_data->t_hoff; CopySendData(&length, sizeof(int32), fp); if (oids) CopySendData((char *) &tuple->t_data->t_oid, sizeof(int32), fp); CopySendData(&null_ct, sizeof(int32), fp); if (null_ct > 0) { for (i = 0; i < attr_count; i++) { if (nulls[i] == 'n') { CopySendData(&i, sizeof(int32), fp); nulls[i] = ' '; } } } CopySendData((char *) tuple->t_data + tuple->t_data->t_hoff, length, fp); } } heap_endscan(scandesc); if (binary) pfree(nulls); else { pfree(out_functions); pfree(elements); pfree(typmod); } heap_close(rel);}static voidCopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim){ HeapTuple tuple; AttrNumber attr_count; Form_pg_attribute *attr; FmgrInfo *in_functions; int i; 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; int32 *typmod; FuncIndexInfo *finfo, **finfoP = NULL; TupleDesc *itupdescArr; HeapTuple pgIndexTup; Form_pg_index *pgIndexP = NULL; int *indexNatts = NULL; char *predString; Node **indexPred = NULL; TupleDesc rtupdesc; ExprContext *econtext = NULL; EState *estate = makeNode(EState); /* for ExecConstraints() */#ifndef OMIT_PARTIAL_INDEX 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 = RelationGetDescr(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(RelationGetRelid(rel), &n_indices, &index_rels); if (n_indices > 0) { has_index = true; itupdescArr = (TupleDesc *) palloc(n_indices * sizeof(TupleDesc)); pgIndexP = (Form_pg_index *) palloc(n_indices * sizeof(Form_pg_index)); 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] = RelationGetDescr(index_rels[i]); pgIndexTup = SearchSysCacheTuple(INDEXRELID, ObjectIdGetDatum(RelationGetRelid(index_rels[i])), 0, 0, 0); Assert(pgIndexTup); pgIndexP[i] = (Form_pg_index) GETSTRUCT(pgIndexTup); for (attnumP = &(pgIndexP[i]->indkey[0]), natts = 0; natts < INDEX_MAX_KEYS && *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 = RelationGetDescr(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 = (FmgrInfo *) palloc(attr_count * sizeof(FmgrInfo)); elements = (Oid *) palloc(attr_count * sizeof(Oid)); typmod = (int32 *) palloc(attr_count * sizeof(int32)); for (i = 0; i < attr_count; i++) { in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid); fmgr_info(in_func_oid, &in_functions[i]); elements[i] = GetTypeElement(attr[i]->atttypid); typmod[i] = attr[i]->atttypmod; } } else { in_functions = NULL; elements = NULL; typmod = NULL; CopyGetData(&ntuples, sizeof(int32), 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); } lineno = 0; while (!done) { if (!binary) {#ifdef COPY_PATCH int newline = 0;#endif lineno++; if (oids) {#ifdef COPY_PATCH string = CopyReadAttribute(fp, &isnull, delim, &newline);#else string = CopyReadAttribute(fp, &isnull, delim);#endif if (string == NULL) done = 1; else { loaded_oid = oidin(string); if (loaded_oid < BootstrapObjectIdData) elog(ERROR, "COPY TEXT: Invalid Oid. line: %d", lineno); } } for (i = 0; i < attr_count && !done; i++) {#ifdef COPY_PATCH string = CopyReadAttribute(fp, &isnull, delim, &newline);#else 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) (*fmgr_faddr(&in_functions[i])) (string, elements[i], typmod[i]); /* * Sanity check - by reference attributes cannot * return NULL */ if (!PointerIsValid(values[i]) && !(rel->rd_att->attrs[i]->attbyval)) elog(ERROR, "copy from line %d: Bad file format", lineno); } }#ifdef COPY_PATCH if (!done) CopyReadNewline(fp, &newline);#endif } else { /* binary */ CopyGetData(&len, sizeof(int32), fp); if (CopyGetEof(fp)) done = 1; else { if (oids) { CopyGetData(&loaded_oid, sizeof(int32), fp); if (loaded_oid < BootstrapObjectIdData) elog(ERROR, "COPY BINARY: Invalid Oid line: %d", lineno); } CopyGetData(&null_ct, sizeof(int32), fp); if (null_ct > 0) { for (i = 0; i < null_ct; i++) { CopyGetData(&null_id, sizeof(int32), fp); nulls[null_id] = 'n'; } } string = (char *) palloc(len); CopyGetData(string, len, 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(ERROR, "COPY BINARY: impossible size! line: %d", lineno); break; } } else if (nulls[i] != 'n') { ptr = (char *) att_align(ptr, attr[i]->attlen, attr[i]->attalign); values[i] = (Datum) ptr; ptr = att_addlength(ptr, attr[i]->attlen, ptr); } } } } 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_data->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) ExecConstraints("CopyFrom", rel, tuple, estate); 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, idatum, index_nulls, finfoP[i]); indexRes = index_insert(index_rels[i], idatum, index_nulls, &(tuple->t_self), 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); pfree(nulls); pfree(index_nulls); pfree(idatum); pfree(byval); if (!binary) { pfree(in_functions);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -