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

📄 pl_comp.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 3 页
字号:
				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.	 * ----------	 */	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_ERROR;		}		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_ERROR;}/* ---------- * plpgsql_parse_dblwordtype		Same lookup for word.word%TYPE * ---------- */intplpgsql_parse_dblwordtype(char *string){	char	   *word1;	char	   *word2;	PLpgSQL_nsitem *nse;	bool		old_nsstate;	HeapTuple	classtup;	Form_pg_class classStruct;	HeapTuple	attrtup;	Form_pg_attribute attrStruct;	HeapTuple	typetup;	Form_pg_type typeStruct;	PLpgSQL_type *typ;	/* ----------	 * Convert to lower case and separate the words	 * ----------	 */	word1 = plpgsql_tolower(string);	word2 = strchr(word1, '.');	*word2++ = '\0';	*(strchr(word2, '%')) = '\0';	/* ----------	 * Lookup the first word	 * ----------	 */	nse = plpgsql_ns_lookup(word1, 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(word2, word1);			plpgsql_ns_setlocal(old_nsstate);			pfree(word1);			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(word1);		return T_ERROR;	}	/* ----------	 * First word could also be a table name	 * ----------	 */	classtup = SearchSysCacheTuple(RELNAME,								   PointerGetDatum(word1), 0, 0, 0);	if (!HeapTupleIsValid(classtup))	{		pfree(word1);		return T_ERROR;	}	/* ----------	 * It must be a (shared) relation class	 * ----------	 */	classStruct = (Form_pg_class) GETSTRUCT(classtup);	if (classStruct->relkind != 'r' && classStruct->relkind != 's')	{		pfree(word1);		return T_ERROR;	}	/* ----------	 * Fetch the named table field and it's type	 * ----------	 */	attrtup = SearchSysCacheTuple(ATTNAME,							   ObjectIdGetDatum(classtup->t_data->t_oid),								  PointerGetDatum(word2), 0, 0);	if (!HeapTupleIsValid(attrtup))	{		pfree(word1);		return T_ERROR;	}	attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);	typetup = SearchSysCacheTuple(TYPOID,						ObjectIdGetDatum(attrStruct->atttypid), 0, 0, 0);	if (!HeapTupleIsValid(typetup))	{		plpgsql_comperrinfo();		elog(ERROR, "cache lookup for type %u of %s.%s failed",			 attrStruct->atttypid, word1, word2);	}	/* ----------	 * Found that - build a compiler type struct and return it	 * ----------	 */	typeStruct = (Form_pg_type) GETSTRUCT(typetup);	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 = attrStruct->atttypmod;	plpgsql_yylval.dtype = typ;	pfree(word1);	return T_DTYPE;}/* ---------- * plpgsql_parse_wordrowtype		Scanner found word%ROWTYPE. *					So word must be a table name. * ---------- */intplpgsql_parse_wordrowtype(char *string){	HeapTuple	classtup;	Form_pg_class classStruct;	HeapTuple	typetup;	Form_pg_type typeStruct;	HeapTuple	attrtup;	Form_pg_attribute attrStruct;	char	   *word1;	char	   *cp;	int			i;	PLpgSQL_row *row;	PLpgSQL_var *var;	/* ----------	 * Get the word in lower case and fetch the pg_class tuple.	 * ----------	 */	word1 = plpgsql_tolower(string);	cp = strchr(word1, '%');	*cp = '\0';	classtup = SearchSysCacheTuple(RELNAME,								   PointerGetDatum(word1), 0, 0, 0);	if (!HeapTupleIsValid(classtup))	{		plpgsql_comperrinfo();		elog(ERROR, "%s: no such class", word1);	}	classStruct = (Form_pg_class) GETSTRUCT(classtup);	if (classStruct->relkind != 'r' && classStruct->relkind != 's')	{		plpgsql_comperrinfo();		elog(ERROR, "%s isn't a table", word1);	}	/* ----------	 * Fetch the tables pg_type tuple too	 * ----------	 */	typetup = SearchSysCacheTuple(TYPNAME,								  PointerGetDatum(word1), 0, 0, 0);	if (!HeapTupleIsValid(typetup))	{		plpgsql_comperrinfo();		elog(ERROR, "cache lookup for %s in pg_type failed", word1);	}	/* ----------	 * Create a row datum entry and all the required variables	 * that it will point to.	 * ----------	 */	row = malloc(sizeof(PLpgSQL_row));	memset(row, 0, sizeof(PLpgSQL_row));	row->dtype = PLPGSQL_DTYPE_ROW;	row->nfields = classStruct->relnatts;	row->rowtypeclass = typetup->t_data->t_oid;	row->fieldnames = malloc(sizeof(char *) * row->nfields);	row->varnos = malloc(sizeof(int) * row->nfields);	for (i = 0; i < row->nfields; i++)	{		/* ----------		 * Get the attribute and it's type		 * ----------		 */		attrtup = SearchSysCacheTuple(ATTNUM,							   ObjectIdGetDatum(classtup->t_data->t_oid),									  (Datum) (i + 1), 0, 0);		if (!HeapTupleIsValid(attrtup))		{			plpgsql_comperrinfo();			elog(ERROR, "cache lookup for attribute %d of class %s failed",				 i + 1, word1);		}		attrStruct = (Form_pg_attribute) GETSTRUCT(attrtup);		typetup = SearchSysCacheTuple(TYPOID,						ObjectIdGetDatum(attrStruct->atttypid), 0, 0, 0);		if (!HeapTupleIsValid(typetup))		{			plpgsql_comperrinfo();			elog(ERROR, "cache lookup for type %u of %s.%s failed",				 attrStruct->atttypid, word1,				 nameout(&(attrStruct->attname)));		}		typeStruct = (Form_pg_type) GETSTRUCT(typetup);		cp = strdup(nameout(&(attrStruct->attname)));		/* ----------		 * Create the internal variable		 * We know if the table definitions contain a default value		 * or if the field is declared in the table as NOT NULL. But		 * it's possible to create a table field as NOT NULL without		 * a default value and that would lead to problems later when		 * initializing the variables due to entering a block at		 * execution time. Thus we ignore this information for now.		 * ----------		 */		var = malloc(sizeof(PLpgSQL_var));		var->dtype = PLPGSQL_DTYPE_VAR;		var->refname = malloc(strlen(word1) + strlen(cp) + 2);		strcpy(var->refname, word1);		strcat(var->refname, ".");		strcat(var->refname, cp);		var->datatype = malloc(sizeof(PLpgSQL_type));		var->datatype->typname = strdup(nameout(&(typeStruct->typname)));		var->datatype->typoid = typetup->t_data->t_oid;		fmgr_info(typeStruct->typinput, &(var->datatype->typinput));		var->datatype->typbyval = typeStruct->typbyval;		var->datatype->atttypmod = attrStruct->atttypmod;		var->isconst = false;		var->notnull = false;		var->default_val = NULL;		var->value = (Datum) 0;		var->isnull = true;		var->shouldfree = false;		plpgsql_adddatum((PLpgSQL_datum *) var);		/* ----------		 * Add the variable to the row.		 * ----------		 */		row->fieldnames[i] = cp;		row->varnos[i] = var->varno;	}	/* ----------	 * Return the complete row definition	 * ----------	 */	plpgsql_yylval.row = row;	return T_ROW;}/* ---------- * plpgsql_adddatum			Add a variable, record or row *					to the compilers datum list. * ---------- */voidplpgsql_adddatum(PLpgSQL_datum * new){	if (plpgsql_nDatums == datums_alloc)	{		datums_alloc *= 2;		plpgsql_Datums = repalloc(plpgsql_Datums, sizeof(PLpgSQL_datum *) * datums_alloc);	}	new->dno = plpgsql_nDatums;	plpgsql_Datums[plpgsql_nDatums++] = new;}/* ---------- * plpgsql_add_initdatums		Put all datum entries created *					since the last call into the *					finishing code block so the *					block knows which variables to *					reinitialize when entered. * ---------- */intplpgsql_add_initdatums(int **varnos){	int			i;	int			n = 0;	for (i = datums_last; i < plpgsql_nDatums; i++)	{		switch (plpgsql_Datums[i]->dtype)		{			case PLPGSQL_DTYPE_VAR:				n++;				break;			default:				break;		}	}	if (varnos != NULL)	{		*varnos = (int *) malloc(sizeof(int) * n);		n = 0;		for (i = datums_last; i < plpgsql_nDatums; i++)		{			switch (plpgsql_Datums[i]->dtype)			{				case PLPGSQL_DTYPE_VAR:					(*varnos)[n++] = plpgsql_Datums[i]->dno;				default:					break;			}		}	}	datums_last = plpgsql_nDatums;	return n;}/* ---------- * plpgsql_comperrinfo			Called before elog(ERROR, ...) *					during compile. * ---------- */voidplpgsql_comperrinfo(){	elog(NOTICE, "plpgsql: ERROR during compile of %s near line %d",		 plpgsql_error_funcname, plpgsql_error_lineno);}/* --------- * plpgsql_yyerror			Handle parser error * --------- */voidplpgsql_yyerror(const char *s){	plpgsql_error_lineno = plpgsql_yylineno;	plpgsql_comperrinfo();	elog(ERROR, "%s at or near \"%s\"", s, plpgsql_yytext);}/* ---------- * xlateSqlType() * Convert alternate type names to internal Postgres types. * * Stolen from backend's main parser * ---------- */static char *xlateSqlType(char *name){	if (!strcasecmp(name, "int")		|| !strcasecmp(name, "integer"))		return "int4";	else if (!strcasecmp(name, "smallint"))		return "int2";	else if (!strcasecmp(name, "real")			 || !strcasecmp(name, "float"))		return "float8";	else if (!strcasecmp(name, "interval"))		return "timespan";	else if (!strcasecmp(name, "boolean"))		return "bool";	else		return name;}	/* xlateSqlType() */

⌨️ 快捷键说明

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