0002-pset-options-for-slash-g-1.patch
text/x-diff
Filename: 0002-pset-options-for-slash-g-1.patch
Type: text/x-diff
Part: 1
Message:
Re: proposal \gcsv
Patch
Format: unified
Series: patch 0002
| File | + | − |
|---|---|---|
| src/bin/psql/command.c | 102 | 10 |
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 1055af5..933e181 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -86,6 +86,10 @@ static backslashResult exec_command_errverbose(PsqlScanState scan_state, bool ac
static backslashResult exec_command_f(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_g(PsqlScanState scan_state, bool active_branch,
const char *cmd);
+static backslashResult process_command_g_options(char *first_option,
+ PsqlScanState scan_state,
+ bool active_branch,
+ const char *cmd);
static backslashResult exec_command_gdesc(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_gexec(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_gset(PsqlScanState scan_state, bool active_branch);
@@ -1280,19 +1284,40 @@ exec_command_f(PsqlScanState scan_state, bool active_branch)
}
/*
- * \g [filename] -- send query, optionally with output to file/pipe
- * \gx [filename] -- same as \g, with expanded mode forced
+ * \g [(pset-option[=pset-value] ...)] [filename/shell-command]
+ * \gx [(pset-option[=pset-value] ...)] [filename/shell-command]
+ *
+ * Send the current query. If pset options are specified, they are made
+ * active just for this query. If a filename or pipe command is given,
+ * the query output goes there. \gx implicitly forces expanded = 1 along
+ * with any other pset options that are specified.
*/
static backslashResult
exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
{
backslashResult status = PSQL_CMD_SKIP_LINE;
+ char *fname;
- if (active_branch)
+ /*
+ * Because the option processing for this is fairly complicated, we do it
+ * and then decide whether the branch is active.
+ */
+ fname = psql_scan_slash_option(scan_state,
+ OT_FILEPIPE, NULL, false);
+
+ if (fname && fname[0] == '(')
{
- char *fname = psql_scan_slash_option(scan_state,
- OT_FILEPIPE, NULL, false);
+ /* Consume pset options through trailing ')' ... */
+ status = process_command_g_options(fname + 1, scan_state,
+ active_branch, cmd);
+ free(fname);
+ /* ... and again attempt to scan the filename. */
+ fname = psql_scan_slash_option(scan_state,
+ OT_FILEPIPE, NULL, false);
+ }
+ if (status == PSQL_CMD_SKIP_LINE && active_branch)
+ {
if (!fname)
pset.gfname = NULL;
else
@@ -1300,22 +1325,89 @@ exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
expand_tilde(&fname);
pset.gfname = pg_strdup(fname);
}
- free(fname);
if (strcmp(cmd, "gx") == 0)
{
- /* save settings, then force expanded = 1 */
- pset.gsavepopt = savePsetInfo(&pset.popt);
+ /* save settings if not done already, then force expanded = 1 */
+ if (pset.gsavepopt == NULL)
+ pset.gsavepopt = savePsetInfo(&pset.popt);
pset.popt.topt.expanded = 1;
}
status = PSQL_CMD_SEND;
}
- else
- ignore_slash_filepipe(scan_state);
+
+ free(fname);
return status;
}
/*
+ * Process parenthesized pset options for \g
+ */
+static backslashResult
+process_command_g_options(char *first_option, PsqlScanState scan_state,
+ bool active_branch, const char *cmd)
+{
+ bool success = true;
+ bool found_r_paren = false;
+
+ do
+ {
+ char *option;
+ size_t optlen;
+
+ /* If not first time through, collect a new option */
+ if (first_option)
+ option = first_option;
+ else
+ {
+ option = psql_scan_slash_option(scan_state,
+ OT_NORMAL, NULL, false);
+ if (!option)
+ {
+ if (active_branch)
+ {
+ pg_log_error("\\%s: missing right parenthesis", cmd);
+ success = false;
+ }
+ break;
+ }
+ }
+
+ /* Check for terminating right paren, and remove it from string */
+ optlen = strlen(option);
+ if (optlen > 0 && option[optlen - 1] == ')')
+ {
+ option[--optlen] = '\0';
+ found_r_paren = true;
+ }
+
+ /* If there was anything besides right paren, parse/execute it */
+ if (optlen > 0)
+ {
+ char *valptr = strchr(option, '=');
+
+ if (valptr)
+ *valptr++ = '\0';
+ if (active_branch)
+ {
+ /* save settings if not done already, then apply option */
+ if (pset.gsavepopt == NULL)
+ pset.gsavepopt = savePsetInfo(&pset.popt);
+ success &= do_pset(option, valptr, &pset.popt, true);
+ }
+ }
+
+ /* Clean up after this option. We should not free first_option. */
+ if (first_option)
+ first_option = NULL;
+ else
+ free(option);
+ } while (!found_r_paren);
+
+ return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
+}
+
+/*
* \gdesc -- describe query result
*/
static backslashResult