Commit ca4e20fd authored by Tom Lane's avatar Tom Lane

Merge duplicative code for \sf/\sv, \ef/\ev in psql/command.c.

Saves ~150 lines, costs little.

Fabien Coelho, reviewed by Victor Drobny

Discussion: https://postgr.es/m/alpine.DEB.2.20.1703311958001.14355@lancre
parent 5b6d13ee
...@@ -71,10 +71,8 @@ static backslashResult exec_command_d(PsqlScanState scan_state, bool active_bran ...@@ -71,10 +71,8 @@ static backslashResult exec_command_d(PsqlScanState scan_state, bool active_bran
const char *cmd); const char *cmd);
static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch, static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch,
PQExpBuffer query_buf, PQExpBuffer previous_buf); PQExpBuffer query_buf, PQExpBuffer previous_buf);
static backslashResult exec_command_ef(PsqlScanState scan_state, bool active_branch, static backslashResult exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
PQExpBuffer query_buf); PQExpBuffer query_buf, bool is_func);
static backslashResult exec_command_ev(PsqlScanState scan_state, bool active_branch,
PQExpBuffer query_buf);
static backslashResult exec_command_echo(PsqlScanState scan_state, bool active_branch, static backslashResult exec_command_echo(PsqlScanState scan_state, bool active_branch,
const char *cmd); const char *cmd);
static backslashResult exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack, static backslashResult exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
...@@ -115,10 +113,8 @@ static backslashResult exec_command_s(PsqlScanState scan_state, bool active_bran ...@@ -115,10 +113,8 @@ static backslashResult exec_command_s(PsqlScanState scan_state, bool active_bran
static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch, static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch,
const char *cmd); const char *cmd);
static backslashResult exec_command_sf(PsqlScanState scan_state, bool active_branch, static backslashResult exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
const char *cmd); const char *cmd, bool is_func);
static backslashResult exec_command_sv(PsqlScanState scan_state, bool active_branch,
const char *cmd);
static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch);
...@@ -319,9 +315,9 @@ exec_command(const char *cmd, ...@@ -319,9 +315,9 @@ exec_command(const char *cmd,
status = exec_command_edit(scan_state, active_branch, status = exec_command_edit(scan_state, active_branch,
query_buf, previous_buf); query_buf, previous_buf);
else if (strcmp(cmd, "ef") == 0) else if (strcmp(cmd, "ef") == 0)
status = exec_command_ef(scan_state, active_branch, query_buf); status = exec_command_ef_ev(scan_state, active_branch, query_buf, true);
else if (strcmp(cmd, "ev") == 0) else if (strcmp(cmd, "ev") == 0)
status = exec_command_ev(scan_state, active_branch, query_buf); status = exec_command_ef_ev(scan_state, active_branch, query_buf, false);
else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0) else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
status = exec_command_echo(scan_state, active_branch, cmd); status = exec_command_echo(scan_state, active_branch, cmd);
else if (strcmp(cmd, "elif") == 0) else if (strcmp(cmd, "elif") == 0)
...@@ -380,9 +376,9 @@ exec_command(const char *cmd, ...@@ -380,9 +376,9 @@ exec_command(const char *cmd,
else if (strcmp(cmd, "setenv") == 0) else if (strcmp(cmd, "setenv") == 0)
status = exec_command_setenv(scan_state, active_branch, cmd); status = exec_command_setenv(scan_state, active_branch, cmd);
else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0) else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
status = exec_command_sf(scan_state, active_branch, cmd); status = exec_command_sf_sv(scan_state, active_branch, cmd, true);
else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0) else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0)
status = exec_command_sv(scan_state, active_branch, cmd); status = exec_command_sf_sv(scan_state, active_branch, cmd, false);
else if (strcmp(cmd, "t") == 0) else if (strcmp(cmd, "t") == 0)
status = exec_command_t(scan_state, active_branch); status = exec_command_t(scan_state, active_branch);
else if (strcmp(cmd, "T") == 0) else if (strcmp(cmd, "T") == 0)
...@@ -979,28 +975,34 @@ exec_command_edit(PsqlScanState scan_state, bool active_branch, ...@@ -979,28 +975,34 @@ exec_command_edit(PsqlScanState scan_state, bool active_branch,
} }
/* /*
* \ef -- edit the named function, or present a blank CREATE FUNCTION * \ef/\ev -- edit the named function/view, or
* template if no argument is given * present a blank CREATE FUNCTION/VIEW template if no argument is given
*/ */
static backslashResult static backslashResult
exec_command_ef(PsqlScanState scan_state, bool active_branch, exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
PQExpBuffer query_buf) PQExpBuffer query_buf, bool is_func)
{ {
backslashResult status = PSQL_CMD_SKIP_LINE; backslashResult status = PSQL_CMD_SKIP_LINE;
if (active_branch) if (active_branch)
{ {
char *func = psql_scan_slash_option(scan_state, char *obj_desc = psql_scan_slash_option(scan_state,
OT_WHOLE_LINE, NULL, true); OT_WHOLE_LINE,
NULL, true);
int lineno = -1; int lineno = -1;
if (pset.sversion < 80400) if (pset.sversion < (is_func ? 80400 : 70400))
{ {
char sverbuf[32]; char sverbuf[32];
psql_error("The server (version %s) does not support editing function source.\n",
formatPGVersionNumber(pset.sversion, false, formatPGVersionNumber(pset.sversion, false,
sverbuf, sizeof(sverbuf))); sverbuf, sizeof(sverbuf));
if (is_func)
psql_error("The server (version %s) does not support editing function source.\n",
sverbuf);
else
psql_error("The server (version %s) does not support editing view definitions.\n",
sverbuf);
status = PSQL_CMD_ERROR; status = PSQL_CMD_ERROR;
} }
else if (!query_buf) else if (!query_buf)
...@@ -1010,36 +1012,44 @@ exec_command_ef(PsqlScanState scan_state, bool active_branch, ...@@ -1010,36 +1012,44 @@ exec_command_ef(PsqlScanState scan_state, bool active_branch,
} }
else else
{ {
Oid foid = InvalidOid; Oid obj_oid = InvalidOid;
EditableObjectType eot = is_func ? EditableFunction : EditableView;
lineno = strip_lineno_from_objdesc(func); lineno = strip_lineno_from_objdesc(obj_desc);
if (lineno == 0) if (lineno == 0)
{ {
/* error already reported */ /* error already reported */
status = PSQL_CMD_ERROR; status = PSQL_CMD_ERROR;
} }
else if (!func) else if (!obj_desc)
{ {
/* set up an empty command to fill in */ /* set up an empty command to fill in */
printfPQExpBuffer(query_buf, resetPQExpBuffer(query_buf);
if (is_func)
appendPQExpBufferStr(query_buf,
"CREATE FUNCTION ( )\n" "CREATE FUNCTION ( )\n"
" RETURNS \n" " RETURNS \n"
" LANGUAGE \n" " LANGUAGE \n"
" -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n" " -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n"
"AS $function$\n" "AS $function$\n"
"\n$function$\n"); "\n$function$\n");
else
appendPQExpBufferStr(query_buf,
"CREATE VIEW AS\n"
" SELECT \n"
" -- something...\n");
} }
else if (!lookup_object_oid(EditableFunction, func, &foid)) else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
{ {
/* error already reported */ /* error already reported */
status = PSQL_CMD_ERROR; status = PSQL_CMD_ERROR;
} }
else if (!get_create_object_cmd(EditableFunction, foid, query_buf)) else if (!get_create_object_cmd(eot, obj_oid, query_buf))
{ {
/* error already reported */ /* error already reported */
status = PSQL_CMD_ERROR; status = PSQL_CMD_ERROR;
} }
else if (lineno > 0) else if (is_func && lineno > 0)
{ {
/* /*
* lineno "1" should correspond to the first line of the * lineno "1" should correspond to the first line of the
...@@ -1078,89 +1088,8 @@ exec_command_ef(PsqlScanState scan_state, bool active_branch, ...@@ -1078,89 +1088,8 @@ exec_command_ef(PsqlScanState scan_state, bool active_branch,
status = PSQL_CMD_NEWEDIT; status = PSQL_CMD_NEWEDIT;
} }
if (func) if (obj_desc)
free(func); free(obj_desc);
}
else
ignore_slash_whole_line(scan_state);
return status;
}
/*
* \ev -- edit the named view, or present a blank CREATE VIEW
* template if no argument is given
*/
static backslashResult
exec_command_ev(PsqlScanState scan_state, bool active_branch,
PQExpBuffer query_buf)
{
backslashResult status = PSQL_CMD_SKIP_LINE;
if (active_branch)
{
char *view = psql_scan_slash_option(scan_state,
OT_WHOLE_LINE, NULL, true);
int lineno = -1;
if (pset.sversion < 70400)
{
char sverbuf[32];
psql_error("The server (version %s) does not support editing view definitions.\n",
formatPGVersionNumber(pset.sversion, false,
sverbuf, sizeof(sverbuf)));
status = PSQL_CMD_ERROR;
}
else if (!query_buf)
{
psql_error("no query buffer\n");
status = PSQL_CMD_ERROR;
}
else
{
Oid view_oid = InvalidOid;
lineno = strip_lineno_from_objdesc(view);
if (lineno == 0)
{
/* error already reported */
status = PSQL_CMD_ERROR;
}
else if (!view)
{
/* set up an empty command to fill in */
printfPQExpBuffer(query_buf,
"CREATE VIEW AS\n"
" SELECT \n"
" -- something...\n");
}
else if (!lookup_object_oid(EditableView, view, &view_oid))
{
/* error already reported */
status = PSQL_CMD_ERROR;
}
else if (!get_create_object_cmd(EditableView, view_oid, query_buf))
{
/* error already reported */
status = PSQL_CMD_ERROR;
}
}
if (status != PSQL_CMD_ERROR)
{
bool edited = false;
if (!do_edit(NULL, query_buf, lineno, &edited))
status = PSQL_CMD_ERROR;
else if (!edited)
puts(_("No changes"));
else
status = PSQL_CMD_NEWEDIT;
}
if (view)
free(view);
} }
else else
ignore_slash_whole_line(scan_state); ignore_slash_whole_line(scan_state);
...@@ -2234,43 +2163,53 @@ exec_command_setenv(PsqlScanState scan_state, bool active_branch, ...@@ -2234,43 +2163,53 @@ exec_command_setenv(PsqlScanState scan_state, bool active_branch,
} }
/* /*
* \sf -- show a function's source code * \sf/\sv -- show a function/view's source code
*/ */
static backslashResult static backslashResult
exec_command_sf(PsqlScanState scan_state, bool active_branch, const char *cmd) exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
const char *cmd, bool is_func)
{ {
backslashResult status = PSQL_CMD_SKIP_LINE; backslashResult status = PSQL_CMD_SKIP_LINE;
if (active_branch) if (active_branch)
{ {
bool show_linenumbers = (strcmp(cmd, "sf+") == 0); bool show_linenumbers = (strchr(cmd, '+') != NULL);
PQExpBuffer func_buf; PQExpBuffer buf;
char *func; char *obj_desc;
Oid foid = InvalidOid; Oid obj_oid = InvalidOid;
EditableObjectType eot = is_func ? EditableFunction : EditableView;
func_buf = createPQExpBuffer(); buf = createPQExpBuffer();
func = psql_scan_slash_option(scan_state, obj_desc = psql_scan_slash_option(scan_state,
OT_WHOLE_LINE, NULL, true); OT_WHOLE_LINE, NULL, true);
if (pset.sversion < 80400) if (pset.sversion < (is_func ? 80400 : 70400))
{ {
char sverbuf[32]; char sverbuf[32];
psql_error("The server (version %s) does not support showing function source.\n",
formatPGVersionNumber(pset.sversion, false, formatPGVersionNumber(pset.sversion, false,
sverbuf, sizeof(sverbuf))); sverbuf, sizeof(sverbuf));
if (is_func)
psql_error("The server (version %s) does not support showing function source.\n",
sverbuf);
else
psql_error("The server (version %s) does not support showing view definitions.\n",
sverbuf);
status = PSQL_CMD_ERROR; status = PSQL_CMD_ERROR;
} }
else if (!func) else if (!obj_desc)
{ {
if (is_func)
psql_error("function name is required\n"); psql_error("function name is required\n");
else
psql_error("view name is required\n");
status = PSQL_CMD_ERROR; status = PSQL_CMD_ERROR;
} }
else if (!lookup_object_oid(EditableFunction, func, &foid)) else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
{ {
/* error already reported */ /* error already reported */
status = PSQL_CMD_ERROR; status = PSQL_CMD_ERROR;
} }
else if (!get_create_object_cmd(EditableFunction, foid, func_buf)) else if (!get_create_object_cmd(eot, obj_oid, buf))
{ {
/* error already reported */ /* error already reported */
status = PSQL_CMD_ERROR; status = PSQL_CMD_ERROR;
...@@ -2284,7 +2223,7 @@ exec_command_sf(PsqlScanState scan_state, bool active_branch, const char *cmd) ...@@ -2284,7 +2223,7 @@ exec_command_sf(PsqlScanState scan_state, bool active_branch, const char *cmd)
if (pset.queryFout == stdout) if (pset.queryFout == stdout)
{ {
/* count lines in function to see if pager is needed */ /* count lines in function to see if pager is needed */
int lineno = count_lines_in_buf(func_buf); int lineno = count_lines_in_buf(buf);
output = PageOutput(lineno, &(pset.popt.topt)); output = PageOutput(lineno, &(pset.popt.topt));
is_pager = true; is_pager = true;
...@@ -2299,115 +2238,28 @@ exec_command_sf(PsqlScanState scan_state, bool active_branch, const char *cmd) ...@@ -2299,115 +2238,28 @@ exec_command_sf(PsqlScanState scan_state, bool active_branch, const char *cmd)
if (show_linenumbers) if (show_linenumbers)
{ {
/* /*
* lineno "1" should correspond to the first line of the * For functions, lineno "1" should correspond to the first
* function body. We expect that pg_get_functiondef() will * line of the function body. We expect that
* emit that on a line beginning with "AS ", and that there * pg_get_functiondef() will emit that on a line beginning
* can be no such line before the real start of the function * with "AS ", and that there can be no such line before the
* body. * real start of the function body.
*/ */
print_with_linenumbers(output, func_buf->data, "AS "); print_with_linenumbers(output, buf->data,
} is_func ? "AS " : NULL);
else
{
/* just send the function definition to output */
fputs(func_buf->data, output);
}
if (is_pager)
ClosePager(output);
}
if (func)
free(func);
destroyPQExpBuffer(func_buf);
}
else
ignore_slash_whole_line(scan_state);
return status;
}
/*
* \sv -- show a view's source code
*/
static backslashResult
exec_command_sv(PsqlScanState scan_state, bool active_branch, const char *cmd)
{
backslashResult status = PSQL_CMD_SKIP_LINE;
if (active_branch)
{
bool show_linenumbers = (strcmp(cmd, "sv+") == 0);
PQExpBuffer view_buf;
char *view;
Oid view_oid = InvalidOid;
view_buf = createPQExpBuffer();
view = psql_scan_slash_option(scan_state,
OT_WHOLE_LINE, NULL, true);
if (pset.sversion < 70400)
{
char sverbuf[32];
psql_error("The server (version %s) does not support showing view definitions.\n",
formatPGVersionNumber(pset.sversion, false,
sverbuf, sizeof(sverbuf)));
status = PSQL_CMD_ERROR;
}
else if (!view)
{
psql_error("view name is required\n");
status = PSQL_CMD_ERROR;
}
else if (!lookup_object_oid(EditableView, view, &view_oid))
{
/* error already reported */
status = PSQL_CMD_ERROR;
}
else if (!get_create_object_cmd(EditableView, view_oid, view_buf))
{
/* error already reported */
status = PSQL_CMD_ERROR;
} }
else else
{ {
FILE *output; /* just send the definition to output */
bool is_pager; fputs(buf->data, output);
/* Select output stream: stdout, pager, or file */
if (pset.queryFout == stdout)
{
/* count lines in view to see if pager is needed */
int lineno = count_lines_in_buf(view_buf);
output = PageOutput(lineno, &(pset.popt.topt));
is_pager = true;
}
else
{
/* use previously set output file, without pager */
output = pset.queryFout;
is_pager = false;
}
if (show_linenumbers)
{
/* add line numbers, numbering all lines */
print_with_linenumbers(output, view_buf->data, NULL);
}
else
{
/* just send the view definition to output */
fputs(view_buf->data, output);
} }
if (is_pager) if (is_pager)
ClosePager(output); ClosePager(output);
} }
if (view) if (obj_desc)
free(view); free(obj_desc);
destroyPQExpBuffer(view_buf); destroyPQExpBuffer(buf);
} }
else else
ignore_slash_whole_line(scan_state); ignore_slash_whole_line(scan_state);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment