Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wUtGV-001WHw-2u for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Jun 2026 21:36:44 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wUtGU-003bYf-1b for pgsql-hackers@arkaria.postgresql.org; Wed, 03 Jun 2026 21:36:42 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wUtGU-003bYX-0R for pgsql-hackers@lists.postgresql.org; Wed, 03 Jun 2026 21:36:42 +0000 Received: from mail-oi1-x236.google.com ([2607:f8b0:4864:20::236]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wUtGS-000000017jA-05Fw for pgsql-hackers@postgresql.org; Wed, 03 Jun 2026 21:36:41 +0000 Received: by mail-oi1-x236.google.com with SMTP id 5614622812f47-48662d16d08so493741b6e.2 for ; Wed, 03 Jun 2026 14:36:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1780522598; x=1781127398; darn=postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=Jq5NXQ0d/8D7UuJpZxvWZ8/F+an7r8B1no4OVIV8Dw4=; b=sT+7FFqEWnhNEONLvquY/ZgDsmPPH8bI/h3oYP+cyhTWs80vJey4dYbpVM4oIekJjZ 5GU83FsGZC+sQoXGnlo6FEdasBJtPrnK+wbGRPVt0AK9SCmFFPqtrqaCltrPjzb45IXc UdOiDNeW1hQJI2fGVMq6Qm6IfLp0H2aG/bP+tcpFYcAZRTgQffVdhxCUIfjxAVCliD5T Xbz6lEexCNbxPw8meTxUA5uRH4Tnk0mEZshkNkNH/l5udURRxqehvqB2u3RODqJYVgZJ jXecGNNDDv90XYyVOnkaSyc9Z4iAu9AiQ017dzmQztmbzeD06VImQV6qUfvnzfg/zVsM qLFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780522598; x=1781127398; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Jq5NXQ0d/8D7UuJpZxvWZ8/F+an7r8B1no4OVIV8Dw4=; b=TK6PaiMulECr3SgYFORNiKPgJf3QKPiAw8xwbu7yfLUGuVGvpShkglHTgZlDbPTLRO Ks7DR39oxwnrPJNSm+xHiOjBuhwbfIMIQPYfbDKRXWgANULFqJrdMlWjcpf2YeSVY3G4 7Q4spNY6zPOLqJq30Kfzn7ABtGCx6KDH97phFAM0PhTSX24mHPmhoOeBYdh8hsSt89nR LjMbT8VS5MrMr65mdvC0jr8F5innrb8Ob3RyKA8pRKPPL4jsk32aM/0gzV7cRlobtiMt oik6e6MDzd3rOsYlphC4aPFtuXEuErVk27gJJ41xfDpsVivhyLVVQYBtaOegy/mDvBa0 B8VA== X-Gm-Message-State: AOJu0Yw9y/9zbqAvHX06ymUNOD9aF7HvcfKNjBnRVDC5TVQk05RWZJNB TqDOIT+DadO4I50Ngpe8XNWG3SaGTDfP3yPCyx8l7/+Ztw/U1lJ9GjGwZXI3HA== X-Gm-Gg: Acq92OFTknSBnJTzE+w4Lli29pXK6Carchch+JtYSoKEAN9MBUNX/2T0st8FlbY1pIk pi0mEb1J8fJ27sckPYHmOGXVEsAhBK9t8+Rj4gP1WlGuYzN+FMmKpeL3LZXDT7A+UUHjr+5cq35 Z/yTNREFwux5YdLESZl2EgNwHiNoaGQSoKS92ZY9vwLHLpG/8o78mnNs5l12Z2EVWw65E1ehb60 NCWzzSVlzEcYp8Vkwz5hO3ZwkOIcl5DFypOhs3gEyv46amwY1rJmt5apskNc8BvsZUnL/bWC26R +F8rWa8VGCELyMRZ9UukifuZQguM3th6prRWDz2WWu6d/vQJ6+ivN2gpPSJCthOF/D7/4iNjAtQ emwhBvRIYJWfcMvLfm10ZboSWwcCAJ2AYbVzBsfWNKDSlFWxDbuT69dtwT9RUvg4KNA8u/Zk740 w/JTEARG2ZHEv0al/laf9KFErB8Rjne1RuOXBvmFyCPYLI2zNHMsmGfjfQuxjMDTK7x116Kezbv rEq9YTSHTd7hk/CRk9dN8b5su1fq3wD X-Received: by 2002:a05:6808:4f61:b0:485:43ed:bd4d with SMTP id 5614622812f47-4865aad1ac7mr3172925b6e.33.1780522597864; Wed, 03 Jun 2026 14:36:37 -0700 (PDT) Received: from nathan (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id 5614622812f47-4865b91ead7sm2781624b6e.10.2026.06.03.14.36.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jun 2026 14:36:37 -0700 (PDT) Date: Wed, 3 Jun 2026 16:36:34 -0500 From: Nathan Bossart To: Jacob Champion Cc: pgsql-hackers@postgresql.org Subject: Re: future of PQfn() Message-ID: References: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="6CoALBM/+cswbGQ8" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --6CoALBM/+cswbGQ8 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline While the prepared statement deallocation idea bakes in the other thread, I thought I'd post a new patch set here. I've reordered things a bit and left out the conversion to prepared statements for now (although I do have a patch for that). 0001 removes PQfn() and changes all internal uses to PQnfn(). 0002 and 0003 are just some additional cleanup that I noticed as I've been working on this stuff. -- nathan --6CoALBM/+cswbGQ8 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0001-remove-PQfn.patch From 3d3a983333daa9e2d59887a5fdd7b8806d33c588 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Mon, 1 Jun 2026 16:55:00 -0500 Subject: [PATCH v3 1/3] remove PQfn --- doc/src/sgml/libpq.sgml | 117 +-------------------------------- src/backend/tcop/fastpath.c | 4 +- src/include/tcop/dest.h | 4 +- src/interfaces/libpq/fe-exec.c | 42 ++++++++++-- src/interfaces/libpq/fe-lobj.c | 38 +++++------ 5 files changed, 60 insertions(+), 145 deletions(-) diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 7d3c3bb66d8..123e7f03902 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -5887,7 +5887,7 @@ int PQflush(PGconn *conn); are permitted, command strings containing multiple SQL commands are disallowed, and so is COPY. Using synchronous command execution functions - such as PQfn, + such as PQexec, PQexecParams, PQprepare, @@ -7046,121 +7046,6 @@ int PQrequestCancel(PGconn *conn); - - The Fast-Path Interface - - - fast path - - - - PostgreSQL provides a fast-path interface - to send simple function calls to the server. - - - - - This interface is unsafe and should not be used. When - result_is_int is set to 0, - PQfn may write data beyond the end of - result_buf, regardless of whether the buffer has - enough space for the requested number of bytes. Furthermore, it is - obsolete, as one can achieve similar - performance and greater functionality by setting up a prepared - statement to define the function call. Then, executing the statement - with binary transmission of parameters and results substitutes for a - fast-path function call. - - - - - The function PQfnPQfn - requests execution of a server function via the fast-path interface: - -PGresult *PQfn(PGconn *conn, - int fnid, - int *result_buf, - int *result_len, - int result_is_int, - const PQArgBlock *args, - int nargs); - -typedef struct -{ - int len; - int isint; - union - { - int *ptr; - int integer; - } u; -} PQArgBlock; - - - - - The fnid argument is the OID of the function to be - executed. args and nargs define the - parameters to be passed to the function; they must match the declared - function argument list. When the isint field of a - parameter structure is true, the u.integer value is sent - to the server as an integer of the indicated length (this must be - 2 or 4 bytes); proper byte-swapping occurs. When isint - is false, the indicated number of bytes at *u.ptr are - sent with no processing; the data must be in the format expected by - the server for binary transmission of the function's argument data - type. (The declaration of u.ptr as being of - type int * is historical; it would be better to consider - it void *.) - result_buf points to the buffer in which to place - the function's return value. The caller must have allocated sufficient - space to store the return value. (There is no check!) The actual result - length in bytes will be returned in the integer pointed to by - result_len. If a 2- or 4-byte integer result - is expected, set result_is_int to 1, otherwise - set it to 0. Setting result_is_int to 1 causes - libpq to byte-swap the value if necessary, so that it - is delivered as a proper int value for the client machine; - note that a 4-byte integer is delivered into *result_buf - for either allowed result size. - When result_is_int is 0, the binary-format byte string - sent by the server is returned unmodified. (In this case it's better - to consider result_buf as being of - type void *.) - - - - PQfn always returns a valid - PGresult pointer, with - status PGRES_COMMAND_OK for success - or PGRES_FATAL_ERROR if some problem was encountered. - The result status should be - checked before the result is used. The caller is responsible for - freeing the PGresult with - when it is no longer needed. - - - - To pass a NULL argument to the function, set - the len field of that parameter structure - to -1; the isint - and u fields are then irrelevant. - - - - If the function returns NULL, *result_len is set - to -1, and *result_buf is not - modified. - - - - Note that it is not possible to handle set-valued results when using - this interface. Also, the function must be a plain function, not an - aggregate, window function, or procedure. - - - - Asynchronous Notification diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c index 52772bc90a8..5379e4ad9f5 100644 --- a/src/backend/tcop/fastpath.c +++ b/src/backend/tcop/fastpath.c @@ -11,7 +11,9 @@ * src/backend/tcop/fastpath.c * * NOTES - * This cruft is the server side of PQfn. + * This cruft is the server side of PQfn. libpq's PQfn() was retired in + * v20 and now always errors, but the server code is retained for the + * benefit of older clients. * *------------------------------------------------------------------------- */ diff --git a/src/include/tcop/dest.h b/src/include/tcop/dest.h index 103f27fc3cb..507414421ec 100644 --- a/src/include/tcop/dest.h +++ b/src/include/tcop/dest.h @@ -12,8 +12,8 @@ * * - a remote process is the destination when we are * running a backend with a frontend and the frontend executes - * PQexec() or PQfn(). In this case, the results are sent - * to the frontend via the functions in backend/libpq. + * PQexec(). In this case, the results are sent to the frontend via + * the functions in backend/libpq. * * - DestNone is the destination when the system executes * a query internally. The results are discarded. diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index 7b8edacbfde..2f034d70e65 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -2986,10 +2986,10 @@ PQendcopy(PGconn *conn) * nargs : # of arguments in args array. * * RETURNS - * PGresult with status = PGRES_COMMAND_OK if successful. - * *result_len is > 0 if there is a return value, 0 if not. - * PGresult with status = PGRES_FATAL_ERROR if backend returns an error. - * NULL on communications failure. conn->errorMessage will be set. + * This function was unsafe and is no longer supported, so it now always + * sets *result_len to 0 and returns a PGresult with status set to + * PGRES_FATAL_ERROR (unless the connection is in the wrong state, in + * which case it returns NULL). * ---------------- */ @@ -3002,15 +3002,43 @@ PQfn(PGconn *conn, const PQArgBlock *args, int nargs) { - return PQnfn(conn, fnid, result_buf, -1, result_len, - result_is_int, args, nargs); + *result_len = 0; + + if (!conn) + return NULL; + + /* + * Since this is the beginning of a query cycle, reset the error state. + * However, in pipeline mode with something already queued, the error + * buffer belongs to that command and we shouldn't clear it. + */ + if (conn->cmd_queue_head == NULL) + pqClearConnErrorState(conn); + + if (conn->pipelineStatus != PQ_PIPELINE_OFF) + { + libpq_append_conn_error(conn, "%s not allowed in pipeline mode", "PQfn"); + return NULL; + } + + if (conn->sock == PGINVALID_SOCKET || conn->asyncStatus != PGASYNC_IDLE || + pgHavePendingResult(conn)) + { + libpq_append_conn_error(conn, "connection in wrong state"); + return NULL; + } + + libpq_append_conn_error(conn, "PQfn() is no longer supported; use a prepared statement or PQexecParams() with binary results instead"); + pqSaveErrorResult(conn); + return pqPrepareAsyncResult(conn); } /* * PQnfn * Private version of PQfn() with verification that returned data fits in * result_buf when result_is_int == 0. Setting buf_size to -1 disables - * this verification. + * this verification. This is currently only used by the frontend LO + * interface and will hopefully be removed down the road. */ PGresult * PQnfn(PGconn *conn, int fnid, int *result_buf, int buf_size, int *result_len, diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c index 12a32fcbaf3..1660c969f58 100644 --- a/src/interfaces/libpq/fe-lobj.c +++ b/src/interfaces/libpq/fe-lobj.c @@ -72,7 +72,7 @@ lo_open(PGconn *conn, Oid lobjId, int mode) argv[1].len = 4; argv[1].u.integer = mode; - res = PQfn(conn, conn->lobjfuncs->fn_lo_open, &fd, &result_len, 1, argv, 2); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_open, &fd, -1, &result_len, 1, argv, 2); if (PQresultStatus(res) == PGRES_COMMAND_OK) { PQclear(res); @@ -106,8 +106,8 @@ lo_close(PGconn *conn, int fd) argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = fd; - res = PQfn(conn, conn->lobjfuncs->fn_lo_close, - &retval, &result_len, 1, argv, 1); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_close, + &retval, -1, &result_len, 1, argv, 1); if (PQresultStatus(res) == PGRES_COMMAND_OK) { PQclear(res); @@ -169,8 +169,8 @@ lo_truncate(PGconn *conn, int fd, size_t len) argv[1].len = 4; argv[1].u.integer = (int) len; - res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate, - &retval, &result_len, 1, argv, 2); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_truncate, + &retval, -1, &result_len, 1, argv, 2); if (PQresultStatus(res) == PGRES_COMMAND_OK) { @@ -218,8 +218,8 @@ lo_truncate64(PGconn *conn, int fd, int64_t len) argv[1].len = 8; argv[1].u.ptr = (int *) &len; - res = PQfn(conn, conn->lobjfuncs->fn_lo_truncate64, - &retval, &result_len, 1, argv, 2); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_truncate64, + &retval, -1, &result_len, 1, argv, 2); if (PQresultStatus(res) == PGRES_COMMAND_OK) { @@ -322,8 +322,8 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len) argv[1].len = (int) len; argv[1].u.ptr = (int *) unconstify(char *, buf); - res = PQfn(conn, conn->lobjfuncs->fn_lo_write, - &retval, &result_len, 1, argv, 2); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_write, + &retval, -1, &result_len, 1, argv, 2); if (PQresultStatus(res) == PGRES_COMMAND_OK) { PQclear(res); @@ -363,8 +363,8 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence) argv[2].len = 4; argv[2].u.integer = whence; - res = PQfn(conn, conn->lobjfuncs->fn_lo_lseek, - &retval, &result_len, 1, argv, 3); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_lseek, + &retval, -1, &result_len, 1, argv, 3); if (PQresultStatus(res) == PGRES_COMMAND_OK) { PQclear(res); @@ -448,8 +448,8 @@ lo_creat(PGconn *conn, int mode) argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = mode; - res = PQfn(conn, conn->lobjfuncs->fn_lo_creat, - &retval, &result_len, 1, argv, 1); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_creat, + &retval, -1, &result_len, 1, argv, 1); if (PQresultStatus(res) == PGRES_COMMAND_OK) { PQclear(res); @@ -492,8 +492,8 @@ lo_create(PGconn *conn, Oid lobjId) argv[0].isint = 1; argv[0].len = 4; argv[0].u.integer = lobjId; - res = PQfn(conn, conn->lobjfuncs->fn_lo_create, - &retval, &result_len, 1, argv, 1); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_create, + &retval, -1, &result_len, 1, argv, 1); if (PQresultStatus(res) == PGRES_COMMAND_OK) { PQclear(res); @@ -526,8 +526,8 @@ lo_tell(PGconn *conn, int fd) argv[0].len = 4; argv[0].u.integer = fd; - res = PQfn(conn, conn->lobjfuncs->fn_lo_tell, - &retval, &result_len, 1, argv, 1); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_tell, + &retval, -1, &result_len, 1, argv, 1); if (PQresultStatus(res) == PGRES_COMMAND_OK) { PQclear(res); @@ -600,8 +600,8 @@ lo_unlink(PGconn *conn, Oid lobjId) argv[0].len = 4; argv[0].u.integer = lobjId; - res = PQfn(conn, conn->lobjfuncs->fn_lo_unlink, - &retval, &result_len, 1, argv, 1); + res = PQnfn(conn, conn->lobjfuncs->fn_lo_unlink, + &retval, -1, &result_len, 1, argv, 1); if (PQresultStatus(res) == PGRES_COMMAND_OK) { PQclear(res); -- 2.50.1 (Apple Git-155) --6CoALBM/+cswbGQ8 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0002-remove-lo_hton64-and-lo_ntoh64.patch From 8b03849dadebe8d6c31be83b2ab3f5c8736adb32 Mon Sep 17 00:00:00 2001 From: Reviewer Date: Tue, 2 Jun 2026 17:22:48 +0000 Subject: [PATCH v3 2/3] remove lo_hton64() and lo_ntoh64() --- src/interfaces/libpq/fe-lobj.c | 58 +++------------------------------- 1 file changed, 4 insertions(+), 54 deletions(-) diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c index 1660c969f58..42b2a36bda9 100644 --- a/src/interfaces/libpq/fe-lobj.c +++ b/src/interfaces/libpq/fe-lobj.c @@ -43,8 +43,6 @@ static int lo_initialize(PGconn *conn); static Oid lo_import_internal(PGconn *conn, const char *filename, Oid oid); -static int64_t lo_hton64(int64_t host64); -static int64_t lo_ntoh64(int64_t net64); /* * lo_open @@ -213,7 +211,7 @@ lo_truncate64(PGconn *conn, int fd, int64_t len) argv[0].len = 4; argv[0].u.integer = fd; - len = lo_hton64(len); + len = pg_hton64(len); argv[1].isint = 0; argv[1].len = 8; argv[1].u.ptr = (int *) &len; @@ -403,7 +401,7 @@ lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence) argv[0].len = 4; argv[0].u.integer = fd; - offset = lo_hton64(offset); + offset = pg_hton64(offset); argv[1].isint = 0; argv[1].len = 8; argv[1].u.ptr = (int *) &offset; @@ -417,7 +415,7 @@ lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence) if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8) { PQclear(res); - return lo_ntoh64(retval); + return pg_ntoh64(retval); } else { @@ -571,7 +569,7 @@ lo_tell64(PGconn *conn, int fd) if (PQresultStatus(res) == PGRES_COMMAND_OK && result_len == 8) { PQclear(res); - return lo_ntoh64(retval); + return pg_ntoh64(retval); } else { @@ -1014,51 +1012,3 @@ lo_initialize(PGconn *conn) conn->lobjfuncs = lobjfuncs; return 0; } - -/* - * lo_hton64 - * converts a 64-bit integer from host byte order to network byte order - */ -static int64_t -lo_hton64(int64_t host64) -{ - union - { - int64 i64; - uint32 i32[2]; - } swap; - uint32 t; - - /* High order half first, since we're doing MSB-first */ - t = (uint32) (host64 >> 32); - swap.i32[0] = pg_hton32(t); - - /* Now the low order half */ - t = (uint32) host64; - swap.i32[1] = pg_hton32(t); - - return swap.i64; -} - -/* - * lo_ntoh64 - * converts a 64-bit integer from network byte order to host byte order - */ -static int64_t -lo_ntoh64(int64_t net64) -{ - union - { - int64 i64; - uint32 i32[2]; - } swap; - int64 result; - - swap.i64 = net64; - - result = (uint32) pg_ntoh32(swap.i32[0]); - result <<= 32; - result |= (uint32) pg_ntoh32(swap.i32[1]); - - return result; -} -- 2.50.1 (Apple Git-155) --6CoALBM/+cswbGQ8 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=v3-0003-add-helper-functions-for-fast-path-arg-setup.patch From e5b1df7a69d0d0f1798ce0dc2beb18fedfdfd081 Mon Sep 17 00:00:00 2001 From: Reviewer Date: Tue, 2 Jun 2026 18:24:30 +0000 Subject: [PATCH v3 3/3] add helper functions for fast-path arg setup --- src/interfaces/libpq/fe-lobj.c | 104 ++++++++++++--------------------- 1 file changed, 38 insertions(+), 66 deletions(-) diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c index 42b2a36bda9..8802c6f8098 100644 --- a/src/interfaces/libpq/fe-lobj.c +++ b/src/interfaces/libpq/fe-lobj.c @@ -44,6 +44,22 @@ static int lo_initialize(PGconn *conn); static Oid lo_import_internal(PGconn *conn, const char *filename, Oid oid); +static inline void +lo_set_int_arg(PQArgBlock *arg, int value) +{ + arg->isint = 1; + arg->len = 4; + arg->u.integer = value; +} + +static inline void +lo_set_ptr_arg(PQArgBlock *arg, const void *ptr, int len) +{ + arg->isint = 0; + arg->len = len; + arg->u.ptr = (int *) unconstify(void *, ptr); +} + /* * lo_open * opens an existing large object @@ -62,13 +78,9 @@ lo_open(PGconn *conn, Oid lobjId, int mode) if (lo_initialize(conn) < 0) return -1; - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = lobjId; + lo_set_int_arg(&argv[0], lobjId); - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = mode; + lo_set_int_arg(&argv[1], mode); res = PQnfn(conn, conn->lobjfuncs->fn_lo_open, &fd, -1, &result_len, 1, argv, 2); if (PQresultStatus(res) == PGRES_COMMAND_OK) @@ -101,9 +113,7 @@ lo_close(PGconn *conn, int fd) if (lo_initialize(conn) < 0) return -1; - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + lo_set_int_arg(&argv[0], fd); res = PQnfn(conn, conn->lobjfuncs->fn_lo_close, &retval, -1, &result_len, 1, argv, 1); if (PQresultStatus(res) == PGRES_COMMAND_OK) @@ -159,13 +169,9 @@ lo_truncate(PGconn *conn, int fd, size_t len) return -1; } - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + lo_set_int_arg(&argv[0], fd); - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = (int) len; + lo_set_int_arg(&argv[1], (int) len); res = PQnfn(conn, conn->lobjfuncs->fn_lo_truncate, &retval, -1, &result_len, 1, argv, 2); @@ -207,14 +213,10 @@ lo_truncate64(PGconn *conn, int fd, int64_t len) return -1; } - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + lo_set_int_arg(&argv[0], fd); len = pg_hton64(len); - argv[1].isint = 0; - argv[1].len = 8; - argv[1].u.ptr = (int *) &len; + lo_set_ptr_arg(&argv[1], &len, 8); res = PQnfn(conn, conn->lobjfuncs->fn_lo_truncate64, &retval, -1, &result_len, 1, argv, 2); @@ -261,13 +263,9 @@ lo_read(PGconn *conn, int fd, char *buf, size_t len) return -1; } - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + lo_set_int_arg(&argv[0], fd); - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = (int) len; + lo_set_int_arg(&argv[1], (int) len); res = PQnfn(conn, conn->lobjfuncs->fn_lo_read, (void *) buf, len, &result_len, 0, argv, 2); @@ -312,13 +310,9 @@ lo_write(PGconn *conn, int fd, const char *buf, size_t len) return -1; } - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + lo_set_int_arg(&argv[0], fd); - argv[1].isint = 0; - argv[1].len = (int) len; - argv[1].u.ptr = (int *) unconstify(char *, buf); + lo_set_ptr_arg(&argv[1], buf, (int) len); res = PQnfn(conn, conn->lobjfuncs->fn_lo_write, &retval, -1, &result_len, 1, argv, 2); @@ -349,17 +343,11 @@ lo_lseek(PGconn *conn, int fd, int offset, int whence) if (lo_initialize(conn) < 0) return -1; - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + lo_set_int_arg(&argv[0], fd); - argv[1].isint = 1; - argv[1].len = 4; - argv[1].u.integer = offset; + lo_set_int_arg(&argv[1], offset); - argv[2].isint = 1; - argv[2].len = 4; - argv[2].u.integer = whence; + lo_set_int_arg(&argv[2], whence); res = PQnfn(conn, conn->lobjfuncs->fn_lo_lseek, &retval, -1, &result_len, 1, argv, 3); @@ -397,18 +385,12 @@ lo_lseek64(PGconn *conn, int fd, int64_t offset, int whence) return -1; } - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + lo_set_int_arg(&argv[0], fd); offset = pg_hton64(offset); - argv[1].isint = 0; - argv[1].len = 8; - argv[1].u.ptr = (int *) &offset; + lo_set_ptr_arg(&argv[1], &offset, 8); - argv[2].isint = 1; - argv[2].len = 4; - argv[2].u.integer = whence; + lo_set_int_arg(&argv[2], whence); res = PQnfn(conn, conn->lobjfuncs->fn_lo_lseek64, (void *) &retval, sizeof(retval), &result_len, 0, argv, 3); @@ -443,9 +425,7 @@ lo_creat(PGconn *conn, int mode) if (lo_initialize(conn) < 0) return InvalidOid; - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = mode; + lo_set_int_arg(&argv[0], mode); res = PQnfn(conn, conn->lobjfuncs->fn_lo_creat, &retval, -1, &result_len, 1, argv, 1); if (PQresultStatus(res) == PGRES_COMMAND_OK) @@ -487,9 +467,7 @@ lo_create(PGconn *conn, Oid lobjId) return InvalidOid; } - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = lobjId; + lo_set_int_arg(&argv[0], lobjId); res = PQnfn(conn, conn->lobjfuncs->fn_lo_create, &retval, -1, &result_len, 1, argv, 1); if (PQresultStatus(res) == PGRES_COMMAND_OK) @@ -520,9 +498,7 @@ lo_tell(PGconn *conn, int fd) if (lo_initialize(conn) < 0) return -1; - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + lo_set_int_arg(&argv[0], fd); res = PQnfn(conn, conn->lobjfuncs->fn_lo_tell, &retval, -1, &result_len, 1, argv, 1); @@ -560,9 +536,7 @@ lo_tell64(PGconn *conn, int fd) return -1; } - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = fd; + lo_set_int_arg(&argv[0], fd); res = PQnfn(conn, conn->lobjfuncs->fn_lo_tell64, (void *) &retval, sizeof(retval), &result_len, 0, argv, 1); @@ -594,9 +568,7 @@ lo_unlink(PGconn *conn, Oid lobjId) if (lo_initialize(conn) < 0) return -1; - argv[0].isint = 1; - argv[0].len = 4; - argv[0].u.integer = lobjId; + lo_set_int_arg(&argv[0], lobjId); res = PQnfn(conn, conn->lobjfuncs->fn_lo_unlink, &retval, -1, &result_len, 1, argv, 1); -- 2.50.1 (Apple Git-155) --6CoALBM/+cswbGQ8--