pl_comp.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 2,081 行 · 第 1/4 页

C
2,081
字号
						pfree(cp[0]);						pfree(cp[1]);						pfree(cp[2]);						return T_SCALAR;					}				}				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_COLUMN),						 errmsg("row \"%s.%s\" has no field \"%s\"",								cp[0], cp[1], cp[2])));			}		default:			break;	}	pfree(cp[0]);	pfree(cp[1]);	pfree(cp[2]);	return T_ERROR;}/* ---------- * plpgsql_parse_wordtype	The scanner found word%TYPE. word can be *				a variable name or a basetype. * ---------- */intplpgsql_parse_wordtype(char *word){	PLpgSQL_nsitem *nse;	bool		old_nsstate;	HeapTuple	typeTup;	char	   *cp[2];	int			i;	/* Do case conversion and word separation */	/* We convert %type to .type momentarily to keep converter happy */	i = strlen(word) - 5;	Assert(word[i] == '%');	word[i] = '.';	plpgsql_convert_ident(word, cp, 2);	word[i] = '%';	pfree(cp[1]);	/*	 * Do a lookup on the compiler's namestack.  Ensure we scan all levels.	 */	old_nsstate = plpgsql_ns_setlocal(false);	nse = plpgsql_ns_lookup(cp[0], NULL, NULL, NULL);	plpgsql_ns_setlocal(old_nsstate);	if (nse != NULL)	{		pfree(cp[0]);		switch (nse->itemtype)		{			case PLPGSQL_NSTYPE_VAR:				plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;				return T_DTYPE;				/* XXX perhaps allow REC here? */			default:				return T_ERROR;		}	}	/*	 * Word wasn't found on the namestack. Try to find a data type with that	 * name, but ignore shell types and complex types.	 */	typeTup = LookupTypeName(NULL, makeTypeName(cp[0]), NULL);	if (typeTup)	{		Form_pg_type typeStruct = (Form_pg_type) GETSTRUCT(typeTup);		if (!typeStruct->typisdefined ||			typeStruct->typrelid != InvalidOid)		{			ReleaseSysCache(typeTup);			pfree(cp[0]);			return T_ERROR;		}		plpgsql_yylval.dtype = build_datatype(typeTup, -1);		ReleaseSysCache(typeTup);		pfree(cp[0]);		return T_DTYPE;	}	/*	 * Nothing found - up to now it's a word without any special meaning for	 * us.	 */	pfree(cp[0]);	return T_ERROR;}/* ---------- * plpgsql_parse_dblwordtype		Same lookup for word.word%TYPE * ---------- */intplpgsql_parse_dblwordtype(char *word){	PLpgSQL_nsitem *nse;	bool		old_nsstate;	Oid			classOid;	HeapTuple	classtup = NULL;	HeapTuple	attrtup = NULL;	HeapTuple	typetup = NULL;	Form_pg_class classStruct;	Form_pg_attribute attrStruct;	char	   *cp[3];	int			i;	MemoryContext oldCxt;	int			result = T_ERROR;	/* Avoid memory leaks in the long-term function context */	oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);	/* Do case conversion and word separation */	/* We convert %type to .type momentarily to keep converter happy */	i = strlen(word) - 5;	Assert(word[i] == '%');	word[i] = '.';	plpgsql_convert_ident(word, cp, 3);	word[i] = '%';	pfree(cp[2]);	/*	 * Do a lookup on the compiler's namestack.  Ensure we scan all levels.	 * We don't need to check number of names matched, because we will only	 * consider scalar variables.	 */	old_nsstate = plpgsql_ns_setlocal(false);	nse = plpgsql_ns_lookup(cp[0], cp[1], NULL, NULL);	plpgsql_ns_setlocal(old_nsstate);	if (nse != NULL && nse->itemtype == PLPGSQL_NSTYPE_VAR)	{		plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;		result = T_DTYPE;		goto done;	}	/*	 * First word could also be a table name	 */	classOid = RelnameGetRelid(cp[0]);	if (!OidIsValid(classOid))		goto done;	classtup = SearchSysCache(RELOID,							  ObjectIdGetDatum(classOid),							  0, 0, 0);	if (!HeapTupleIsValid(classtup))		goto done;	classStruct = (Form_pg_class) GETSTRUCT(classtup);	/*	 * It must be a relation, sequence, view, or type	 */	if (classStruct->relkind != RELKIND_RELATION &&		classStruct->relkind != RELKIND_SEQUENCE &&		classStruct->relkind != RELKIND_VIEW &&		classStruct->relkind != RELKIND_COMPOSITE_TYPE)		goto done;	/*	 * Fetch the named table field and its type	 */	attrtup = SearchSysCacheAttName(classOid, cp[1]);	if (!HeapTupleIsValid(attrtup))		goto done;	attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);	typetup = SearchSysCache(TYPEOID,							 ObjectIdGetDatum(attrStruct->atttypid),							 0, 0, 0);	if (!HeapTupleIsValid(typetup))		elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);	/*	 * Found that - build a compiler type struct in the caller's cxt and	 * return it	 */	MemoryContextSwitchTo(oldCxt);	plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);	MemoryContextSwitchTo(compile_tmp_cxt);	result = T_DTYPE;done:	if (HeapTupleIsValid(classtup))		ReleaseSysCache(classtup);	if (HeapTupleIsValid(attrtup))		ReleaseSysCache(attrtup);	if (HeapTupleIsValid(typetup))		ReleaseSysCache(typetup);	MemoryContextSwitchTo(oldCxt);	return result;}/* ---------- * plpgsql_parse_tripwordtype		Same lookup for word.word.word%TYPE * ---------- */intplpgsql_parse_tripwordtype(char *word){	Oid			classOid;	HeapTuple	classtup = NULL;	HeapTuple	attrtup = NULL;	HeapTuple	typetup = NULL;	Form_pg_class classStruct;	Form_pg_attribute attrStruct;	char	   *cp[4];	int			i;	RangeVar   *relvar;	MemoryContext oldCxt;	int			result = T_ERROR;	/* Avoid memory leaks in the long-term function context */	oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);	/* Do case conversion and word separation */	/* We convert %type to .type momentarily to keep converter happy */	i = strlen(word) - 5;	Assert(word[i] == '%');	word[i] = '.';	plpgsql_convert_ident(word, cp, 4);	word[i] = '%';	pfree(cp[3]);	relvar = makeRangeVar(cp[0], cp[1]);	classOid = RangeVarGetRelid(relvar, true);	if (!OidIsValid(classOid))		goto done;	classtup = SearchSysCache(RELOID,							  ObjectIdGetDatum(classOid),							  0, 0, 0);	if (!HeapTupleIsValid(classtup))		goto done;	classStruct = (Form_pg_class) GETSTRUCT(classtup);	/*	 * It must be a relation, sequence, view, or type	 */	if (classStruct->relkind != RELKIND_RELATION &&		classStruct->relkind != RELKIND_SEQUENCE &&		classStruct->relkind != RELKIND_VIEW &&		classStruct->relkind != RELKIND_COMPOSITE_TYPE)		goto done;	/*	 * Fetch the named table field and its type	 */	attrtup = SearchSysCacheAttName(classOid, cp[2]);	if (!HeapTupleIsValid(attrtup))		goto done;	attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);	typetup = SearchSysCache(TYPEOID,							 ObjectIdGetDatum(attrStruct->atttypid),							 0, 0, 0);	if (!HeapTupleIsValid(typetup))		elog(ERROR, "cache lookup failed for type %u", attrStruct->atttypid);	/*	 * Found that - build a compiler type struct in the caller's cxt and	 * return it	 */	MemoryContextSwitchTo(oldCxt);	plpgsql_yylval.dtype = build_datatype(typetup, attrStruct->atttypmod);	MemoryContextSwitchTo(compile_tmp_cxt);	result = T_DTYPE;done:	if (HeapTupleIsValid(classtup))		ReleaseSysCache(classtup);	if (HeapTupleIsValid(attrtup))		ReleaseSysCache(attrtup);	if (HeapTupleIsValid(typetup))		ReleaseSysCache(typetup);	MemoryContextSwitchTo(oldCxt);	return result;}/* ---------- * plpgsql_parse_wordrowtype		Scanner found word%ROWTYPE. *					So word must be a table name. * ---------- */intplpgsql_parse_wordrowtype(char *word){	Oid			classOid;	char	   *cp[2];	int			i;	/* Do case conversion and word separation */	/* We convert %rowtype to .rowtype momentarily to keep converter happy */	i = strlen(word) - 8;	Assert(word[i] == '%');	word[i] = '.';	plpgsql_convert_ident(word, cp, 2);	word[i] = '%';	/* Lookup the relation */	classOid = RelnameGetRelid(cp[0]);	if (!OidIsValid(classOid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_TABLE),				 errmsg("relation \"%s\" does not exist", cp[0])));	/*	 * Build and return the row type struct	 */	plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),												  -1);	pfree(cp[0]);	pfree(cp[1]);	return T_DTYPE;}/* ---------- * plpgsql_parse_dblwordrowtype		Scanner found word.word%ROWTYPE. *			So word must be a namespace qualified table name. * ---------- */intplpgsql_parse_dblwordrowtype(char *word){	Oid			classOid;	char	   *cp[3];	int			i;	RangeVar   *relvar;	MemoryContext oldCxt;	/* Avoid memory leaks in long-term function context */	oldCxt = MemoryContextSwitchTo(compile_tmp_cxt);	/* Do case conversion and word separation */	/* We convert %rowtype to .rowtype momentarily to keep converter happy */	i = strlen(word) - 8;	Assert(word[i] == '%');	word[i] = '.';	plpgsql_convert_ident(word, cp, 3);	word[i] = '%';	/* Lookup the relation */	relvar = makeRangeVar(cp[0], cp[1]);	classOid = RangeVarGetRelid(relvar, true);	if (!OidIsValid(classOid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_TABLE),				 errmsg("relation \"%s.%s\" does not exist", cp[0], cp[1])));	/* Build and return the row type struct */	plpgsql_yylval.dtype = plpgsql_build_datatype(get_rel_type_id(classOid),												  -1);	MemoryContextSwitchTo(oldCxt);	return T_DTYPE;}/* * plpgsql_build_variable - build a datum-array entry of a given * datatype * * The returned struct may be a PLpgSQL_var, PLpgSQL_row, or * PLpgSQL_rec depending on the given datatype, and is allocated via * palloc.	The struct is automatically added to the current datum * array, and optionally to the current namespace. */PLpgSQL_variable *plpgsql_build_variable(const char *refname, int lineno, PLpgSQL_type *dtype,					   bool add2namespace){	PLpgSQL_variable *result;	switch (dtype->ttype)	{		case PLPGSQL_TTYPE_SCALAR:			{				/* Ordinary scalar datatype */				PLpgSQL_var *var;				var = palloc0(sizeof(PLpgSQL_var));				var->dtype = PLPGSQL_DTYPE_VAR;				var->refname = pstrdup(refname);				var->lineno = lineno;				var->datatype = dtype;				/* other fields might be filled by caller */				/* preset to NULL */				var->value = 0;				var->isnull = true;				var->freeval = false;				plpgsql_adddatum((PLpgSQL_datum *) var);				if (add2namespace)					plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR,									   var->varno,									   refname);				result = (PLpgSQL_variable *) var;				break;			}		case PLPGSQL_TTYPE_ROW:			{				/* Composite type -- build a row variable */				PLpgSQL_row *row;				row = build_row_from_class(dtype->typrelid);				row->dtype = PLPGSQL_DTYPE_ROW;				row->refname = pstrdup(refname);				row->lineno = lineno;				plpgsql_adddatum((PLpgSQL_datum *) row);				if (add2namespace)					plpgsql_ns_additem(PLPGSQL_NSTYPE_ROW,									   row->rowno,									   refname);				result = (PLpgSQL_variable *) row;				break;			}		case PLPGSQL_TTYPE_REC:			{				/*				 * "record" type -- build a variable-contents record variable				 */				PLpgSQL_rec *rec;				rec = palloc0(sizeof(PLpgSQL_rec));				rec->dtype = PLPGSQL_DTYPE_REC;				rec->refname = pstrdup(refname);				rec->lineno = lineno;				plpgsql_adddatum((PLpgSQL_datum *) rec);				if (add2namespace)					plpgsql_ns_additem(PLPGSQL_NSTYPE_REC,									   rec->recno,									   refname);				result = (PLpgSQL_variable *) rec;				break;			}		case PLPGSQL_TTYPE_PSEUDO:			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("variable \"%s\" has pseudo-type %s",							refname, format_type_be(dtype->typoid))));			result = NULL;		/* keep compiler quiet */			break;		default:			elog(ERROR, "unrecognized ttype: %d", dtype->ttype);			result = NULL;		/* keep compiler quiet */			break;	}	return result;}/* * Build a row-variable data structure given the pg_class OID. */static PLpgSQL_row *build_row_from_class(Oid classOid){	PLpgSQL_row *row;	Relation	rel;	Form_pg_class classStruct;	const char *relname;	int			i;	/*	 * Open the relation to get info.	 */	rel = relation_open(classOid, AccessShareLock);	classStruct = RelationGetForm(rel);	relname = RelationGetRelationName(rel);	/* accept relation, sequence, view, or composite type entries */	if (classStruct->relkind != RELKIND_RELATION &&		classStruct->relkind != RELKIND_SEQUENCE &&		classStruct->relkind != RELKIND_VIEW &&		classStruct->relkind != RELKIND_COMPOSITE_TYPE)		ereport(ERROR,				(errcode(ERRCODE_WRONG_OBJECT_TYPE),				 errmsg("relation \"%s\" is not a table", relname)));	/*	 * Create a row datum entry and all the required variables that it will	 * point to.	 */	row = palloc0(sizeof(PLpgSQL_row));	row->dtype = PLPGSQL_DTYPE_ROW;	row->rowtupdesc = CreateTupleDescCopy(RelationGetDescr(rel));	row->nfields = classStruct->relnatts;	row->fieldnames = palloc(sizeof(char *) * row->nfields);	row->varnos = palloc(sizeof(int) * row->nfields);	for (i = 0; i < row->nfields; i++)	{		Form_pg_attribute attrStruct;		/*		 * Get the attribute and check for dropped column		 */		attrStruct = row->rowtupdesc->attrs[i];

⌨️ 快捷键说明

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