📄 tupdesc.c
字号:
* * attcacheoff must NOT be checked since it's possibly not set in both * copies. */ if (strcmp(NameStr(attr1->attname), NameStr(attr2->attname)) != 0) return false; if (attr1->atttypid != attr2->atttypid) return false; if (attr1->attstattarget != attr2->attstattarget) return false; if (attr1->attlen != attr2->attlen) return false; if (attr1->attndims != attr2->attndims) return false; if (attr1->atttypmod != attr2->atttypmod) return false; if (attr1->attbyval != attr2->attbyval) return false; if (attr1->attstorage != attr2->attstorage) return false; if (attr1->attalign != attr2->attalign) return false; if (attr1->attnotnull != attr2->attnotnull) return false; if (attr1->atthasdef != attr2->atthasdef) return false; if (attr1->attisdropped != attr2->attisdropped) return false; if (attr1->attislocal != attr2->attislocal) return false; if (attr1->attinhcount != attr2->attinhcount) return false; } if (tupdesc1->constr != NULL) { TupleConstr *constr1 = tupdesc1->constr; TupleConstr *constr2 = tupdesc2->constr; if (constr2 == NULL) return false; if (constr1->has_not_null != constr2->has_not_null) return false; n = constr1->num_defval; if (n != (int) constr2->num_defval) return false; for (i = 0; i < n; i++) { AttrDefault *defval1 = constr1->defval + i; AttrDefault *defval2 = constr2->defval; /* * We can't assume that the items are always read from the system * catalogs in the same order; so use the adnum field to identify * the matching item to compare. */ for (j = 0; j < n; defval2++, j++) { if (defval1->adnum == defval2->adnum) break; } if (j >= n) return false; if (strcmp(defval1->adbin, defval2->adbin) != 0) return false; } n = constr1->num_check; if (n != (int) constr2->num_check) return false; for (i = 0; i < n; i++) { ConstrCheck *check1 = constr1->check + i; ConstrCheck *check2 = constr2->check; /* * Similarly, don't assume that the checks are always read in the * same order; match them up by name and contents. (The name * *should* be unique, but...) */ for (j = 0; j < n; check2++, j++) { if (strcmp(check1->ccname, check2->ccname) == 0 && strcmp(check1->ccbin, check2->ccbin) == 0) break; } if (j >= n) return false; } } else if (tupdesc2->constr != NULL) return false; return true;}/* * TupleDescInitEntry * This function initializes a single attribute structure in * a previously allocated tuple descriptor. */voidTupleDescInitEntry(TupleDesc desc, AttrNumber attributeNumber, const char *attributeName, Oid oidtypeid, int32 typmod, int attdim){ HeapTuple tuple; Form_pg_type typeForm; Form_pg_attribute att; /* * sanity checks */ AssertArg(PointerIsValid(desc)); AssertArg(attributeNumber >= 1); AssertArg(attributeNumber <= desc->natts); /* * initialize the attribute fields */ att = desc->attrs[attributeNumber - 1]; att->attrelid = 0; /* dummy value */ /* * Note: attributeName can be NULL, because the planner doesn't always * fill in valid resname values in targetlists, particularly for resjunk * attributes. */ if (attributeName != NULL) namestrcpy(&(att->attname), attributeName); else MemSet(NameStr(att->attname), 0, NAMEDATALEN); att->attstattarget = -1; att->attcacheoff = -1; att->atttypmod = typmod; att->attnum = attributeNumber; att->attndims = attdim; att->attnotnull = false; att->atthasdef = false; att->attisdropped = false; att->attislocal = true; att->attinhcount = 0; tuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(oidtypeid), 0, 0, 0); if (!HeapTupleIsValid(tuple)) elog(ERROR, "cache lookup failed for type %u", oidtypeid); typeForm = (Form_pg_type) GETSTRUCT(tuple); att->atttypid = oidtypeid; att->attlen = typeForm->typlen; att->attbyval = typeForm->typbyval; att->attalign = typeForm->typalign; att->attstorage = typeForm->typstorage; ReleaseSysCache(tuple);}/* * BuildDescForRelation * * Given a relation schema (list of ColumnDef nodes), build a TupleDesc. * * Note: the default assumption is no OIDs; caller may modify the returned * TupleDesc if it wants OIDs. Also, tdtypeid will need to be filled in * later on. */TupleDescBuildDescForRelation(List *schema){ int natts; AttrNumber attnum; ListCell *l; TupleDesc desc; AttrDefault *attrdef = NULL; TupleConstr *constr = (TupleConstr *) palloc0(sizeof(TupleConstr)); char *attname; Oid atttypid; int32 atttypmod; int attdim; int ndef = 0; /* * allocate a new tuple descriptor */ natts = list_length(schema); desc = CreateTemplateTupleDesc(natts, false); constr->has_not_null = false; attnum = 0; foreach(l, schema) { ColumnDef *entry = lfirst(l); /* * for each entry in the list, get the name and type information from * the list and have TupleDescInitEntry fill in the attribute * information we need. */ attnum++; attname = entry->colname; atttypid = typenameTypeId(NULL, entry->typename, &atttypmod); attdim = list_length(entry->typename->arrayBounds); if (entry->typename->setof) ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), errmsg("column \"%s\" cannot be declared SETOF", attname))); TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, attdim); /* Fill in additional stuff not handled by TupleDescInitEntry */ if (entry->is_not_null) constr->has_not_null = true; desc->attrs[attnum - 1]->attnotnull = entry->is_not_null; /* * Note we copy only pre-cooked default expressions. Digestion of raw * ones is someone else's problem. */ if (entry->cooked_default != NULL) { if (attrdef == NULL) attrdef = (AttrDefault *) palloc(natts * sizeof(AttrDefault)); attrdef[ndef].adnum = attnum; attrdef[ndef].adbin = pstrdup(entry->cooked_default); ndef++; desc->attrs[attnum - 1]->atthasdef = true; } desc->attrs[attnum - 1]->attislocal = entry->is_local; desc->attrs[attnum - 1]->attinhcount = entry->inhcount; } if (constr->has_not_null || ndef > 0) { desc->constr = constr; if (ndef > 0) /* DEFAULTs */ { if (ndef < natts) constr->defval = (AttrDefault *) repalloc(attrdef, ndef * sizeof(AttrDefault)); else constr->defval = attrdef; constr->num_defval = ndef; } else { constr->defval = NULL; constr->num_defval = 0; } constr->check = NULL; constr->num_check = 0; } else { pfree(constr); desc->constr = NULL; } return desc;}/* * BuildDescFromLists * * Build a TupleDesc given lists of column names (as String nodes), * column type OIDs, and column typmods. No constraints are generated. * * This is essentially a cut-down version of BuildDescForRelation for use * with functions returning RECORD. */TupleDescBuildDescFromLists(List *names, List *types, List *typmods){ int natts; AttrNumber attnum; ListCell *l1; ListCell *l2; ListCell *l3; TupleDesc desc; natts = list_length(names); Assert(natts == list_length(types)); Assert(natts == list_length(typmods)); /* * allocate a new tuple descriptor */ desc = CreateTemplateTupleDesc(natts, false); attnum = 0; l2 = list_head(types); l3 = list_head(typmods); foreach(l1, names) { char *attname = strVal(lfirst(l1)); Oid atttypid; int32 atttypmod; atttypid = lfirst_oid(l2); l2 = lnext(l2); atttypmod = lfirst_int(l3); l3 = lnext(l3); attnum++; TupleDescInitEntry(desc, attnum, attname, atttypid, atttypmod, 0); } return desc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -