⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tupdesc.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 2 页
字号:
TupleDescInitEntry(TupleDesc desc,				   AttrNumber attributeNumber,				   const char *attributeName,				   Oid oidtypeid,				   int32 typmod,				   int attdim,				   bool attisset){	HeapTuple	tuple;	Form_pg_type typeForm;	Form_pg_attribute att;	/*	 * sanity checks	 */	AssertArg(PointerIsValid(desc));	AssertArg(attributeNumber >= 1);	AssertArg(attributeNumber <= desc->natts);	AssertArg(!PointerIsValid(desc->attrs[attributeNumber - 1]));	/*	 * allocate storage for this attribute	 */	att = (Form_pg_attribute) palloc(ATTRIBUTE_TUPLE_SIZE);	desc->attrs[attributeNumber - 1] = att;	/*	 * initialize the attribute fields	 */	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->attisset = attisset;	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);	/*	 * type info exists so we initialize our attribute information from	 * the type tuple we found..	 */	typeForm = (Form_pg_type) GETSTRUCT(tuple);	att->atttypid = HeapTupleGetOid(tuple);	/*	 * There are a couple of cases where we must override the information	 * stored in pg_type.	 *	 * First: if this attribute is a set, what is really stored in the	 * attribute is the OID of a tuple in the pg_proc catalog. The pg_proc	 * tuple contains the query string which defines this set - i.e., the	 * query to run to get the set. So the atttypid (just assigned above)	 * refers to the type returned by this query, but the actual length of	 * this attribute is the length (size) of an OID.	 *	 * (Why not just make the atttypid point to the OID type, instead of the	 * type the query returns?	Because the executor uses the atttypid to	 * tell the front end what type will be returned, and in the end the	 * type returned will be the result of the query, not an OID.)	 *	 * (Why not wait until the return type of the set is known (i.e., the	 * recursive call to the executor to execute the set has returned)	 * before telling the front end what the return type will be?  Because	 * the executor is a delicate thing, and making sure that the correct	 * order of front-end commands is maintained is messy, especially	 * considering that target lists may change as inherited attributes	 * are considered, etc.  Ugh.)	 *	 * Second: if we are dealing with a complex type (a tuple type), then	 * pg_type will say that the representation is the same as Oid.  But	 * if typmod is sizeof(Pointer) then the internal representation is	 * actually a pointer to a TupleTableSlot, and we have to substitute	 * that information.	 *	 * A set of complex type is first and foremost a set, so its	 * representation is Oid not pointer.  So, test that case first.	 */	if (attisset)	{		att->attlen = sizeof(Oid);		att->attbyval = true;		att->attalign = 'i';		att->attstorage = 'p';	}	else if (typeForm->typtype == 'c' && typmod == sizeof(Pointer))	{		att->attlen = sizeof(Pointer);		att->attbyval = true;		att->attalign = 'd';	/* kluge to work with 8-byte pointers */		/* XXX ought to have a separate attalign value for pointers ... */		att->attstorage = 'p';	}	else	{		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. */TupleDescBuildDescForRelation(List *schema){	int			natts;	AttrNumber	attnum;	List	   *p;	TupleDesc	desc;	AttrDefault *attrdef = NULL;	TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr));	char	   *attname;	int32		atttypmod;	int			attdim;	int			ndef = 0;	bool		attisset;	/*	 * allocate a new tuple descriptor	 */	natts = length(schema);	desc = CreateTemplateTupleDesc(natts, false);	constr->has_not_null = false;	attnum = 0;	foreach(p, schema)	{		ColumnDef  *entry = lfirst(p);		/*		 * 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;		attisset = entry->typename->setof;		atttypmod = entry->typename->typmod;		attdim = length(entry->typename->arrayBounds);		TupleDescInitEntry(desc, attnum, attname,						   typenameTypeId(entry->typename),						   atttypmod, attdim, attisset);		/* 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;}/* * RelationNameGetTupleDesc * * Given a (possibly qualified) relation name, build a TupleDesc. */TupleDescRelationNameGetTupleDesc(const char *relname){	RangeVar   *relvar;	Relation	rel;	TupleDesc	tupdesc;	List	   *relname_list;	/* Open relation and get the tuple description */	relname_list = stringToQualifiedNameList(relname, "RelationNameGetTupleDesc");	relvar = makeRangeVarFromNameList(relname_list);	rel = relation_openrv(relvar, AccessShareLock);	tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));	relation_close(rel, AccessShareLock);	return tupdesc;}/* * TypeGetTupleDesc * * Given a type Oid, build a TupleDesc. * * If the type is composite, *and* a colaliases List is provided, *and* * the List is of natts length, use the aliases instead of the relation * attnames. * * If the type is a base type, a single item alias List is required. */TupleDescTypeGetTupleDesc(Oid typeoid, List *colaliases){	char		functyptype = get_typtype(typeoid);	TupleDesc	tupdesc = NULL;	/*	 * Build a suitable tupledesc representing the output rows	 */	if (functyptype == 'c')	{		/* Composite data type, i.e. a table's row type */		Oid			relid = typeidTypeRelid(typeoid);		Relation	rel;		int			natts;		if (!OidIsValid(relid))			elog(ERROR, "invalid typrelid for complex type %u", typeoid);		rel = relation_open(relid, AccessShareLock);		tupdesc = CreateTupleDescCopy(RelationGetDescr(rel));		natts = tupdesc->natts;		relation_close(rel, AccessShareLock);		/* XXX should we hold the lock to ensure table doesn't change? */		if (colaliases != NIL)		{			int			varattno;			/* does the list length match the number of attributes? */			if (length(colaliases) != natts)				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),						 errmsg("number of aliases does not match number of columns")));			/* OK, use the aliases instead */			for (varattno = 0; varattno < natts; varattno++)			{				char	   *label = strVal(nth(varattno, colaliases));				if (label != NULL)					namestrcpy(&(tupdesc->attrs[varattno]->attname), label);			}		}	}	else if (functyptype == 'b' || functyptype == 'd')	{		/* Must be a base data type, i.e. scalar */		char	   *attname;		/* the alias list is required for base types */		if (colaliases == NIL)			ereport(ERROR,					(errcode(ERRCODE_DATATYPE_MISMATCH),					 errmsg("no column alias was provided")));		/* the alias list length must be 1 */		if (length(colaliases) != 1)			ereport(ERROR,					(errcode(ERRCODE_DATATYPE_MISMATCH),					 errmsg("number of aliases does not match number of columns")));		/* OK, get the column alias */		attname = strVal(lfirst(colaliases));		tupdesc = CreateTemplateTupleDesc(1, false);		TupleDescInitEntry(tupdesc,						   (AttrNumber) 1,						   attname,						   typeoid,						   -1,						   0,						   false);	}	else if (functyptype == 'p' && typeoid == RECORDOID)		ereport(ERROR,				(errcode(ERRCODE_DATATYPE_MISMATCH),				 errmsg("could not determine row description for function returning record")));	else	{		/* crummy error message, but parser should have caught this */		elog(ERROR, "function in FROM has unsupported return type");	}	return tupdesc;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -