pl_comp.c

来自「关系型数据库 Postgresql 6.5.2」· C语言 代码 · 共 1,370 行 · 第 1/3 页

C
1,370
字号
	/* ----------	 * Create the magic found variable indicating if the	 * last FOR or SELECT statement returned data	 * ----------	 */	var = malloc(sizeof(PLpgSQL_var));	memset(var, 0, sizeof(PLpgSQL_var));	var->dtype = PLPGSQL_DTYPE_VAR;	var->refname = strdup("found");	var->lineno = 0;	plpgsql_parse_word("bool");	var->datatype = plpgsql_yylval.dtype;	var->isconst = false;	var->notnull = false;	var->default_val = NULL;	plpgsql_adddatum((PLpgSQL_datum *) var);	plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, strdup("found"));	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)	{		plpgsql_comperrinfo();		elog(ERROR, "plpgsql: parser returned %d ???", parse_rc);	}	/* ----------	 * 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;	/* ----------	 * Finally return the compiled function	 * ----------	 */	if (plpgsql_DumpExecTree)		plpgsql_dumptree(function);	return function;}/* ---------- * 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;	HeapTuple	typeTup;	Form_pg_type typeStruct;	char	   *typeXlated;	/* ----------	 * We do our lookups case insensitive	 * ----------	 */	cp = plpgsql_tolower(word);	/* ----------	 * Special handling when compiling triggers	 * ----------	 */	if (plpgsql_curr_compile->fn_functype == T_TRIGGER)	{		if (!strcmp(cp, "tg_argv"))		{			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.trigarg = trigarg;			plpgsql_SpaceScanned = save_spacescanned;			return T_TGARGV;		}	}	/* ----------	 * Do a lookup on the compilers namestack	 * ----------	 */	nse = plpgsql_ns_lookup(cp, NULL);	if (nse != NULL)	{		pfree(cp);		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;		}	}	/* ----------	 * Try to find a data type with that name, but ignore	 * pg_type entries that are in fact class types.	 * ----------	 */	typeXlated = xlateSqlType(cp);	typeTup = SearchSysCacheTuple(TYPNAME,								  PointerGetDatum(typeXlated), 0, 0, 0);	if (HeapTupleIsValid(typeTup))	{		PLpgSQL_type *typ;		typeStruct = (Form_pg_type) GETSTRUCT(typeTup);		if (typeStruct->typrelid != InvalidOid)		{			pfree(cp);			return T_WORD;		}		typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type));		typ->typname = strdup(nameout(&(typeStruct->typname)));		typ->typoid = typeTup->t_data->t_oid;		fmgr_info(typeStruct->typinput, &(typ->typinput));		typ->typbyval = typeStruct->typbyval;		typ->atttypmod = -1;		plpgsql_yylval.dtype = typ;		pfree(cp);		return T_DTYPE;	}	/* ----------	 * Nothing found - up to now it's a word without any	 * special meaning for us.	 * ----------	 */	pfree(cp);	return T_WORD;}/* ---------- * plpgsql_parse_dblword		Same lookup for two words *					separated by a dot. * ---------- */intplpgsql_parse_dblword(char *string){	char	   *word1;	char	   *word2;	PLpgSQL_nsitem *ns;	/* ----------	 * Convert to lower case and separate the words	 * ----------	 */	word1 = plpgsql_tolower(string);	word2 = strchr(word1, '.');	*word2++ = '\0';	/* ----------	 * Lookup the first word	 * ----------	 */	ns = plpgsql_ns_lookup(word1, NULL);	if (ns == NULL)	{		pfree(word1);		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(word2, word1);			if (ns == NULL)			{				pfree(word1);				return T_ERROR;			}			switch (ns->itemtype)			{				case PLPGSQL_NSTYPE_VAR:					plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[ns->itemno]);					pfree(word1);					return T_VARIABLE;				case PLPGSQL_NSTYPE_REC:					plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]);					pfree(word1);					return T_RECORD;				case PLPGSQL_NSTYPE_ROW:					plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]);					pfree(word1);					return T_ROW;				default:					pfree(word1);					return T_ERROR;			}		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(word2);				new->recno = ns->itemno;				plpgsql_adddatum((PLpgSQL_datum *) new);				pfree(word1);				plpgsql_yylval.recfield = new;				return T_RECFIELD;			}		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 (!strcmp(row->fieldnames[i], word2))					{						plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);						pfree(word1);						return T_VARIABLE;					}				}				plpgsql_comperrinfo();				elog(ERROR, "row %s doesn't have a field %s",					 word1, word2);			}		default:			break;	}	pfree(word1);	return T_ERROR;}/* ---------- * plpgsql_parse_tripword		Same lookup for three words *					separated by dots. * ---------- */intplpgsql_parse_tripword(char *string){	char	   *word1;	char	   *word2;	char	   *word3;	PLpgSQL_nsitem *ns;	/* ----------	 * Convert to lower case and separate the words	 * ----------	 */	word1 = plpgsql_tolower(string);	word2 = strchr(word1, '.');	*word2++ = '\0';	word3 = strchr(word2, '.');	*word3++ = '\0';	/* ----------	 * Lookup the first word - it must be a label	 * ----------	 */	ns = plpgsql_ns_lookup(word1, NULL);	if (ns == NULL)	{		pfree(word1);		return T_ERROR;	}	if (ns->itemtype != PLPGSQL_NSTYPE_LABEL)	{		pfree(word1);		return T_ERROR;	}	/* ----------	 * First word is a label, so second word could be	 * a record or row	 * ----------	 */	ns = plpgsql_ns_lookup(word2, word1);	if (ns == NULL)	{		pfree(word1);		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(word3);				new->recno = ns->itemno;				plpgsql_adddatum((PLpgSQL_datum *) new);				pfree(word1);				plpgsql_yylval.recfield = new;				return T_RECFIELD;			}		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 (!strcmp(row->fieldnames[i], word3))					{						plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]);						pfree(word1);						return T_VARIABLE;					}				}				plpgsql_comperrinfo();				elog(ERROR, "row %s.%s doesn't have a field %s",					 word1, word2, word3);			}		default:			break;	}	pfree(word1);	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;	char	   *cp;	HeapTuple	typeTup;	Form_pg_type typeStruct;	char	   *typeXlated;	bool		old_nsstate;	/* ----------	 * We do our lookups case insensitive	 * ----------	 */	cp = plpgsql_tolower(word);	*(strchr(cp, '%')) = '\0';	/* ----------	 * 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, NULL);	plpgsql_ns_setlocal(old_nsstate);	if (nse != NULL)	{		pfree(cp);		switch (nse->itemtype)		{			case PLPGSQL_NSTYPE_VAR:				plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;

⌨️ 快捷键说明

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