📄 heap.c
字号:
/* ---------------- * create a scan key to locate the type tuple corresponding * to this relation. * ---------------- */ ScanKeyEntryInitialize(&key, 0, Anum_pg_type_typrelid, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(rel))); pg_type_scan = heap_beginscan(pg_type_desc, 0, SnapshotNow, 1, &key); /* ---------------- * use heap_getnext() to fetch the pg_type tuple. If this * tuple is not valid then something's wrong. * ---------------- */ tup = heap_getnext(pg_type_scan, 0); if (!HeapTupleIsValid(tup)) { heap_endscan(pg_type_scan); heap_close(pg_type_desc); elog(ERROR, "DeleteTypeTuple: %s type nonexistent", &rel->rd_rel->relname); } /* ---------------- * now scan pg_attribute. if any other relations have * attributes of the type of the relation we are deleteing * then we have to disallow the deletion. should talk to * stonebraker about this. -cim 6/19/90 * ---------------- */ typoid = tup->t_data->t_oid; pg_attribute_desc = heap_openr(AttributeRelationName); ScanKeyEntryInitialize(&attkey, 0, Anum_pg_attribute_atttypid, F_OIDEQ, typoid); pg_attribute_scan = heap_beginscan(pg_attribute_desc, 0, SnapshotNow, 1, &attkey); /* ---------------- * try and get a pg_attribute tuple. if we succeed it means * we can't delete the relation because something depends on * the schema. * ---------------- */ atttup = heap_getnext(pg_attribute_scan, 0); if (HeapTupleIsValid(atttup)) { Oid relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid; heap_endscan(pg_type_scan); heap_close(pg_type_desc); heap_endscan(pg_attribute_scan); heap_close(pg_attribute_desc); elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u", &rel->rd_rel->relname, relid); } heap_endscan(pg_attribute_scan); heap_close(pg_attribute_desc); /* ---------------- * Ok, it's safe so we delete the relation tuple * from pg_type and finish up. But first end the scan so that * we release the read lock on pg_type. -mer 13 Aug 1991 * ---------------- */ heap_delete(pg_type_desc, &tup->t_self, NULL); heap_endscan(pg_type_scan); heap_close(pg_type_desc);}/* -------------------------------- * heap_destroy_with_catalog * * -------------------------------- */voidheap_destroy_with_catalog(char *relname){ Relation rel; Oid rid; bool istemp = (get_temp_rel_by_name(relname) != NULL); /* ---------------- * first open the relation. if the relation does exist, * heap_openr() returns NULL. * ---------------- */ rel = heap_openr(relname); if (rel == NULL) elog(ERROR, "Relation '%s' does not exist", relname); LockRelation(rel, AccessExclusiveLock); rid = rel->rd_id; /* ---------------- * prevent deletion of system relations * ---------------- */ /* allow temp of pg_class? Guess so. */ if (!istemp && !allowSystemTableMods && IsSystemRelationName(RelationGetRelationName(rel)->data)) elog(ERROR, "System relation '%s' cannot be destroyed", &rel->rd_rel->relname); /* ---------------- * remove inheritance information * ---------------- */ RelationRemoveInheritance(rel); /* ---------------- * remove indexes if necessary * ---------------- */ if (rel->rd_rel->relhasindex) RelationRemoveIndexes(rel); /* ---------------- * remove rules if necessary * ---------------- */ if (rel->rd_rules != NULL) RelationRemoveRules(rid); /* triggers */ if (rel->rd_rel->reltriggers > 0) RelationRemoveTriggers(rel); /* ---------------- * delete attribute tuples * ---------------- */ DeleteAttributeTuples(rel); if (istemp) remove_temp_relation(rid); /* ---------------- * delete type tuple. here we want to see the effects * of the deletions we just did, so we use setheapoverride(). * ---------------- */ setheapoverride(true); DeleteTypeTuple(rel); setheapoverride(false); /* ---------------- * delete relation tuple * ---------------- */ /* must delete fake tuple in cache */ DeleteRelationTuple(rel); /* * release dirty buffers of this relation */ ReleaseRelationBuffers(rel); /* ---------------- * flush the relation from the relcache * ---------------- * Does nothing!!! Flushing moved below. - vadim 06/04/97 RelationIdInvalidateRelationCacheByRelationId(rel->rd_id); */ RemoveConstraints(rel); /* ---------------- * unlink the relation and finish up. * ---------------- */ if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked)) smgrunlink(DEFAULT_SMGR, rel); rel->rd_nonameunlinked = TRUE; UnlockRelation(rel, AccessExclusiveLock); heap_close(rel); RelationForgetRelation(rid);}/* * heap_destroy * destroy and close temporary relations * */voidheap_destroy(Relation rel){ ReleaseRelationBuffers(rel); if (!(rel->rd_isnoname) || !(rel->rd_nonameunlinked)) smgrunlink(DEFAULT_SMGR, rel); rel->rd_nonameunlinked = TRUE; heap_close(rel); RemoveFromNoNameRelList(rel);}/************************************************************** functions to deal with the list of temporary relations**************************************************************//* -------------- InitTempRellist(): initialize temporary relations list the tempRelList is a list of temporary relations that are created in the course of the transactions they need to be destroyed properly at the end of the transactions MODIFIES the global variable tempRels >> NOTE << malloc is used instead of palloc because we KNOW when we are going to free these things. Keeps us away from the memory context hairyness*/voidInitNoNameRelList(void){ if (tempRels) { free(tempRels->rels); free(tempRels); } tempRels = (TempRelList *) malloc(sizeof(TempRelList)); tempRels->size = NONAME_REL_LIST_SIZE; tempRels->rels = (Relation *) malloc(sizeof(Relation) * tempRels->size); MemSet(tempRels->rels, 0, sizeof(Relation) * tempRels->size); tempRels->num = 0;}/* removes a relation from the TempRelList MODIFIES the global variable tempRels we don't really remove it, just mark it as NULL and DestroyNoNameRels will look for NULLs*/static voidRemoveFromNoNameRelList(Relation r){ int i; if (!tempRels) return; for (i = 0; i < tempRels->num; i++) { if (tempRels->rels[i] == r) { tempRels->rels[i] = NULL; break; } }}/* add a temporary relation to the TempRelList MODIFIES the global variable tempRels*/static voidAddToNoNameRelList(Relation r){ if (!tempRels) return; if (tempRels->num == tempRels->size) { tempRels->size += NONAME_REL_LIST_SIZE; tempRels->rels = realloc(tempRels->rels, sizeof(Relation) * tempRels->size); } tempRels->rels[tempRels->num] = r; tempRels->num++;}/* go through the tempRels list and destroy each of the relations*/voidDestroyNoNameRels(void){ int i; Relation rel; if (!tempRels) return; for (i = 0; i < tempRels->num; i++) { rel = tempRels->rels[i]; /* rel may be NULL if it has been removed from the list already */ if (rel) heap_destroy(rel); } free(tempRels->rels); free(tempRels); tempRels = NULL;}static voidStoreAttrDefault(Relation rel, AttrDefault *attrdef){ char str[MAX_PARSE_BUFFER]; char cast[2 * NAMEDATALEN] = {0}; Form_pg_attribute atp = rel->rd_att->attrs[attrdef->adnum - 1]; List *queryTree_list; List *planTree_list; Query *query; TargetEntry *te; Resdom *resdom; Node *expr; Oid type; char *adbin; MemoryContext oldcxt; Relation adrel; Relation idescs[Num_pg_attrdef_indices]; HeapTuple tuple; Datum values[4]; char nulls[4] = {' ', ' ', ' ', ' '}; extern GlobalMemory CacheCxt;start: /* * Surround table name with double quotes to allow mixed-case and * whitespaces in names. - BGA 1998-11-14 */ snprintf(str, MAX_PARSE_BUFFER, "select %s%s from \"%.*s\"", attrdef->adsrc, cast, NAMEDATALEN, rel->rd_rel->relname.data); setheapoverride(true); planTree_list = pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE); setheapoverride(false); query = (Query *) lfirst(queryTree_list); if (length(query->rtable) > 1 || flatten_tlist(query->targetList) != NIL) elog(ERROR, "Cannot use attribute(s) in DEFAULT clause"); te = (TargetEntry *) lfirst(query->targetList); resdom = te->resdom; expr = te->expr; type = exprType(expr); if (type != atp->atttypid) { if (IS_BINARY_COMPATIBLE(type, atp->atttypid)) ; /* use without change */ else if (can_coerce_type(1, &(type), &(atp->atttypid))) expr = coerce_type(NULL, (Node *) expr, type, atp->atttypid, atp->atttypmod); else if (IsA(expr, Const)) { if (*cast != 0) elog(ERROR, "DEFAULT clause const type '%s' mismatched with column type '%s'", typeidTypeName(type), typeidTypeName(atp->atttypid)); snprintf(cast, 2 * NAMEDATALEN, ":: %s", typeidTypeName(atp->atttypid)); goto start; } else elog(ERROR, "DEFAULT clause type '%s' mismatched with column type '%s'", typeidTypeName(type), typeidTypeName(atp->atttypid)); } adbin = nodeToString(expr); oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); attrdef->adbin = pstrdup(adbin); (void) MemoryContextSwitchTo(oldcxt); pfree(adbin); values[Anum_pg_attrdef_adrelid - 1] = rel->rd_id; values[Anum_pg_attrdef_adnum - 1] = attrdef->adnum; values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(attrdef->adbin)); values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(attrdef->adsrc)); adrel = heap_openr(AttrDefaultRelationName); tuple = heap_formtuple(adrel->rd_att, values, nulls); CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices, idescs); heap_insert(adrel, tuple); CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple); CatalogCloseIndices(Num_pg_attrdef_indices, idescs); heap_close(adrel); pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1])); pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1])); pfree(tuple);}static voidStoreRelCheck(Relation rel, ConstrCheck *check){ char str[MAX_PARSE_BUFFER]; List *queryTree_list; List *planTree_list; Query *query; Plan *plan; List *qual; char *ccbin; MemoryContext oldcxt; Relation rcrel; Relation idescs[Num_pg_relcheck_indices]; HeapTuple tuple; Datum values[4]; char nulls[4] = {' ', ' ', ' ', ' '}; extern GlobalMemory CacheCxt; /* * Check for table's existance. Surround table name with double-quotes * to allow mixed-case and whitespace names. - thomas 1998-11-12 */ snprintf(str, MAX_PARSE_BUFFER, "select 1 from \"%.*s\" where %s", NAMEDATALEN, rel->rd_rel->relname.data, check->ccsrc); setheapoverride(true); planTree_list = pg_parse_and_plan(str, NULL, 0, &queryTree_list, None, FALSE); setheapoverride(false); query = (Query *) lfirst(queryTree_list); if (length(query->rtable) > 1) elog(ERROR, "Only relation '%.*s' can be referenced", NAMEDATALEN, rel->rd_rel->relname.data); plan = (Plan *) lfirst(planTree_list); qual = plan->qual; ccbin = nodeToString(qual); oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); check->ccbin = (char *) palloc(strlen(ccbin) + 1); strcpy(check->ccbin, ccbin); (void) MemoryContextSwitchTo(oldcxt); pfree(ccbin); values[Anum_pg_relcheck_rcrelid - 1] = rel->rd_id; values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(check->ccname)); values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(check->ccbin)); values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(check->ccsrc)); rcrel = heap_openr(RelCheckRelationName); tuple = heap_formtuple(rcrel->rd_att, values, nulls); CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices, idescs); heap_insert(rcrel, tuple); CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple); CatalogCloseIndices(Num_pg_relcheck_indices, idescs); heap_close(rcrel); pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1])); pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1])); pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1])); pfree(tuple); return;}static voidStoreConstraints(Relation rel){ TupleConstr *constr = rel->rd_att->constr; int i; if (!constr) return; if (constr->num_defval > 0) { for (i = 0; i < constr->num_defval; i++) StoreAttrDefault(rel, &(constr->defval[i])); } if (constr->num_check > 0) { for (i = 0; i < constr->num_check; i++) StoreRelCheck(rel, &(constr->check[i])); } return;}static voidRemoveAttrDefault(Relation rel){ Relation adrel; HeapScanDesc adscan; ScanKeyData key; HeapTuple tup; adrel = heap_openr(AttrDefaultRelationName); ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid, F_OIDEQ, rel->rd_id); LockRelation(adrel, AccessExclusiveLock); adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key); while (HeapTupleIsValid(tup = heap_getnext(adscan, 0))) heap_delete(adrel, &tup->t_self, NULL); heap_endscan(adscan); UnlockRelation(adrel, AccessExclusiveLock); heap_close(adrel);}static voidRemoveRelCheck(Relation rel){ Relation rcrel; HeapScanDesc rcscan; ScanKeyData key; HeapTuple tup; rcrel = heap_openr(RelCheckRelationName); ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid, F_OIDEQ, rel->rd_id); LockRelation(rcrel, AccessExclusiveLock); rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key); while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0))) heap_delete(rcrel, &tup->t_self, NULL); heap_endscan(rcscan); UnlockRelation(rcrel, AccessExclusiveLock); heap_close(rcrel);}static voidRemoveConstraints(Relation rel){ TupleConstr *constr = rel->rd_att->constr; if (!constr) return; if (constr->num_defval > 0) RemoveAttrDefault(rel); if (constr->num_check > 0) RemoveRelCheck(rel); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -