fastpath.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 603 行 · 第 1/2 页

C
603
字号
		ereport(ERROR,				(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),				 errmsg("current transaction is aborted, "					 "commands ignored until end of transaction block")));	/*	 * Begin parsing the buffer contents.	 */	if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)		(void) pq_getmsgstring(msgBuf); /* dummy string */	fid = (Oid) pq_getmsgint(msgBuf, 4);		/* function oid */	/*	 * There used to be a lame attempt at caching lookup info here. Now we	 * just do the lookups on every call.	 */	fip = &my_fp;	fetch_fp_info(fid, fip);	/*	 * Check permission to access and call function.  Since we didn't go	 * through a normal name lookup, we need to check schema usage too.	 */	aclresult = pg_namespace_aclcheck(fip->namespace, GetUserId(), ACL_USAGE);	if (aclresult != ACLCHECK_OK)		aclcheck_error(aclresult, ACL_KIND_NAMESPACE,					   get_namespace_name(fip->namespace));	aclresult = pg_proc_aclcheck(fid, GetUserId(), ACL_EXECUTE);	if (aclresult != ACLCHECK_OK)		aclcheck_error(aclresult, ACL_KIND_PROC,					   get_func_name(fid));	/*	 * Set up a query snapshot in case function needs one.	 */	SetQuerySnapshot();	/*	 * Prepare function call info block and insert arguments.	 */	MemSet(&fcinfo, 0, sizeof(fcinfo));	fcinfo.flinfo = &fip->flinfo;	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)		rformat = parse_fcall_arguments(msgBuf, fip, &fcinfo);	else		rformat = parse_fcall_arguments_20(msgBuf, fip, &fcinfo);	/* Verify we reached the end of the message where expected. */	pq_getmsgend(msgBuf);	/*	 * If func is strict, must not call it for null args.	 */	callit = true;	if (fip->flinfo.fn_strict)	{		int			i;		for (i = 0; i < fcinfo.nargs; i++)		{			if (fcinfo.argnull[i])			{				callit = false;				break;			}		}	}	if (callit)	{		/* Okay, do it ... */		retval = FunctionCallInvoke(&fcinfo);	}	else	{		fcinfo.isnull = true;		retval = (Datum) 0;	}	SendFunctionResult(retval, fcinfo.isnull, fip->rettype, rformat);	return 0;}/* * Parse function arguments in a 3.0 protocol message * * Argument values are loaded into *fcinfo, and the desired result format * is returned. */static int16parse_fcall_arguments(StringInfo msgBuf, struct fp_info * fip,					  FunctionCallInfo fcinfo){	int			nargs;	int			i;	int			numAFormats;	int16	   *aformats = NULL;	StringInfoData abuf;	/* Get the argument format codes */	numAFormats = pq_getmsgint(msgBuf, 2);	if (numAFormats > 0)	{		aformats = (int16 *) palloc(numAFormats * sizeof(int16));		for (i = 0; i < numAFormats; i++)			aformats[i] = pq_getmsgint(msgBuf, 2);	}	nargs = pq_getmsgint(msgBuf, 2);	/* # of arguments */	if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS)		ereport(ERROR,				(errcode(ERRCODE_PROTOCOL_VIOLATION),				 errmsg("function call message contains %d arguments but function requires %d",						nargs, fip->flinfo.fn_nargs)));	fcinfo->nargs = nargs;	if (numAFormats > 1 && numAFormats != nargs)		ereport(ERROR,				(errcode(ERRCODE_PROTOCOL_VIOLATION),				 errmsg("function call message contains %d argument formats but %d arguments",						numAFormats, nargs)));	initStringInfo(&abuf);	/*	 * Copy supplied arguments into arg vector.	 */	for (i = 0; i < nargs; ++i)	{		int			argsize;		int16		aformat;		argsize = pq_getmsgint(msgBuf, 4);		if (argsize == -1)		{			fcinfo->argnull[i] = true;			continue;		}		if (argsize < 0)			ereport(ERROR,					(errcode(ERRCODE_PROTOCOL_VIOLATION),			  errmsg("invalid argument size %d in function call message",					 argsize)));		/* Reset abuf to empty, and insert raw data into it */		abuf.len = 0;		abuf.data[0] = '\0';		abuf.cursor = 0;		appendBinaryStringInfo(&abuf,							   pq_getmsgbytes(msgBuf, argsize),							   argsize);		if (numAFormats > 1)			aformat = aformats[i];		else if (numAFormats > 0)			aformat = aformats[0];		else			aformat = 0;		/* default = text */		if (aformat == 0)		{			Oid			typInput;			Oid			typElem;			char	   *pstring;			getTypeInputInfo(fip->argtypes[i], &typInput, &typElem);			/*			 * Since stringinfo.c keeps a trailing null in place even for			 * binary data, the contents of abuf are a valid C string.	We			 * have to do encoding conversion before calling the typinput			 * routine, though.			 */			pstring = (char *)				pg_client_to_server((unsigned char *) abuf.data,									argsize);			fcinfo->arg[i] =				OidFunctionCall3(typInput,								 CStringGetDatum(pstring),								 ObjectIdGetDatum(typElem),								 Int32GetDatum(-1));			/* Free result of encoding conversion, if any */			if (pstring != abuf.data)				pfree(pstring);		}		else if (aformat == 1)		{			Oid			typReceive;			Oid			typElem;			/* Call the argument type's binary input converter */			getTypeBinaryInputInfo(fip->argtypes[i], &typReceive, &typElem);			fcinfo->arg[i] = OidFunctionCall2(typReceive,											  PointerGetDatum(&abuf),											  ObjectIdGetDatum(typElem));			/* Trouble if it didn't eat the whole buffer */			if (abuf.cursor != abuf.len)				ereport(ERROR,						(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),						 errmsg("incorrect binary data format in function argument %d",								i + 1)));		}		else			ereport(ERROR,					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),					 errmsg("unsupported format code: %d", aformat)));	}	/* Return result format code */	return (int16) pq_getmsgint(msgBuf, 2);}/* * Parse function arguments in a 2.0 protocol message * * Argument values are loaded into *fcinfo, and the desired result format * is returned. */static int16parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info * fip,						 FunctionCallInfo fcinfo){	int			nargs;	int			i;	StringInfoData abuf;	nargs = pq_getmsgint(msgBuf, 4);	/* # of arguments */	if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS)		ereport(ERROR,				(errcode(ERRCODE_PROTOCOL_VIOLATION),				 errmsg("function call message contains %d arguments but function requires %d",						nargs, fip->flinfo.fn_nargs)));	fcinfo->nargs = nargs;	initStringInfo(&abuf);	/*	 * Copy supplied arguments into arg vector.  In protocol 2.0 these are	 * always assumed to be supplied in binary format.	 *	 * Note: although the original protocol 2.0 code did not have any way for	 * the frontend to specify a NULL argument, we now choose to interpret	 * length == -1 as meaning a NULL.	 */	for (i = 0; i < nargs; ++i)	{		int			argsize;		Oid			typReceive;		Oid			typElem;		argsize = pq_getmsgint(msgBuf, 4);		if (argsize == -1)		{			fcinfo->argnull[i] = true;			continue;		}		if (argsize < 0)			ereport(ERROR,					(errcode(ERRCODE_PROTOCOL_VIOLATION),			  errmsg("invalid argument size %d in function call message",					 argsize)));		/* Reset abuf to empty, and insert raw data into it */		abuf.len = 0;		abuf.data[0] = '\0';		abuf.cursor = 0;		appendBinaryStringInfo(&abuf,							   pq_getmsgbytes(msgBuf, argsize),							   argsize);		/* Call the argument type's binary input converter */		getTypeBinaryInputInfo(fip->argtypes[i], &typReceive, &typElem);		fcinfo->arg[i] = OidFunctionCall2(typReceive,										  PointerGetDatum(&abuf),										  ObjectIdGetDatum(typElem));		/* Trouble if it didn't eat the whole buffer */		if (abuf.cursor != abuf.len)			ereport(ERROR,					(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),			errmsg("incorrect binary data format in function argument %d",				   i + 1)));	}	/* Desired result format is always binary in protocol 2.0 */	return 1;}

⌨️ 快捷键说明

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