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

📄 parse_target.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
 * needed. * * targetName is the name of the field or subfield we're assigning to, and * targetIsArray is true if we're subscripting it.  These are just for * error reporting. * * targetTypeId and targetTypMod indicate the datatype of the object to * be assigned to (initially the target column, later some subobject). * * indirection is the sublist remaining to process.  When it's NULL, we're * done recursing and can just coerce and return the RHS. * * rhs is the already-transformed value to be assigned; note it has not been * coerced to any particular type. */static Node *transformAssignmentIndirection(ParseState *pstate,							   Node *basenode,							   const char *targetName,							   bool targetIsArray,							   Oid targetTypeId,							   int32 targetTypMod,							   ListCell *indirection,							   Node *rhs){	Node	   *result;	List	   *subscripts = NIL;	bool		isSlice = false;	ListCell   *i;	if (indirection && !basenode)	{		/* Set up a substitution.  We reuse CaseTestExpr for this. */		CaseTestExpr *ctest = makeNode(CaseTestExpr);		ctest->typeId = targetTypeId;		ctest->typeMod = targetTypMod;		basenode = (Node *) ctest;	}	/*	 * We have to split any field-selection operations apart from	 * subscripting.  Adjacent A_Indices nodes have to be treated as a single	 * multidimensional subscript operation.	 */	for_each_cell(i, indirection)	{		Node	   *n = lfirst(i);		if (IsA(n, A_Indices))		{			subscripts = lappend(subscripts, n);			if (((A_Indices *) n)->lidx != NULL)				isSlice = true;		}		else		{			FieldStore *fstore;			Oid			typrelid;			AttrNumber	attnum;			Oid			fieldTypeId;			int32		fieldTypMod;			Assert(IsA(n, String));			/* process subscripts before this field selection */			if (subscripts)			{				Oid			elementTypeId = transformArrayType(targetTypeId);				Oid			typeNeeded = isSlice ? targetTypeId : elementTypeId;				/* recurse to create appropriate RHS for array assign */				rhs = transformAssignmentIndirection(pstate,													 NULL,													 targetName,													 true,													 typeNeeded,													 targetTypMod,													 i,													 rhs);				/* process subscripts */				return (Node *) transformArraySubscripts(pstate,														 basenode,														 targetTypeId,														 elementTypeId,														 targetTypMod,														 subscripts,														 rhs);			}			/* No subscripts, so can process field selection here */			typrelid = typeidTypeRelid(targetTypeId);			if (!typrelid)				ereport(ERROR,						(errcode(ERRCODE_DATATYPE_MISMATCH),						 errmsg("cannot assign to field \"%s\" of column \"%s\" because its type %s is not a composite type",								strVal(n), targetName,								format_type_be(targetTypeId))));			attnum = get_attnum(typrelid, strVal(n));			if (attnum == InvalidAttrNumber)				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_COLUMN),						 errmsg("cannot assign to field \"%s\" of column \"%s\" because there is no such column in data type %s",								strVal(n), targetName,								format_type_be(targetTypeId))));			if (attnum < 0)				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_COLUMN),						 errmsg("cannot assign to system column \"%s\"",								strVal(n))));			get_atttypetypmod(typrelid, attnum,							  &fieldTypeId, &fieldTypMod);			/* recurse to create appropriate RHS for field assign */			rhs = transformAssignmentIndirection(pstate,												 NULL,												 strVal(n),												 false,												 fieldTypeId,												 fieldTypMod,												 lnext(i),												 rhs);			/* and build a FieldStore node */			fstore = makeNode(FieldStore);			fstore->arg = (Expr *) basenode;			fstore->newvals = list_make1(rhs);			fstore->fieldnums = list_make1_int(attnum);			fstore->resulttype = targetTypeId;			return (Node *) fstore;		}	}	/* process trailing subscripts, if any */	if (subscripts)	{		Oid			elementTypeId = transformArrayType(targetTypeId);		Oid			typeNeeded = isSlice ? targetTypeId : elementTypeId;		/* recurse to create appropriate RHS for array assign */		rhs = transformAssignmentIndirection(pstate,											 NULL,											 targetName,											 true,											 typeNeeded,											 targetTypMod,											 NULL,											 rhs);		/* process subscripts */		return (Node *) transformArraySubscripts(pstate,												 basenode,												 targetTypeId,												 elementTypeId,												 targetTypMod,												 subscripts,												 rhs);	}	/* base case: just coerce RHS to match target type ID */	result = coerce_to_target_type(pstate,								   rhs, exprType(rhs),								   targetTypeId, targetTypMod,								   COERCION_ASSIGNMENT,								   COERCE_IMPLICIT_CAST);	if (result == NULL)	{		if (targetIsArray)			ereport(ERROR,					(errcode(ERRCODE_DATATYPE_MISMATCH),					 errmsg("array assignment to \"%s\" requires type %s"							" but expression is of type %s",							targetName,							format_type_be(targetTypeId),							format_type_be(exprType(rhs))),			   errhint("You will need to rewrite or cast the expression.")));		else			ereport(ERROR,					(errcode(ERRCODE_DATATYPE_MISMATCH),					 errmsg("subfield \"%s\" is of type %s"							" but expression is of type %s",							targetName,							format_type_be(targetTypeId),							format_type_be(exprType(rhs))),			   errhint("You will need to rewrite or cast the expression.")));	}	return result;}/* * checkInsertTargets - *	  generate a list of INSERT column targets if not supplied, or *	  test supplied column names to make sure they are in target table. *	  Also return an integer list of the columns' attribute numbers. */List *checkInsertTargets(ParseState *pstate, List *cols, List **attrnos){	*attrnos = NIL;	if (cols == NIL)	{		/*		 * Generate default column list for INSERT.		 */		Form_pg_attribute *attr = pstate->p_target_relation->rd_att->attrs;		int			numcol = pstate->p_target_relation->rd_rel->relnatts;		int			i;		for (i = 0; i < numcol; i++)		{			ResTarget  *col;			if (attr[i]->attisdropped)				continue;			col = makeNode(ResTarget);			col->name = pstrdup(NameStr(attr[i]->attname));			col->indirection = NIL;			col->val = NULL;			cols = lappend(cols, col);			*attrnos = lappend_int(*attrnos, i + 1);		}	}	else	{		/*		 * Do initial validation of user-supplied INSERT column list.		 */		Bitmapset  *wholecols = NULL;		Bitmapset  *partialcols = NULL;		ListCell   *tl;		foreach(tl, cols)		{			ResTarget  *col = (ResTarget *) lfirst(tl);			char	   *name = col->name;			int			attrno;			/* Lookup column name, ereport on failure */			attrno = attnameAttNum(pstate->p_target_relation, name, false);			/*			 * Check for duplicates, but only of whole columns --- we allow			 * INSERT INTO foo (col.subcol1, col.subcol2)			 */			if (col->indirection == NIL)			{				/* whole column; must not have any other assignment */				if (bms_is_member(attrno, wholecols) ||					bms_is_member(attrno, partialcols))					ereport(ERROR,							(errcode(ERRCODE_DUPLICATE_COLUMN),							 errmsg("column \"%s\" specified more than once",									name)));				wholecols = bms_add_member(wholecols, attrno);			}			else			{				/* partial column; must not have any whole assignment */				if (bms_is_member(attrno, wholecols))					ereport(ERROR,							(errcode(ERRCODE_DUPLICATE_COLUMN),							 errmsg("column \"%s\" specified more than once",									name)));				partialcols = bms_add_member(partialcols, attrno);			}			*attrnos = lappend_int(*attrnos, attrno);		}	}	return cols;}/* * ExpandColumnRefStar() *		Turns foo.* (in the target list) into a list of targetlist entries. * * This handles the case where '*' appears as the last or only name in a * ColumnRef. */static List *ExpandColumnRefStar(ParseState *pstate, ColumnRef *cref){	List	   *fields = cref->fields;	int			numnames = list_length(fields);	if (numnames == 1)	{		/*		 * Target item is a bare '*', expand all tables		 *		 * (e.g., SELECT * FROM emp, dept)		 */		return ExpandAllTables(pstate);	}	else	{		/*		 * Target item is relation.*, expand that table		 *		 * (e.g., SELECT emp.*, dname FROM emp, dept)		 */		char	   *schemaname;		char	   *relname;		RangeTblEntry *rte;		int			sublevels_up;		int			rtindex;		switch (numnames)		{			case 2:				schemaname = NULL;				relname = strVal(linitial(fields));				break;			case 3:				schemaname = strVal(linitial(fields));				relname = strVal(lsecond(fields));				break;			case 4:				{					char	   *name1 = strVal(linitial(fields));					/*					 * We check the catalog name and then ignore it.					 */					if (strcmp(name1, get_database_name(MyDatabaseId)) != 0)						ereport(ERROR,								(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),								 errmsg("cross-database references are not implemented: %s",										NameListToString(fields))));					schemaname = strVal(lsecond(fields));					relname = strVal(lthird(fields));					break;				}			default:				ereport(ERROR,						(errcode(ERRCODE_SYNTAX_ERROR),				errmsg("improper qualified name (too many dotted names): %s",					   NameListToString(fields))));				schemaname = NULL;		/* keep compiler quiet */				relname = NULL;				break;		}		rte = refnameRangeTblEntry(pstate, schemaname, relname,								   &sublevels_up);		if (rte == NULL)			rte = addImplicitRTE(pstate, makeRangeVar(schemaname,													  relname));		rtindex = RTERangeTablePosn(pstate, rte, &sublevels_up);		return expandRelAttrs(pstate, rte, rtindex, sublevels_up);	}}/* * ExpandAllTables() *		Turns '*' (in the target list) into a list of targetlist entries. * * tlist entries are generated for each relation appearing in the query's * varnamespace.  We do not consider relnamespace because that would include * input tables of aliasless JOINs, NEW/OLD pseudo-entries, implicit RTEs, * etc. */static List *ExpandAllTables(ParseState *pstate){	List	   *target = NIL;	ListCell   *l;	/* Check for SELECT *; */	if (!pstate->p_varnamespace)		ereport(ERROR,				(errcode(ERRCODE_SYNTAX_ERROR),

⌨️ 快捷键说明

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