aboutsummaryrefslogtreecommitdiff
path: root/src/bin/psql/common.c
diff options
context:
space:
mode:
authorMichael Paquier <michael@paquier.xyz>2024-08-22 16:25:57 +0900
committerMichael Paquier <michael@paquier.xyz>2024-08-22 16:25:57 +0900
commitd55322b0da60a8798ffdb8b78ef90db0fb5be18e (patch)
treed6d5ff5ec0fe3f7d8c49d38357529f113ef617d3 /src/bin/psql/common.c
parenta36aa223ec447276bf7050ab9ec6d974cafdf6c4 (diff)
downloadpostgresql-d55322b0da60a8798ffdb8b78ef90db0fb5be18e.tar.gz
postgresql-d55322b0da60a8798ffdb8b78ef90db0fb5be18e.zip
psql: Add more meta-commands able to use the extended protocol
Currently, only unnamed prepared statement are supported by psql with the meta-command \bind. With only this command, it is not possible to test named statement creation, execution or close through the extended protocol. This commit introduces three additional commands: * \parse creates a prepared statement using the extended protocol, acting as a wrapper of libpq's PQsendPrepare(). * \bind_named binds and executes an existing prepared statement using the extended protocol, for PQsendQueryPrepared(). * \close closes an existing prepared statement using the extended protocol, for PQsendClosePrepared(). This is going to be useful to add regression tests for the extended query protocol, and I have some plans for that on separate threads. Note that \bind relies on PQsendQueryParams(). The code of psql is refactored so as bind_flag is replaced by an enum in _psqlSettings that tracks the type of libpq routine to execute, based on the meta-command involved, with the default being PQsendQuery(). This refactoring piece has been written by me, while Anthonin has implemented the rest. Author: Anthonin Bonnefoy, Michael Paquier Reviewed-by: Aleksander Alekseev, Jelte Fennema-Nio Discussion: https://postgr.es/m/CAO6_XqpSq0Q0kQcVLCbtagY94V2GxNP3zCnR6WnOM8WqXPK4nw@mail.gmail.com
Diffstat (limited to 'src/bin/psql/common.c')
-rw-r--r--src/bin/psql/common.c59
1 files changed, 47 insertions, 12 deletions
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index fe8e049c4c1..be265aa05a4 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -1274,15 +1274,28 @@ sendquery_cleanup:
pset.gsavepopt = NULL;
}
- /* clean up after \bind */
- if (pset.bind_flag)
+ /* clean up after extended protocol queries */
+ switch (pset.send_mode)
{
- for (i = 0; i < pset.bind_nparams; i++)
- free(pset.bind_params[i]);
- free(pset.bind_params);
- pset.bind_params = NULL;
- pset.bind_flag = false;
+ case PSQL_SEND_EXTENDED_CLOSE: /* \close */
+ free(pset.stmtName);
+ break;
+ case PSQL_SEND_EXTENDED_PARSE: /* \parse */
+ free(pset.stmtName);
+ break;
+ case PSQL_SEND_EXTENDED_QUERY_PARAMS: /* \bind */
+ case PSQL_SEND_EXTENDED_QUERY_PREPARED: /* \bind_named */
+ for (i = 0; i < pset.bind_nparams; i++)
+ free(pset.bind_params[i]);
+ free(pset.bind_params);
+ free(pset.stmtName);
+ pset.bind_params = NULL;
+ break;
+ case PSQL_SEND_QUERY:
+ break;
}
+ pset.stmtName = NULL;
+ pset.send_mode = PSQL_SEND_QUERY;
/* reset \gset trigger */
if (pset.gset_prefix)
@@ -1456,7 +1469,7 @@ ExecQueryAndProcessResults(const char *query,
const printQueryOpt *opt, FILE *printQueryFout)
{
bool timing = pset.timing;
- bool success;
+ bool success = false;
bool return_early = false;
instr_time before,
after;
@@ -1469,10 +1482,32 @@ ExecQueryAndProcessResults(const char *query,
else
INSTR_TIME_SET_ZERO(before);
- if (pset.bind_flag)
- success = PQsendQueryParams(pset.db, query, pset.bind_nparams, NULL, (const char *const *) pset.bind_params, NULL, NULL, 0);
- else
- success = PQsendQuery(pset.db, query);
+ switch (pset.send_mode)
+ {
+ case PSQL_SEND_EXTENDED_CLOSE:
+ success = PQsendClosePrepared(pset.db, pset.stmtName);
+ break;
+ case PSQL_SEND_EXTENDED_PARSE:
+ success = PQsendPrepare(pset.db, pset.stmtName, query, 0, NULL);
+ break;
+ case PSQL_SEND_EXTENDED_QUERY_PARAMS:
+ Assert(pset.stmtName == NULL);
+ success = PQsendQueryParams(pset.db, query,
+ pset.bind_nparams, NULL,
+ (const char *const *) pset.bind_params,
+ NULL, NULL, 0);
+ break;
+ case PSQL_SEND_EXTENDED_QUERY_PREPARED:
+ Assert(pset.stmtName != NULL);
+ success = PQsendQueryPrepared(pset.db, pset.stmtName,
+ pset.bind_nparams,
+ (const char *const *) pset.bind_params,
+ NULL, NULL, 0);
+ break;
+ case PSQL_SEND_QUERY:
+ success = PQsendQuery(pset.db, query);
+ break;
+ }
if (!success)
{