📄 relcache.c
字号:
/* ---------------- * end the scan and close the attribute relation * ---------------- */ heap_endscan(pg_attribute_scan); heap_close(pg_attribute_desc);}static voidbuild_tupdesc_ind(RelationBuildDescInfo buildinfo, Relation relation, u_int natts){ Relation attrel; HeapTuple atttup; Form_pg_attribute attp; TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); AttrDefault *attrdef = NULL; int ndef = 0; int i; constr->has_not_null = false; attrel = heap_openr(AttributeRelationName); for (i = 1; i <= relation->rd_rel->relnatts; i++) { atttup = (HeapTuple) AttributeNumIndexScan(attrel, RelationGetRelid(relation), i); if (!HeapTupleIsValid(atttup)) elog(ERROR, "cannot find attribute %d of relation %s", i, relation->rd_rel->relname.data); attp = (Form_pg_attribute) GETSTRUCT(atttup); relation->rd_att->attrs[i - 1] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); memmove((char *) (relation->rd_att->attrs[i - 1]), (char *) attp, ATTRIBUTE_TUPLE_SIZE); /* Update if this attribute have a constraint */ if (attp->attnotnull) constr->has_not_null = true; if (attp->atthasdef) { if (attrdef == NULL) attrdef = (AttrDefault *) palloc(relation->rd_rel->relnatts * sizeof(AttrDefault)); attrdef[ndef].adnum = i; attrdef[ndef].adbin = NULL; attrdef[ndef].adsrc = NULL; ndef++; } } heap_close(attrel); if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks) { relation->rd_att->constr = constr; if (ndef > 0) /* DEFAULTs */ { if (ndef < relation->rd_rel->relnatts) constr->defval = (AttrDefault *) repalloc(attrdef, ndef * sizeof(AttrDefault)); else constr->defval = attrdef; constr->num_defval = ndef; AttrDefaultFetch(relation); } else constr->num_defval = 0; if (relation->rd_rel->relchecks > 0) /* CHECKs */ { constr->num_check = relation->rd_rel->relchecks; constr->check = (ConstrCheck *) palloc(constr->num_check * sizeof(ConstrCheck)); MemSet(constr->check, 0, constr->num_check * sizeof(ConstrCheck)); RelCheckFetch(relation); } else constr->num_check = 0; } else { pfree(constr); relation->rd_att->constr = NULL; }}/* -------------------------------- * RelationBuildRuleLock * * Form the relation's rewrite rules from information in * the pg_rewrite system catalog. * -------------------------------- */static voidRelationBuildRuleLock(Relation relation){ HeapTuple pg_rewrite_tuple; Relation pg_rewrite_desc; TupleDesc pg_rewrite_tupdesc; HeapScanDesc pg_rewrite_scan; ScanKeyData key; RuleLock *rulelock; int numlocks; RewriteRule **rules; int maxlocks; /* ---------------- * form an array to hold the rewrite rules (the array is extended if * necessary) * ---------------- */ maxlocks = 4; rules = (RewriteRule **) palloc(sizeof(RewriteRule *) * maxlocks); numlocks = 0; /* ---------------- * form a scan key * ---------------- */ ScanKeyEntryInitialize(&key, 0, Anum_pg_rewrite_ev_class, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); /* ---------------- * open pg_attribute and begin a scan * ---------------- */ pg_rewrite_desc = heap_openr(RewriteRelationName); pg_rewrite_scan = heap_beginscan(pg_rewrite_desc, 0, SnapshotNow, 1, &key); pg_rewrite_tupdesc = RelationGetDescr(pg_rewrite_desc); /* ---------------- * add attribute data to relation->rd_att * ---------------- */ while (HeapTupleIsValid(pg_rewrite_tuple = heap_getnext(pg_rewrite_scan, 0))) { bool isnull; Datum ruleaction; Datum rule_evqual_string; RewriteRule *rule; rule = (RewriteRule *) palloc(sizeof(RewriteRule)); rule->ruleId = pg_rewrite_tuple->t_data->t_oid; rule->event = (int) heap_getattr(pg_rewrite_tuple, Anum_pg_rewrite_ev_type, pg_rewrite_tupdesc, &isnull) - 48; rule->attrno = (int) heap_getattr(pg_rewrite_tuple, Anum_pg_rewrite_ev_attr, pg_rewrite_tupdesc, &isnull); rule->isInstead = !!heap_getattr(pg_rewrite_tuple, Anum_pg_rewrite_is_instead, pg_rewrite_tupdesc, &isnull); ruleaction = heap_getattr(pg_rewrite_tuple, Anum_pg_rewrite_ev_action, pg_rewrite_tupdesc, &isnull); rule_evqual_string = heap_getattr(pg_rewrite_tuple, Anum_pg_rewrite_ev_qual, pg_rewrite_tupdesc, &isnull); ruleaction = PointerGetDatum(textout((struct varlena *) DatumGetPointer(ruleaction))); rule_evqual_string = PointerGetDatum(textout((struct varlena *) DatumGetPointer(rule_evqual_string))); rule->actions = (List *) stringToNode(DatumGetPointer(ruleaction)); rule->qual = (Node *) stringToNode(DatumGetPointer(rule_evqual_string)); rules[numlocks++] = rule; if (numlocks == maxlocks) { maxlocks *= 2; rules = (RewriteRule **) repalloc(rules, sizeof(RewriteRule *) * maxlocks); } } /* ---------------- * end the scan and close the attribute relation * ---------------- */ heap_endscan(pg_rewrite_scan); heap_close(pg_rewrite_desc); /* ---------------- * form a RuleLock and insert into relation * ---------------- */ rulelock = (RuleLock *) palloc(sizeof(RuleLock)); rulelock->numLocks = numlocks; rulelock->rules = rules; relation->rd_rules = rulelock; return;}/* -------------------------------- * RelationBuildDesc * * To build a relation descriptor, we have to allocate space, * open the underlying unix file and initialize the following * fields: * * File rd_fd; open file descriptor * int rd_nblocks; number of blocks in rel * it will be set in ambeginscan() * uint16 rd_refcnt; reference count * Form_pg_am rd_am; AM tuple * Form_pg_class rd_rel; RELATION tuple * Oid rd_id; relations's object id * Pointer lockInfo; ptr. to misc. info. * TupleDesc rd_att; tuple desciptor * * Note: rd_ismem (rel is in-memory only) is currently unused * by any part of the system. someday this will indicate that * the relation lives only in the main-memory buffer pool * -cim 2/4/91 * -------------------------------- */static RelationRelationBuildDesc(RelationBuildDescInfo buildinfo){ File fd; Relation relation; u_int natts; Oid relid; Oid relam; Form_pg_class relp; MemoryContext oldcxt; HeapTuple pg_class_tuple; oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); /* ---------------- * find the tuple in pg_class corresponding to the given relation id * ---------------- */ pg_class_tuple = ScanPgRelation(buildinfo); /* ---------------- * if no such tuple exists, return NULL * ---------------- */ if (!HeapTupleIsValid(pg_class_tuple)) { MemoryContextSwitchTo(oldcxt); return NULL; } /* ---------------- * get information from the pg_class_tuple * ---------------- */ relid = pg_class_tuple->t_data->t_oid; relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); natts = relp->relnatts; /* ---------------- * allocate storage for the relation descriptor, * initialize relation->rd_rel and get the access method id. * ---------------- */ relation = AllocateRelationDesc(natts, relp); relam = relation->rd_rel->relam; /* ---------------- * initialize the relation's relation id (relation->rd_id) * ---------------- */ RelationGetRelid(relation) = relid; /* ---------------- * initialize relation->rd_refcnt * ---------------- */ RelationSetReferenceCount(relation, 1); /* ---------------- * normal relations are not nailed into the cache * ---------------- */ relation->rd_isnailed = false; /* ---------------- * initialize the access method information (relation->rd_am) * ---------------- */ if (OidIsValid(relam)) relation->rd_am = (Form_pg_am) AccessMethodObjectIdGetForm(relam); /* ---------------- * initialize the tuple descriptor (relation->rd_att). * remember, rd_att is an array of attribute pointers that lives * off the end of the relation descriptor structure so space was * already allocated for it by AllocateRelationDesc. * ---------------- */ RelationBuildTupleDesc(buildinfo, relation, natts); /* ---------------- * initialize rules that affect this relation * ---------------- */ if (relp->relhasrules) RelationBuildRuleLock(relation); else relation->rd_rules = NULL; /* Triggers */ if (relp->reltriggers > 0) RelationBuildTriggers(relation); else relation->trigdesc = NULL; /* ---------------- * initialize index strategy and support information for this relation * ---------------- */ if (OidIsValid(relam)) IndexedAccessMethodInitialize(relation); /* ---------------- * initialize the relation lock manager information * ---------------- */ RelationInitLockInfo(relation); /* see lmgr.c */ /* ---------------- * open the relation and assign the file descriptor returned * by the storage manager code to rd_fd. * ---------------- */ fd = smgropen(DEFAULT_SMGR, relation); Assert(fd >= -1); if (fd == -1) elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m", &relp->relname); relation->rd_fd = fd; /* ---------------- * insert newly created relation into proper relcaches, * restore memory context and return the new reldesc. * ---------------- */ RelationCacheInsert(relation); /* ------------------- * free the memory allocated for pg_class_tuple * and for lock data pointed to by pg_class_tuple * ------------------- */ pfree(pg_class_tuple); MemoryContextSwitchTo(oldcxt); return relation;}static voidIndexedAccessMethodInitialize(Relation relation){ IndexStrategy strategy; RegProcedure *support; int natts; Size stratSize; Size supportSize; uint16 relamstrategies; uint16 relamsupport; natts = relation->rd_rel->relnatts; relamstrategies = relation->rd_am->amstrategies; stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies); strategy = (IndexStrategy) palloc(stratSize); relamsupport = relation->rd_am->amsupport; if (relamsupport > 0) { supportSize = natts * (relamsupport * sizeof(RegProcedure)); support = (RegProcedure *) palloc(supportSize); } else support = (RegProcedure *) NULL; IndexSupportInitialize(strategy, support, relation->rd_att->attrs[0]->attrelid, relation->rd_rel->relam, relamstrategies, relamsupport, natts); RelationSetIndexSupport(relation, strategy, support);}/* -------------------------------- * formrdesc * * This is a special version of RelationBuildDesc() * used by RelationInitialize() in initializing the * relcache. The system relation descriptors built * here are all nailed in the descriptor caches, for * bootstrapping. * -------------------------------- */static voidformrdesc(char *relationName, u_int natts, FormData_pg_attribute *att){ Relation relation; Size len; int i; /* ---------------- * allocate new relation desc * ---------------- */ len = sizeof(RelationData); relation = (Relation) palloc(len); MemSet((char *) relation, 0, len); /* ---------------- * don't open the unix file yet.. * ---------------- */ relation->rd_fd = -1; /* ---------------- * initialize reference count * ---------------- */ RelationSetReferenceCount(relation, 1); /* ---------------- * initialize relation tuple form * ---------------- */ relation->rd_rel = (Form_pg_class) palloc((Size) (sizeof(*relation->rd_rel))); MemSet(relation->rd_rel, 0, sizeof(FormData_pg_class)); namestrcpy(&relation->rd_rel->relname, relationName); /* ---------------- initialize attribute tuple form */ relation->rd_att = CreateTemplateTupleDesc(natts); /* * For debugging purposes, it's important to distinguish between * shared and non-shared relations, even at bootstrap time. There's * code in the buffer manager that traces allocations that has to know * about this. */ if (IsSystemRelationName(relationName)) { relation->rd_rel->relowner = 6; /* XXX use sym const */ relation->rd_rel->relisshared = IsSharedSystemRelationName(relationName); } else { relation->rd_rel->relowner = 0; relation->rd_rel->relisshared = false; } relation->rd_rel->relpages = 1; /* XXX */ relation->rd_rel->reltuples = 1; /* XXX */ relation->rd_rel->relkind = RELKIND_RELATION; relation->rd_rel->relnatts = (uint16) natts; relation->rd_isnailed = true; /* ---------------- * initialize tuple desc info * ---------------- */ for (i = 0; i < natts; i++) { relation->rd_att->attrs[i] = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE); MemSet((char *) relation->rd_att->attrs[i], 0, ATTRIBUTE_TUPLE_SIZE); memmove((char *) relation->rd_att->attrs[i], (char *) &att[i], ATTRIBUTE_TUPLE_SIZE); } /* ---------------- * initialize relation id * ---------------- */ RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid; /* ---------------- * add new reldesc to relcache * ---------------- */ RelationCacheInsert(relation); RelationInitLockInfo(relation); /* * Determining this requires a scan on pg_class, but to do the scan * the rdesc for pg_class must already exist. Therefore we must do * the check (and possible set) after cache insertion. */ relation->rd_rel->relhasindex = CatalogHasIndex(relationName, RelationGetRelid(relation));}/* ---------------------------------------------------------------- * Relation Descriptor Lookup Interface * ---------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -