1996-07-09 06:22:35 +00:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-13 23:22:53 +00:00
|
|
|
* fastpath.c
|
1997-09-07 05:04:48 +00:00
|
|
|
* routines to handle function requests from the frontend
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
2018-01-02 23:30:12 -05:00
|
|
|
* Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group
|
2000-01-26 05:58:53 +00:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/backend/tcop/fastpath.c
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
* NOTES
|
1997-09-07 05:04:48 +00:00
|
|
|
* This cruft is the server side of PQfn.
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
2012-08-30 16:15:44 -04:00
|
|
|
#include "access/htup_details.h"
|
2006-07-13 16:49:20 +00:00
|
|
|
#include "access/xact.h"
|
2013-04-05 08:51:31 -04:00
|
|
|
#include "catalog/objectaccess.h"
|
1996-07-09 06:22:35 +00:00
|
|
|
#include "catalog/pg_proc.h"
|
1999-07-16 05:00:38 +00:00
|
|
|
#include "libpq/libpq.h"
|
|
|
|
#include "libpq/pqformat.h"
|
2003-05-09 18:08:48 +00:00
|
|
|
#include "mb/pg_wchar.h"
|
2006-07-11 16:35:33 +00:00
|
|
|
#include "miscadmin.h"
|
2017-10-01 15:36:14 -07:00
|
|
|
#include "port/pg_bswap.h"
|
1999-07-16 05:00:38 +00:00
|
|
|
#include "tcop/fastpath.h"
|
2006-06-11 15:49:28 +00:00
|
|
|
#include "tcop/tcopprot.h"
|
2003-01-01 21:57:05 +00:00
|
|
|
#include "utils/acl.h"
|
2001-06-01 15:45:42 +00:00
|
|
|
#include "utils/lsyscache.h"
|
2008-03-26 18:48:59 +00:00
|
|
|
#include "utils/snapmgr.h"
|
1999-07-16 05:00:38 +00:00
|
|
|
#include "utils/syscache.h"
|
1996-07-09 06:22:35 +00:00
|
|
|
|
|
|
|
|
2003-05-08 18:16:37 +00:00
|
|
|
/*
|
|
|
|
* Formerly, this code attempted to cache the function and type info
|
|
|
|
* looked up by fetch_fp_info, but only for the duration of a single
|
|
|
|
* transaction command (since in theory the info could change between
|
|
|
|
* commands). This was utterly useless, because postgres.c executes
|
|
|
|
* each fastpath call as a separate transaction command, and so the
|
|
|
|
* cached data could never actually have been reused. If it had worked
|
|
|
|
* as intended, it would have had problems anyway with dangling references
|
2014-05-06 12:12:18 -04:00
|
|
|
* in the FmgrInfo struct. So, forget about caching and just repeat the
|
|
|
|
* syscache fetches on each usage. They're not *that* expensive.
|
2003-05-08 18:16:37 +00:00
|
|
|
*/
|
|
|
|
struct fp_info
|
|
|
|
{
|
|
|
|
Oid funcid;
|
|
|
|
FmgrInfo flinfo; /* function lookup info for funcid */
|
2003-05-09 18:08:48 +00:00
|
|
|
Oid namespace; /* other stuff from pg_proc */
|
|
|
|
Oid rettype;
|
|
|
|
Oid argtypes[FUNC_MAX_ARGS];
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 15:18:54 -04:00
|
|
|
char fname[NAMEDATALEN]; /* function name for logging */
|
2003-05-08 18:16:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-06-21 14:39:04 -04:00
|
|
|
static int16 parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip,
|
2003-08-04 00:43:34 +00:00
|
|
|
FunctionCallInfo fcinfo);
|
2017-06-21 14:39:04 -04:00
|
|
|
static int16 parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info *fip,
|
2003-08-04 00:43:34 +00:00
|
|
|
FunctionCallInfo fcinfo);
|
2003-05-08 18:16:37 +00:00
|
|
|
|
|
|
|
|
2003-04-19 00:02:30 +00:00
|
|
|
/* ----------------
|
|
|
|
* GetOldFunctionMessage
|
|
|
|
*
|
|
|
|
* In pre-3.0 protocol, there is no length word on the message, so we have
|
|
|
|
* to have code that understands the message layout to absorb the message
|
|
|
|
* into a buffer. We want to do this before we start execution, so that
|
|
|
|
* we do not lose sync with the frontend if there's an error.
|
|
|
|
*
|
|
|
|
* The caller should already have initialized buf to empty.
|
|
|
|
* ----------------
|
|
|
|
*/
|
Be more careful to not lose sync in the FE/BE protocol.
If any error occurred while we were in the middle of reading a protocol
message from the client, we could lose sync, and incorrectly try to
interpret a part of another message as a new protocol message. That will
usually lead to an "invalid frontend message" error that terminates the
connection. However, this is a security issue because an attacker might
be able to deliberately cause an error, inject a Query message in what's
supposed to be just user data, and have the server execute it.
We were quite careful to not have CHECK_FOR_INTERRUPTS() calls or other
operations that could ereport(ERROR) in the middle of processing a message,
but a query cancel interrupt or statement timeout could nevertheless cause
it to happen. Also, the V2 fastpath and COPY handling were not so careful.
It's very difficult to recover in the V2 COPY protocol, so we will just
terminate the connection on error. In practice, that's what happened
previously anyway, as we lost protocol sync.
To fix, add a new variable in pqcomm.c, PqCommReadingMsg, that is set
whenever we're in the middle of reading a message. When it's set, we cannot
safely ERROR out and continue running, because we might've read only part
of a message. PqCommReadingMsg acts somewhat similarly to critical sections
in that if an error occurs while it's set, the error handler will force the
connection to be terminated, as if the error was FATAL. It's not
implemented by promoting ERROR to FATAL in elog.c, like ERROR is promoted
to PANIC in critical sections, because we want to be able to use
PG_TRY/CATCH to recover and regain protocol sync. pq_getmessage() takes
advantage of that to prevent an OOM error from terminating the connection.
To prevent unnecessary connection terminations, add a holdoff mechanism
similar to HOLD/RESUME_INTERRUPTS() that can be used hold off query cancel
interrupts, but still allow die interrupts. The rules on which interrupts
are processed when are now a bit more complicated, so refactor
ProcessInterrupts() and the calls to it in signal handlers so that the
signal handlers always call it if ImmediateInterruptOK is set, and
ProcessInterrupts() can decide to not do anything if the other conditions
are not met.
Reported by Emil Lenngren. Patch reviewed by Noah Misch and Andres Freund.
Backpatch to all supported versions.
Security: CVE-2015-0244
2015-02-02 17:08:45 +02:00
|
|
|
int
|
2003-04-19 00:02:30 +00:00
|
|
|
GetOldFunctionMessage(StringInfo buf)
|
|
|
|
{
|
|
|
|
int32 ibuf;
|
|
|
|
int nargs;
|
|
|
|
|
|
|
|
/* Dummy string argument */
|
|
|
|
if (pq_getstring(buf))
|
|
|
|
return EOF;
|
|
|
|
/* Function OID */
|
|
|
|
if (pq_getbytes((char *) &ibuf, 4))
|
|
|
|
return EOF;
|
|
|
|
appendBinaryStringInfo(buf, (char *) &ibuf, 4);
|
|
|
|
/* Number of arguments */
|
|
|
|
if (pq_getbytes((char *) &ibuf, 4))
|
|
|
|
return EOF;
|
|
|
|
appendBinaryStringInfo(buf, (char *) &ibuf, 4);
|
2017-10-01 15:36:14 -07:00
|
|
|
nargs = pg_ntoh32(ibuf);
|
2003-04-19 00:02:30 +00:00
|
|
|
/* For each argument ... */
|
|
|
|
while (nargs-- > 0)
|
|
|
|
{
|
|
|
|
int argsize;
|
|
|
|
|
|
|
|
/* argsize */
|
|
|
|
if (pq_getbytes((char *) &ibuf, 4))
|
|
|
|
return EOF;
|
|
|
|
appendBinaryStringInfo(buf, (char *) &ibuf, 4);
|
2017-10-01 15:36:14 -07:00
|
|
|
argsize = pg_ntoh32(ibuf);
|
2003-05-09 18:08:48 +00:00
|
|
|
if (argsize < -1)
|
2003-04-19 00:02:30 +00:00
|
|
|
{
|
|
|
|
/* FATAL here since no hope of regaining message sync */
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(FATAL,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 15:35:54 -04:00
|
|
|
errmsg("invalid argument size %d in function call message",
|
|
|
|
argsize)));
|
2003-04-19 00:02:30 +00:00
|
|
|
}
|
|
|
|
/* and arg contents */
|
|
|
|
if (argsize > 0)
|
|
|
|
{
|
|
|
|
/* Allocate space for arg */
|
|
|
|
enlargeStringInfo(buf, argsize);
|
|
|
|
/* And grab it */
|
|
|
|
if (pq_getbytes(buf->data + buf->len, argsize))
|
|
|
|
return EOF;
|
|
|
|
buf->len += argsize;
|
|
|
|
/* Place a trailing null per StringInfo convention */
|
|
|
|
buf->data[buf->len] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1996-07-09 06:22:35 +00:00
|
|
|
/* ----------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* SendFunctionResult
|
2002-08-24 15:00:47 +00:00
|
|
|
*
|
2003-05-09 18:08:48 +00:00
|
|
|
* Note: although this routine doesn't check, the format had better be 1
|
|
|
|
* (binary) when talking to a pre-3.0 client.
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------
|
|
|
|
*/
|
|
|
|
static void
|
2003-05-09 18:08:48 +00:00
|
|
|
SendFunctionResult(Datum retval, bool isnull, Oid rettype, int16 format)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2003-05-09 18:08:48 +00:00
|
|
|
bool newstyle = (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3);
|
1999-04-25 03:19:27 +00:00
|
|
|
StringInfoData buf;
|
|
|
|
|
2003-04-22 00:08:07 +00:00
|
|
|
pq_beginmessage(&buf, 'V');
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2003-05-09 18:08:48 +00:00
|
|
|
if (isnull)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
2003-05-09 18:08:48 +00:00
|
|
|
if (newstyle)
|
2017-10-11 21:00:46 -07:00
|
|
|
pq_sendint32(&buf, -1);
|
2003-05-08 18:16:37 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-05-09 18:08:48 +00:00
|
|
|
if (!newstyle)
|
2003-05-08 18:16:37 +00:00
|
|
|
pq_sendbyte(&buf, 'G');
|
2003-05-09 18:08:48 +00:00
|
|
|
|
|
|
|
if (format == 0)
|
|
|
|
{
|
2005-05-01 18:56:19 +00:00
|
|
|
Oid typoutput;
|
2003-05-09 18:08:48 +00:00
|
|
|
bool typisvarlena;
|
|
|
|
char *outputstr;
|
|
|
|
|
2005-05-01 18:56:19 +00:00
|
|
|
getTypeOutputInfo(rettype, &typoutput, &typisvarlena);
|
2006-04-04 19:35:37 +00:00
|
|
|
outputstr = OidOutputFunctionCall(typoutput, retval);
|
2003-05-09 18:08:48 +00:00
|
|
|
pq_sendcountedtext(&buf, outputstr, strlen(outputstr), false);
|
|
|
|
pfree(outputstr);
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
2003-05-09 18:08:48 +00:00
|
|
|
else if (format == 1)
|
|
|
|
{
|
2005-05-01 18:56:19 +00:00
|
|
|
Oid typsend;
|
2003-05-09 18:08:48 +00:00
|
|
|
bool typisvarlena;
|
|
|
|
bytea *outputbytes;
|
|
|
|
|
2005-05-01 18:56:19 +00:00
|
|
|
getTypeBinaryOutputInfo(rettype, &typsend, &typisvarlena);
|
2006-04-04 19:35:37 +00:00
|
|
|
outputbytes = OidSendFunctionCall(typsend, retval);
|
2017-10-11 21:00:46 -07:00
|
|
|
pq_sendint32(&buf, VARSIZE(outputbytes) - VARHDRSZ);
|
2003-05-09 18:08:48 +00:00
|
|
|
pq_sendbytes(&buf, VARDATA(outputbytes),
|
|
|
|
VARSIZE(outputbytes) - VARHDRSZ);
|
|
|
|
pfree(outputbytes);
|
|
|
|
}
|
|
|
|
else
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("unsupported format code: %d", format)));
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
2003-05-09 18:08:48 +00:00
|
|
|
if (!newstyle)
|
|
|
|
pq_sendbyte(&buf, '0');
|
|
|
|
|
1999-04-25 03:19:27 +00:00
|
|
|
pq_endmessage(&buf);
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2001-06-01 15:45:42 +00:00
|
|
|
* fetch_fp_info
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
* Performs catalog lookups to load a struct fp_info 'fip' for the
|
|
|
|
* function 'func_id'.
|
|
|
|
*/
|
|
|
|
static void
|
2017-06-21 14:39:04 -04:00
|
|
|
fetch_fp_info(Oid func_id, struct fp_info *fip)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2001-06-01 15:45:42 +00:00
|
|
|
HeapTuple func_htp;
|
1997-09-08 02:41:22 +00:00
|
|
|
Form_pg_proc pp;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
Assert(OidIsValid(func_id));
|
2004-01-07 18:56:30 +00:00
|
|
|
Assert(fip != NULL);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Since the validity of this structure is determined by whether the
|
2014-05-06 12:12:18 -04:00
|
|
|
* funcid is OK, we clear the funcid here. It must not be set to the
|
2005-10-15 02:49:52 +00:00
|
|
|
* correct value until we are about to return with a good struct fp_info,
|
|
|
|
* since we can be interrupted (i.e., with an ereport(ERROR, ...)) at any
|
|
|
|
* time. [No longer really an issue since we don't save the struct
|
|
|
|
* fp_info across transactions anymore, but keep it anyway.]
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
2005-03-29 03:01:32 +00:00
|
|
|
MemSet(fip, 0, sizeof(struct fp_info));
|
1997-09-07 05:04:48 +00:00
|
|
|
fip->funcid = InvalidOid;
|
|
|
|
|
2001-06-01 15:45:42 +00:00
|
|
|
fmgr_info(func_id, &fip->flinfo);
|
|
|
|
|
2010-02-14 18:42:19 +00:00
|
|
|
func_htp = SearchSysCache1(PROCOID, ObjectIdGetDatum(func_id));
|
1997-09-07 05:04:48 +00:00
|
|
|
if (!HeapTupleIsValid(func_htp))
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
|
|
|
errmsg("function with OID %u does not exist", func_id)));
|
1997-09-07 05:04:48 +00:00
|
|
|
pp = (Form_pg_proc) GETSTRUCT(func_htp);
|
|
|
|
|
2005-03-29 00:17:27 +00:00
|
|
|
/* watch out for catalog entries with more than FUNC_MAX_ARGS args */
|
|
|
|
if (pp->pronargs > FUNC_MAX_ARGS)
|
|
|
|
elog(ERROR, "function %s has more than %d arguments",
|
|
|
|
NameStr(pp->proname), FUNC_MAX_ARGS);
|
|
|
|
|
2003-05-09 18:08:48 +00:00
|
|
|
fip->namespace = pp->pronamespace;
|
|
|
|
fip->rettype = pp->prorettype;
|
2005-03-29 00:17:27 +00:00
|
|
|
memcpy(fip->argtypes, pp->proargtypes.values, pp->pronargs * sizeof(Oid));
|
2006-10-19 22:44:11 +00:00
|
|
|
strlcpy(fip->fname, NameStr(pp->proname), NAMEDATALEN);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2000-11-16 22:30:52 +00:00
|
|
|
ReleaseSysCache(func_htp);
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*
|
|
|
|
* This must be last!
|
|
|
|
*/
|
|
|
|
fip->funcid = func_id;
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
|
1996-07-09 06:22:35 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* HandleFunctionRequest
|
|
|
|
*
|
|
|
|
* Server side of PQfn (fastpath function calls from the frontend).
|
|
|
|
* This corresponds to the libpq protocol symbol "F".
|
|
|
|
*
|
2003-04-19 00:02:30 +00:00
|
|
|
* INPUT:
|
2017-04-06 09:09:39 +03:00
|
|
|
* postgres.c has already read the message body and will pass it in
|
|
|
|
* msgBuf.
|
2000-10-24 20:59:35 +00:00
|
|
|
*
|
|
|
|
* Note: palloc()s done here and in the called function do not need to be
|
|
|
|
* cleaned up explicitly. We are called from PostgresMain() in the
|
2003-05-02 20:54:36 +00:00
|
|
|
* MessageContext memory context, which will be automatically reset when
|
2000-10-24 20:59:35 +00:00
|
|
|
* control returns to PostgresMain.
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2017-04-06 09:09:39 +03:00
|
|
|
void
|
2003-04-19 00:02:30 +00:00
|
|
|
HandleFunctionRequest(StringInfo msgBuf)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
Oid fid;
|
2003-01-01 21:57:05 +00:00
|
|
|
AclResult aclresult;
|
2000-05-28 17:56:29 +00:00
|
|
|
FunctionCallInfoData fcinfo;
|
2003-05-09 18:08:48 +00:00
|
|
|
int16 rformat;
|
2000-05-28 17:56:29 +00:00
|
|
|
Datum retval;
|
2001-06-01 15:45:42 +00:00
|
|
|
struct fp_info my_fp;
|
1997-09-07 05:04:48 +00:00
|
|
|
struct fp_info *fip;
|
2003-05-09 18:18:54 +00:00
|
|
|
bool callit;
|
2006-09-08 15:55:53 +00:00
|
|
|
bool was_logged = false;
|
|
|
|
char msec_str[32];
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2003-04-19 00:02:30 +00:00
|
|
|
/*
|
2017-04-06 09:09:39 +03:00
|
|
|
* We only accept COMMIT/ABORT if we are in an aborted transaction, and
|
|
|
|
* COMMIT/ABORT cannot be executed through the fastpath interface.
|
2003-04-19 00:02:30 +00:00
|
|
|
*/
|
|
|
|
if (IsAbortedTransactionBlockState())
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
|
|
|
|
errmsg("current transaction is aborted, "
|
2005-10-15 02:49:52 +00:00
|
|
|
"commands ignored until end of transaction block")));
|
2003-04-19 00:02:30 +00:00
|
|
|
|
2006-06-11 15:49:28 +00:00
|
|
|
/*
|
2006-10-04 00:30:14 +00:00
|
|
|
* Now that we know we are in a valid transaction, set snapshot in case
|
|
|
|
* needed by function itself or one of the datatype I/O routines.
|
2006-06-11 15:49:28 +00:00
|
|
|
*/
|
2008-05-12 20:02:02 +00:00
|
|
|
PushActiveSnapshot(GetTransactionSnapshot());
|
2006-06-11 15:49:28 +00:00
|
|
|
|
2003-04-19 00:02:30 +00:00
|
|
|
/*
|
2003-05-09 18:08:48 +00:00
|
|
|
* Begin parsing the buffer contents.
|
2003-04-19 00:02:30 +00:00
|
|
|
*/
|
2003-05-08 18:16:37 +00:00
|
|
|
if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
|
2006-10-04 00:30:14 +00:00
|
|
|
(void) pq_getmsgstring(msgBuf); /* dummy string */
|
2003-05-08 18:16:37 +00:00
|
|
|
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 15:18:54 -04:00
|
|
|
fid = (Oid) pq_getmsgint(msgBuf, 4); /* function oid */
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
/*
|
2001-10-25 05:50:21 +00:00
|
|
|
* There used to be a lame attempt at caching lookup info here. Now we
|
|
|
|
* just do the lookups on every call.
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
2001-06-01 15:45:42 +00:00
|
|
|
fip = &my_fp;
|
|
|
|
fetch_fp_info(fid, fip);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2006-10-19 22:44:11 +00:00
|
|
|
/* Log as soon as we have the function OID and name */
|
|
|
|
if (log_statement == LOGSTMT_ALL)
|
|
|
|
{
|
|
|
|
ereport(LOG,
|
|
|
|
(errmsg("fastpath function call: \"%s\" (OID %u)",
|
|
|
|
fip->fname, fid)));
|
|
|
|
was_logged = true;
|
|
|
|
}
|
|
|
|
|
2003-05-09 18:08:48 +00:00
|
|
|
/*
|
|
|
|
* 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)
|
2017-12-02 09:26:34 -05:00
|
|
|
aclcheck_error(aclresult, OBJECT_SCHEMA,
|
2003-08-01 00:15:26 +00:00
|
|
|
get_namespace_name(fip->namespace));
|
2013-04-05 08:51:31 -04:00
|
|
|
InvokeNamespaceSearchHook(fip->namespace, true);
|
2003-05-09 18:08:48 +00:00
|
|
|
|
2003-04-19 00:02:30 +00:00
|
|
|
aclresult = pg_proc_aclcheck(fid, GetUserId(), ACL_EXECUTE);
|
|
|
|
if (aclresult != ACLCHECK_OK)
|
2017-12-02 09:26:34 -05:00
|
|
|
aclcheck_error(aclresult, OBJECT_FUNCTION,
|
2003-08-01 00:15:26 +00:00
|
|
|
get_func_name(fid));
|
2013-04-12 08:55:56 -04:00
|
|
|
InvokeFunctionExecuteHook(fid);
|
2003-04-19 00:02:30 +00:00
|
|
|
|
2003-05-05 00:44:56 +00:00
|
|
|
/*
|
2003-05-08 18:16:37 +00:00
|
|
|
* Prepare function call info block and insert arguments.
|
2011-04-12 19:19:24 -04:00
|
|
|
*
|
|
|
|
* Note: for now we pass collation = InvalidOid, so collation-sensitive
|
|
|
|
* functions can't be called this way. Perhaps we should pass
|
|
|
|
* DEFAULT_COLLATION_OID, instead?
|
2003-05-05 00:44:56 +00:00
|
|
|
*/
|
2011-04-12 19:19:24 -04:00
|
|
|
InitFunctionCallInfoData(fcinfo, &fip->flinfo, 0, InvalidOid, NULL, NULL);
|
2003-05-08 18:16:37 +00:00
|
|
|
|
|
|
|
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
|
2003-05-09 18:08:48 +00:00
|
|
|
rformat = parse_fcall_arguments(msgBuf, fip, &fcinfo);
|
2003-05-08 18:16:37 +00:00
|
|
|
else
|
2003-05-09 18:08:48 +00:00
|
|
|
rformat = parse_fcall_arguments_20(msgBuf, fip, &fcinfo);
|
2003-05-08 18:16:37 +00:00
|
|
|
|
|
|
|
/* Verify we reached the end of the message where expected. */
|
|
|
|
pq_getmsgend(msgBuf);
|
|
|
|
|
2003-05-09 18:18:54 +00:00
|
|
|
/*
|
|
|
|
* If func is strict, must not call it for null args.
|
|
|
|
*/
|
|
|
|
callit = true;
|
|
|
|
if (fip->flinfo.fn_strict)
|
|
|
|
{
|
2003-08-04 00:43:34 +00:00
|
|
|
int i;
|
2003-05-09 18:18:54 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2003-05-08 18:16:37 +00:00
|
|
|
|
2006-06-14 01:24:14 +00:00
|
|
|
/* ensure we do at least one CHECK_FOR_INTERRUPTS per function call */
|
|
|
|
CHECK_FOR_INTERRUPTS();
|
|
|
|
|
2003-05-09 18:08:48 +00:00
|
|
|
SendFunctionResult(retval, fcinfo.isnull, fip->rettype, rformat);
|
2003-05-08 18:16:37 +00:00
|
|
|
|
2008-05-12 20:02:02 +00:00
|
|
|
/* We no longer need the snapshot */
|
|
|
|
PopActiveSnapshot();
|
|
|
|
|
2006-09-08 15:55:53 +00:00
|
|
|
/*
|
|
|
|
* Emit duration logging if appropriate.
|
|
|
|
*/
|
|
|
|
switch (check_log_duration(msec_str, was_logged))
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
ereport(LOG,
|
|
|
|
(errmsg("duration: %s ms", msec_str)));
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
ereport(LOG,
|
2006-10-19 22:44:11 +00:00
|
|
|
(errmsg("duration: %s ms fastpath function call: \"%s\" (OID %u)",
|
|
|
|
msec_str, fip->fname, fid)));
|
2006-09-08 15:55:53 +00:00
|
|
|
break;
|
|
|
|
}
|
2003-05-08 18:16:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse function arguments in a 3.0 protocol message
|
2003-05-09 18:08:48 +00:00
|
|
|
*
|
|
|
|
* Argument values are loaded into *fcinfo, and the desired result format
|
|
|
|
* is returned.
|
2003-05-08 18:16:37 +00:00
|
|
|
*/
|
2003-05-09 18:08:48 +00:00
|
|
|
static int16
|
2017-06-21 14:39:04 -04:00
|
|
|
parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip,
|
2003-05-08 18:16:37 +00:00
|
|
|
FunctionCallInfo fcinfo)
|
|
|
|
{
|
|
|
|
int nargs;
|
|
|
|
int i;
|
|
|
|
int numAFormats;
|
|
|
|
int16 *aformats = NULL;
|
2003-05-09 18:08:48 +00:00
|
|
|
StringInfoData abuf;
|
2003-05-08 18:16:37 +00:00
|
|
|
|
|
|
|
/* 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 */
|
|
|
|
|
2000-05-28 17:56:29 +00:00
|
|
|
if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS)
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("function call message contains %d arguments but function requires %d",
|
|
|
|
nargs, fip->flinfo.fn_nargs)));
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2003-05-08 18:16:37 +00:00
|
|
|
fcinfo->nargs = nargs;
|
2000-05-28 17:56:29 +00:00
|
|
|
|
2003-05-09 18:08:48 +00:00
|
|
|
if (numAFormats > 1 && numAFormats != nargs)
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("function call message contains %d argument formats but %d arguments",
|
|
|
|
numAFormats, nargs)));
|
2003-05-09 18:08:48 +00:00
|
|
|
|
|
|
|
initStringInfo(&abuf);
|
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
/*
|
2003-05-08 18:16:37 +00:00
|
|
|
* Copy supplied arguments into arg vector.
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
2000-05-28 17:56:29 +00:00
|
|
|
for (i = 0; i < nargs; ++i)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
2003-04-19 00:02:30 +00:00
|
|
|
int argsize;
|
2003-05-09 18:08:48 +00:00
|
|
|
int16 aformat;
|
2003-04-19 00:02:30 +00:00
|
|
|
|
|
|
|
argsize = pq_getmsgint(msgBuf, 4);
|
2003-05-09 18:08:48 +00:00
|
|
|
if (argsize == -1)
|
|
|
|
{
|
|
|
|
fcinfo->argnull[i] = true;
|
2000-05-28 17:56:29 +00:00
|
|
|
}
|
2006-04-04 19:35:37 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
fcinfo->argnull[i] = false;
|
|
|
|
if (argsize < 0)
|
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 15:35:54 -04:00
|
|
|
errmsg("invalid argument size %d in function call message",
|
|
|
|
argsize)));
|
2006-04-04 19:35:37 +00:00
|
|
|
|
|
|
|
/* Reset abuf to empty, and insert raw data into it */
|
2007-03-03 19:32:55 +00:00
|
|
|
resetStringInfo(&abuf);
|
2006-04-04 19:35:37 +00:00
|
|
|
appendBinaryStringInfo(&abuf,
|
|
|
|
pq_getmsgbytes(msgBuf, argsize),
|
|
|
|
argsize);
|
|
|
|
}
|
2003-05-09 18:08:48 +00:00
|
|
|
|
|
|
|
if (numAFormats > 1)
|
|
|
|
aformat = aformats[i];
|
|
|
|
else if (numAFormats > 0)
|
|
|
|
aformat = aformats[0];
|
2000-05-28 17:56:29 +00:00
|
|
|
else
|
2003-05-09 18:08:48 +00:00
|
|
|
aformat = 0; /* default = text */
|
|
|
|
|
|
|
|
if (aformat == 0)
|
|
|
|
{
|
2004-06-06 00:41:28 +00:00
|
|
|
Oid typinput;
|
|
|
|
Oid typioparam;
|
2003-05-09 18:08:48 +00:00
|
|
|
char *pstring;
|
|
|
|
|
2004-06-06 00:41:28 +00:00
|
|
|
getTypeInputInfo(fip->argtypes[i], &typinput, &typioparam);
|
2003-08-04 00:43:34 +00:00
|
|
|
|
2003-05-09 18:08:48 +00:00
|
|
|
/*
|
2003-08-04 00:43:34 +00:00
|
|
|
* Since stringinfo.c keeps a trailing null in place even for
|
2014-05-06 12:12:18 -04:00
|
|
|
* binary data, the contents of abuf are a valid C string. We
|
2003-08-04 00:43:34 +00:00
|
|
|
* have to do encoding conversion before calling the typinput
|
2003-05-09 18:08:48 +00:00
|
|
|
* routine, though.
|
|
|
|
*/
|
2006-04-04 19:35:37 +00:00
|
|
|
if (argsize == -1)
|
|
|
|
pstring = NULL;
|
|
|
|
else
|
|
|
|
pstring = pg_client_to_server(abuf.data, argsize);
|
|
|
|
|
|
|
|
fcinfo->arg[i] = OidInputFunctionCall(typinput, pstring,
|
|
|
|
typioparam, -1);
|
2003-05-09 18:08:48 +00:00
|
|
|
/* Free result of encoding conversion, if any */
|
2006-04-04 19:35:37 +00:00
|
|
|
if (pstring && pstring != abuf.data)
|
2003-05-09 18:08:48 +00:00
|
|
|
pfree(pstring);
|
|
|
|
}
|
|
|
|
else if (aformat == 1)
|
|
|
|
{
|
2004-06-06 00:41:28 +00:00
|
|
|
Oid typreceive;
|
|
|
|
Oid typioparam;
|
2006-04-04 19:35:37 +00:00
|
|
|
StringInfo bufptr;
|
2003-05-09 18:08:48 +00:00
|
|
|
|
|
|
|
/* Call the argument type's binary input converter */
|
2004-06-06 00:41:28 +00:00
|
|
|
getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
|
2003-05-09 18:08:48 +00:00
|
|
|
|
2006-04-04 19:35:37 +00:00
|
|
|
if (argsize == -1)
|
|
|
|
bufptr = NULL;
|
|
|
|
else
|
|
|
|
bufptr = &abuf;
|
|
|
|
|
|
|
|
fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, bufptr,
|
|
|
|
typioparam, -1);
|
2003-05-09 18:08:48 +00:00
|
|
|
|
|
|
|
/* Trouble if it didn't eat the whole buffer */
|
2006-04-04 19:35:37 +00:00
|
|
|
if (argsize != -1 && abuf.cursor != abuf.len)
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 15:35:54 -04:00
|
|
|
errmsg("incorrect binary data format in function argument %d",
|
|
|
|
i + 1)));
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
2003-05-09 18:08:48 +00:00
|
|
|
else
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
|
|
|
errmsg("unsupported format code: %d", aformat)));
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
2003-05-09 18:08:48 +00:00
|
|
|
/* Return result format code */
|
|
|
|
return (int16) pq_getmsgint(msgBuf, 2);
|
2003-05-08 18:16:37 +00:00
|
|
|
}
|
2003-01-01 21:57:05 +00:00
|
|
|
|
2003-05-08 18:16:37 +00:00
|
|
|
/*
|
|
|
|
* Parse function arguments in a 2.0 protocol message
|
2003-05-09 18:08:48 +00:00
|
|
|
*
|
|
|
|
* Argument values are loaded into *fcinfo, and the desired result format
|
|
|
|
* is returned.
|
2003-05-08 18:16:37 +00:00
|
|
|
*/
|
2003-05-09 18:08:48 +00:00
|
|
|
static int16
|
2017-06-21 14:39:04 -04:00
|
|
|
parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info *fip,
|
2003-05-08 18:16:37 +00:00
|
|
|
FunctionCallInfo fcinfo)
|
|
|
|
{
|
|
|
|
int nargs;
|
|
|
|
int i;
|
2003-05-09 18:08:48 +00:00
|
|
|
StringInfoData abuf;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2003-05-08 18:16:37 +00:00
|
|
|
nargs = pq_getmsgint(msgBuf, 4); /* # of arguments */
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2003-05-08 18:16:37 +00:00
|
|
|
if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS)
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
|
|
|
errmsg("function call message contains %d arguments but function requires %d",
|
|
|
|
nargs, fip->flinfo.fn_nargs)));
|
2003-05-08 18:16:37 +00:00
|
|
|
|
|
|
|
fcinfo->nargs = nargs;
|
|
|
|
|
2003-05-09 18:08:48 +00:00
|
|
|
initStringInfo(&abuf);
|
|
|
|
|
2003-05-08 18:16:37 +00:00
|
|
|
/*
|
2003-05-09 18:08:48 +00:00
|
|
|
* Copy supplied arguments into arg vector. In protocol 2.0 these are
|
|
|
|
* always assumed to be supplied in binary format.
|
|
|
|
*
|
2005-11-22 18:17:34 +00:00
|
|
|
* 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.
|
2003-05-08 18:16:37 +00:00
|
|
|
*/
|
|
|
|
for (i = 0; i < nargs; ++i)
|
|
|
|
{
|
|
|
|
int argsize;
|
2004-06-06 00:41:28 +00:00
|
|
|
Oid typreceive;
|
|
|
|
Oid typioparam;
|
2003-05-08 18:16:37 +00:00
|
|
|
|
2006-04-04 19:35:37 +00:00
|
|
|
getTypeBinaryInputInfo(fip->argtypes[i], &typreceive, &typioparam);
|
|
|
|
|
2003-05-08 18:16:37 +00:00
|
|
|
argsize = pq_getmsgint(msgBuf, 4);
|
2003-05-09 18:08:48 +00:00
|
|
|
if (argsize == -1)
|
|
|
|
{
|
|
|
|
fcinfo->argnull[i] = true;
|
2006-04-04 19:35:37 +00:00
|
|
|
fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, NULL,
|
|
|
|
typioparam, -1);
|
2003-05-09 18:08:48 +00:00
|
|
|
continue;
|
2003-05-08 18:16:37 +00:00
|
|
|
}
|
2005-03-29 03:01:32 +00:00
|
|
|
fcinfo->argnull[i] = false;
|
2003-05-09 18:08:48 +00:00
|
|
|
if (argsize < 0)
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_PROTOCOL_VIOLATION),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 15:35:54 -04:00
|
|
|
errmsg("invalid argument size %d in function call message",
|
|
|
|
argsize)));
|
2003-05-09 18:08:48 +00:00
|
|
|
|
|
|
|
/* Reset abuf to empty, and insert raw data into it */
|
2007-03-03 19:32:55 +00:00
|
|
|
resetStringInfo(&abuf);
|
2003-05-09 18:08:48 +00:00
|
|
|
appendBinaryStringInfo(&abuf,
|
|
|
|
pq_getmsgbytes(msgBuf, argsize),
|
|
|
|
argsize);
|
|
|
|
|
2006-04-04 19:35:37 +00:00
|
|
|
fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, &abuf,
|
|
|
|
typioparam, -1);
|
2003-05-09 18:08:48 +00:00
|
|
|
|
|
|
|
/* Trouble if it didn't eat the whole buffer */
|
|
|
|
if (abuf.cursor != abuf.len)
|
2003-07-22 19:00:12 +00:00
|
|
|
ereport(ERROR,
|
|
|
|
(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
|
Phase 3 of pgindent updates.
Don't move parenthesized lines to the left, even if that means they
flow past the right margin.
By default, BSD indent lines up statement continuation lines that are
within parentheses so that they start just to the right of the preceding
left parenthesis. However, traditionally, if that resulted in the
continuation line extending to the right of the desired right margin,
then indent would push it left just far enough to not overrun the margin,
if it could do so without making the continuation line start to the left of
the current statement indent. That makes for a weird mix of indentations
unless one has been completely rigid about never violating the 80-column
limit.
This behavior has been pretty universally panned by Postgres developers.
Hence, disable it with indent's new -lpl switch, so that parenthesized
lines are always lined up with the preceding left paren.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 15:35:54 -04:00
|
|
|
errmsg("incorrect binary data format in function argument %d",
|
|
|
|
i + 1)));
|
2003-05-08 18:16:37 +00:00
|
|
|
}
|
2003-05-09 18:08:48 +00:00
|
|
|
|
|
|
|
/* Desired result format is always binary in protocol 2.0 */
|
|
|
|
return 1;
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|