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

📄 pl_comp.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
			var->dtype = PLPGSQL_DTYPE_VAR;			var->refname = strdup("tg_relname");			var->lineno = 0;			var->datatype = plpgsql_parse_datatype("name");			var->isconst = false;			var->notnull = false;			var->default_val = NULL;			plpgsql_adddatum((PLpgSQL_datum *) var);			plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);			function->tg_relname_varno = var->varno;			/*			 * Add the variable tg_nargs			 */			var = malloc(sizeof(PLpgSQL_var));			memset(var, 0, sizeof(PLpgSQL_var));			var->dtype = PLPGSQL_DTYPE_VAR;			var->refname = strdup("tg_nargs");			var->lineno = 0;			var->datatype = plpgsql_parse_datatype("int4");			var->isconst = false;			var->notnull = false;			var->default_val = NULL;			plpgsql_adddatum((PLpgSQL_datum *) var);			plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);			function->tg_nargs_varno = var->varno;			break;		default:			elog(ERROR, "unrecognized function typecode: %u", functype);			break;	}	/*	 * Create the magic FOUND variable.	 */	var = malloc(sizeof(PLpgSQL_var));	memset(var, 0, sizeof(PLpgSQL_var));	var->dtype = PLPGSQL_DTYPE_VAR;	var->refname = strdup("found");	var->lineno = 0;	var->datatype = plpgsql_parse_datatype("bool");	var->isconst = false;	var->notnull = false;	var->default_val = NULL;	plpgsql_adddatum((PLpgSQL_datum *) var);	plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, var->refname);	function->found_varno = var->varno;	/*	 * Forget about the above created variables	 */	plpgsql_add_initdatums(NULL);	/*	 * Now parse the functions text	 */	parse_rc = plpgsql_yyparse();	if (parse_rc != 0)		elog(ERROR, "plpgsql parser returned %d", parse_rc);	plpgsql_scanner_finish();	/*	 * If that was successful, complete the functions info.	 */	function->fn_nargs = procStruct->pronargs;	for (i = 0; i < function->fn_nargs; i++)		function->fn_argvarnos[i] = arg_varnos[i];	function->ndatums = plpgsql_nDatums;	function->datums = malloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums);	for (i = 0; i < plpgsql_nDatums; i++)		function->datums[i] = plpgsql_Datums[i];	function->action = plpgsql_yylval.program;	/* Debug dump for completed functions */	if (plpgsql_DumpExecTree)		plpgsql_dumptree(function);	/*	 * add it to the hash table	 */	plpgsql_HashTableInsert(function, hashkey);	/*	 * Pop the error context stack	 */	error_context_stack = plerrcontext.previous;	plpgsql_error_funcname = NULL;	plpgsql_error_lineno = 0;	return function;}/* * error context callback to let us supply a call-stack traceback */static voidplpgsql_compile_error_callback(void *arg){	if (plpgsql_error_funcname)		errcontext("compile of PL/pgSQL function \"%s\" near line %d",				   plpgsql_error_funcname, plpgsql_error_lineno);}/* ---------- * plpgsql_parse_word		The scanner calls this to postparse *				any single word not found by a *				keyword rule. * ---------- */intplpgsql_parse_word(char *word){	PLpgSQL_nsitem *nse;	char	   *cp[1];	/* Do case conversion and word separation */	plpgsql_convert_ident(word, cp, 1);	/*	 * Recognize tg_argv when compiling triggers	 */	if (plpgsql_curr_compile->fn_functype == T_TRIGGER)	{		if (strcmp(cp[0], "tg_argv") == 0)		{			int			save_spacescanned = plpgsql_SpaceScanned;			PLpgSQL_trigarg *trigarg;			trigarg = malloc(sizeof(PLpgSQL_trigarg));			memset(trigarg, 0, sizeof(PLpgSQL_trigarg));			trigarg->dtype = PLPGSQL_DTYPE_TRIGARG;			if (plpgsql_yylex() != '[')				plpgsql_yyerror("expected \"[\"");			trigarg->argnum = plpgsql_read_expression(']', "]");			plpgsql_adddatum((PLpgSQL_datum *) trigarg);			plpgsql_yylval.variable = (PLpgSQL_datum *) trigarg;			plpgsql_SpaceScanned = save_spacescanned;			pfree(cp[0]);			return T_VARIABLE;		}	}	/*	 * Do a lookup on the compilers namestack	 */	nse = plpgsql_ns_lookup(cp[0], NULL);	if (nse != NULL)	{		pfree(cp[0]);		switch (nse->itemtype)		{			case PLPGSQL_NSTYPE_LABEL:				return T_LABEL;			case PLPGSQL_NSTYPE_VAR:				plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[nse->itemno]);				return T_VARIABLE;			case PLPGSQL_NSTYPE_REC:				plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]);				return T_RECORD;			case PLPGSQL_NSTYPE_ROW:				plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]);				return T_ROW;			default:				return T_ERROR;		}	}	/*	 * Nothing found - up to now it's a word without any special meaning	 * for us.	 */	pfree(cp[0]);	return T_WORD;}/* ---------- * plpgsql_parse_dblword		Same lookup for two words *					separated by a dot. * ---------- */intplpgsql_parse_dblword(char *word){	PLpgSQL_nsitem *ns;	char	   *cp[2];	/* Do case conversion and word separation */	plpgsql_convert_ident(word, cp, 2);	/*	 * Lookup the first word	 */	ns = plpgsql_ns_lookup(cp[0], NULL);	if (ns == NULL)	{		pfree(cp[0]);		pfree(cp[1]);		return T_ERROR;	}	switch (ns->itemtype)	{		case PLPGSQL_NSTYPE_LABEL:			/*			 * First word is a label, so second word could be a variable,			 * record or row in that bodies namestack. Anything else could			 * only be something in a query given to the SPI manager and			 * T_ERROR will get eaten up by the collector routines.			 */			ns = plpgsql_ns_lookup(cp[1], cp[0]);			pfree(cp[0]);			pfree(cp[1]);			if (ns == NULL)				return T_ERROR;			switch (ns->itemtype)			{				case PLPGSQL_NSTYPE_VAR:					plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[ns->itemno]);					return T_VARIABLE;				case PLPGSQL_NSTYPE_REC:					plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);					return T_RECORD;				case PLPGSQL_NSTYPE_ROW:					plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);					return T_ROW;				default:					return T_ERROR;			}			break;		case PLPGSQL_NSTYPE_REC:			{				/*				 * First word is a record name, so second word must be a				 * field in this record.				 */				PLpgSQL_recfield *new;				new = malloc(sizeof(PLpgSQL_recfield));				new->dtype = PLPGSQL_DTYPE_RECFIELD;				new->fieldname = strdup(cp[1]);				new->recparentno = ns->itemno;				plpgsql_adddatum((PLpgSQL_datum *) new);				plpgsql_yylval.variable = (PLpgSQL_datum *) new;				pfree(cp[0]);				pfree(cp[1]);				return T_VARIABLE;			}		case PLPGSQL_NSTYPE_ROW:			{				/*				 * First word is a row name, so second 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[1]) == 0)					{						plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);						pfree(cp[0]);						pfree(cp[1]);						return T_VARIABLE;					}				}				ereport(ERROR,						(errcode(ERRCODE_UNDEFINED_COLUMN),						 errmsg("row \"%s\" has no field \"%s\"",								cp[0], cp[1])));			}		default:			break;	}	pfree(cp[0]);	pfree(cp[1]);	return T_ERROR;}/* ---------- * plpgsql_parse_tripword		Same lookup for three words *					separated by dots. * ---------- */intplpgsql_parse_tripword(char *word){	PLpgSQL_nsitem *ns;	char	   *cp[3];	/* Do case conversion and word separation */	plpgsql_convert_ident(word, cp, 3);	/*	 * Lookup the first word - it must be a label	 */	ns = plpgsql_ns_lookup(cp[0], NULL);	if (ns == NULL)	{		pfree(cp[0]);		pfree(cp[1]);		pfree(cp[2]);		return T_ERROR;	}	if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)	{		pfree(cp[0]);		pfree(cp[1]);		pfree(cp[2]);		return T_ERROR;	}	/*	 * First word is a label, so second word could be a record or row	 */	ns = plpgsql_ns_lookup(cp[1], cp[0]);	if (ns == NULL)	{		pfree(cp[0]);		pfree(cp[1]);		pfree(cp[2]);		return T_ERROR;	}	switch (ns->itemtype)	{		case PLPGSQL_NSTYPE_REC:			{				/*				 * This word is a record name, so third word must be a				 * field in this record.				 */				PLpgSQL_recfield *new;				new = malloc(sizeof(PLpgSQL_recfield));				new->dtype = PLPGSQL_DTYPE_RECFIELD;				new->fieldname = strdup(cp[2]);				new->recparentno = ns->itemno;				plpgsql_adddatum((PLpgSQL_datum *) new);				plpgsql_yylval.variable = (PLpgSQL_datum *) new;				pfree(cp[0]);				pfree(cp[1]);				pfree(cp[2]);				return T_VARIABLE;			}		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.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);						pfree(cp[0]);						pfree(cp[1]);						pfree(cp[2]);						return T_VARIABLE;					}				}				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 compilers 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;			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;	Form_pg_class classStruct;	HeapTuple	attrtup;	Form_pg_attribute attrStruct;	HeapTuple	typetup;	char	   *cp[3];	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, 3);	word[i] = '%';	pfree(cp[2]);	/*	 * Lookup the first word	 */	nse = plpgsql_ns_lookup(cp[0], NULL);	/*	 * If this is a label lookup the second word in that labels 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);			pfree(cp[0]);			pfree(cp[1]);			if (nse != NULL)			{				switch (nse->itemtype)				{					case PLPGSQL_NSTYPE_VAR:						plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;						return T_DTYPE;					default:						return T_ERROR;				}			}			return T_ERROR;		}		pfree(cp[0]);		pfree(cp[1]);		return T_ERROR;	}	/*	 * First word could also be a table name	 */	classOid = RelnameGetRelid(cp[0]);	if (!OidIsValid(classOid))	{		pfree(cp[0]);		pfree(cp[1]);		return T_ERROR;	}	classtup = SearchSysCache(RELOID,							  ObjectIdGetDatum(classOid),							  0, 0, 0);	if (!HeapTupleIsValid(classtup))	{		pfree(cp[0]);		pfree(cp[1]);		return T_ERROR;	}	/*	 * It must be a relation, sequence, view, or type	 */	classStruct = (Form_pg_class) GETSTRUCT(classtup);	if (classStruct->relkind != RELKIND_RELATION &&		classStruct->relkind != RELKIND_SEQUENCE &&		classStruct->relkind != RELKIND_VIEW &&		classStruct->relkind != RELKIND_COMPOSITE_TYPE)	{		ReleaseSysCache(classtup);		pfree(cp[0]);		pfree(cp[1]);		return T_ERROR;	}	/*	 * Fetch the named table field and it's type	 */	attrtup = SearchSysCacheAttName(classOid, cp[1]);	if (!HeapTupleIsValid(attrtup))	{

⌨️ 快捷键说明

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