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

📄 pl_comp.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 4 页
字号:
		case PLPGSQL_NSTYPE_REC:			{				/*				 * This word is a record name, so third word must be a field				 * in this record.				 */				PLpgSQL_recfield *new;				new = palloc(sizeof(PLpgSQL_recfield));				new->dtype = PLPGSQL_DTYPE_RECFIELD;				new->fieldname = pstrdup(cp[2]);				new->recparentno = ns->itemno;				plpgsql_adddatum((PLpgSQL_datum *) new);				plpgsql_yylval.scalar = (PLpgSQL_datum *) new;				pfree(cp[0]);				pfree(cp[1]);				pfree(cp[2]);				return T_SCALAR;			}		case PLPGSQL_NSTYPE_ROW:			{				/*				 * This word is a row name, so third word must be a field in				 * this row.				 */				PLpgSQL_row *row;				int			i;				row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);				for (i = 0; i < row->nfields; i++)				{					if (row->fieldnames[i] &&						strcmp(row->fieldnames[i], cp[2]) == 0)					{						plpgsql_yylval.scalar = plpgsql_Datums[row->varnos[i]];						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;	Oid			typeOid;	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. But ensure it moves up to the	 * toplevel.	 */	old_nsstate = plpgsql_ns_setlocal(false);	nse = plpgsql_ns_lookup(cp[0], 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 pg_type entries that are in fact class types.	 */	typeOid = LookupTypeName(makeTypeName(cp[0]));	if (OidIsValid(typeOid))	{		HeapTuple	typeTup;		typeTup = SearchSysCache(TYPEOID,								 ObjectIdGetDatum(typeOid),								 0, 0, 0);		if (HeapTupleIsValid(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] = '%';	/*	 * Lookup the first word	 */	nse = plpgsql_ns_lookup(cp[0], NULL);	/*	 * If this is a label lookup the second word in that label's namestack	 * level	 */	if (nse != NULL)	{		if (nse->itemtype == PLPGSQL_NSTYPE_LABEL)		{			old_nsstate = plpgsql_ns_setlocal(false);			nse = plpgsql_ns_lookup(cp[1], cp[0]);			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;			}		}		/* Return T_ERROR if not found, otherwise 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 * ---------- */#define TYPE_JUNK_LEN	5intplpgsql_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[2];	char	   *colname[1];	int			qualified_att_len;	int			numdots = 0;	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 */	qualified_att_len = strlen(word) - TYPE_JUNK_LEN;	Assert(word[qualified_att_len] == '%');	for (i = 0; i < qualified_att_len; i++)	{		if (word[i] == '.' && ++numdots == 2)			break;	}	cp[0] = (char *) palloc((i + 1) * sizeof(char));	memcpy(cp[0], word, i * sizeof(char));	cp[0][i] = '\0';	/*	 * qualified_att_len - one based position + 1 (null terminator)	 */	cp[1] = (char *) palloc((qualified_att_len - i) * sizeof(char));	memcpy(cp[1], &word[i + 1], (qualified_att_len - i - 1) * sizeof(char));	cp[1][qualified_att_len - i - 1] = '\0';	relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp[0],											  "plpgsql_parse_tripwordtype"));	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	 */	plpgsql_convert_ident(cp[1], colname, 1);	attrtup = SearchSysCacheAttName(classOid, colname[0]);	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. * ---------- */#define ROWTYPE_JUNK_LEN	8intplpgsql_parse_dblwordrowtype(char *word){	Oid			classOid;	char	   *cp;	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) - ROWTYPE_JUNK_LEN;	Assert(word[i] == '%');	word[i] = '\0';	cp = pstrdup(word);	word[i] = '%';	/* Lookup the relation */	relvar = makeRangeVarFromNameList(stringToQualifiedNameList(cp, "plpgsql_parse_dblwordrowtype"));	classOid = RangeVarGetRelid(relvar, true);	if (!OidIsValid(classOid))		ereport(ERROR,				(errcode(ERRCODE_UNDEFINED_TABLE),				 errmsg("relation \"%s\" does not exist", cp)));	/* 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;

⌨️ 快捷键说明

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