mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
Add psql PROMPT variable showing which line of a statement is being edited.
The new %l substitution shows the line number inside a (potentially multi-line) statement starting from one. Author: Sawada Masahiko, heavily editorialized by me. Reviewed-By: Jeevan Chalke, Alvaro Herrera
This commit is contained in:
parent
bd3b7a9eef
commit
51bb79569f
@ -3315,6 +3315,15 @@ testdb=> <userinput>INSERT INTO my_table VALUES (:'content');</userinput>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><literal>%l</literal></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
The line number inside the current statement, starting from <literal>1</>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><literal>%</literal><replaceable class="parameter">digits</replaceable></term>
|
<term><literal>%</literal><replaceable class="parameter">digits</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
|
@ -517,8 +517,8 @@ bool
|
|||||||
handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
|
handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
|
||||||
{
|
{
|
||||||
bool OK;
|
bool OK;
|
||||||
const char *prompt;
|
|
||||||
char buf[COPYBUFSIZ];
|
char buf[COPYBUFSIZ];
|
||||||
|
bool showprompt = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Establish longjmp destination for exiting from wait-for-input. (This is
|
* Establish longjmp destination for exiting from wait-for-input. (This is
|
||||||
@ -540,21 +540,20 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
|
|||||||
/* Prompt if interactive input */
|
/* Prompt if interactive input */
|
||||||
if (isatty(fileno(copystream)))
|
if (isatty(fileno(copystream)))
|
||||||
{
|
{
|
||||||
|
showprompt = true;
|
||||||
if (!pset.quiet)
|
if (!pset.quiet)
|
||||||
puts(_("Enter data to be copied followed by a newline.\n"
|
puts(_("Enter data to be copied followed by a newline.\n"
|
||||||
"End with a backslash and a period on a line by itself."));
|
"End with a backslash and a period on a line by itself."));
|
||||||
prompt = get_prompt(PROMPT_COPY);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
prompt = NULL;
|
|
||||||
|
|
||||||
OK = true;
|
OK = true;
|
||||||
|
|
||||||
if (isbinary)
|
if (isbinary)
|
||||||
{
|
{
|
||||||
/* interactive input probably silly, but give one prompt anyway */
|
/* interactive input probably silly, but give one prompt anyway */
|
||||||
if (prompt)
|
if (showprompt)
|
||||||
{
|
{
|
||||||
|
const char *prompt = get_prompt(PROMPT_COPY);
|
||||||
fputs(prompt, stdout);
|
fputs(prompt, stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
@ -589,8 +588,9 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
|
|||||||
bool firstload;
|
bool firstload;
|
||||||
bool linedone;
|
bool linedone;
|
||||||
|
|
||||||
if (prompt)
|
if (showprompt)
|
||||||
{
|
{
|
||||||
|
const char *prompt = get_prompt(PROMPT_COPY);
|
||||||
fputs(prompt, stdout);
|
fputs(prompt, stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
@ -650,7 +650,10 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (copystream == pset.cur_cmd_source)
|
if (copystream == pset.cur_cmd_source)
|
||||||
|
{
|
||||||
pset.lineno++;
|
pset.lineno++;
|
||||||
|
pset.stmt_lineno++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ MainLoop(FILE *source)
|
|||||||
pset.cur_cmd_source = source;
|
pset.cur_cmd_source = source;
|
||||||
pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
|
pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
|
||||||
pset.lineno = 0;
|
pset.lineno = 0;
|
||||||
|
pset.stmt_lineno = 1;
|
||||||
|
|
||||||
/* Create working state */
|
/* Create working state */
|
||||||
scan_state = psql_scan_create();
|
scan_state = psql_scan_create();
|
||||||
@ -110,6 +111,7 @@ MainLoop(FILE *source)
|
|||||||
count_eof = 0;
|
count_eof = 0;
|
||||||
slashCmdStatus = PSQL_CMD_UNKNOWN;
|
slashCmdStatus = PSQL_CMD_UNKNOWN;
|
||||||
prompt_status = PROMPT_READY;
|
prompt_status = PROMPT_READY;
|
||||||
|
pset.stmt_lineno = 1;
|
||||||
cancel_pressed = false;
|
cancel_pressed = false;
|
||||||
|
|
||||||
if (pset.cur_cmd_interactive)
|
if (pset.cur_cmd_interactive)
|
||||||
@ -225,7 +227,10 @@ MainLoop(FILE *source)
|
|||||||
{
|
{
|
||||||
PsqlScanResult scan_result;
|
PsqlScanResult scan_result;
|
||||||
promptStatus_t prompt_tmp = prompt_status;
|
promptStatus_t prompt_tmp = prompt_status;
|
||||||
|
size_t pos_in_query;
|
||||||
|
char *tmp_line;
|
||||||
|
|
||||||
|
pos_in_query = query_buf->len;
|
||||||
scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
|
scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
|
||||||
prompt_status = prompt_tmp;
|
prompt_status = prompt_tmp;
|
||||||
|
|
||||||
@ -235,6 +240,22 @@ MainLoop(FILE *source)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Increase statement line number counter for each linebreak added
|
||||||
|
* to the query buffer by the last psql_scan() call. There only
|
||||||
|
* will be ones to add when navigating to a statement in
|
||||||
|
* readline's history containing newlines.
|
||||||
|
*/
|
||||||
|
tmp_line = query_buf->data + pos_in_query;
|
||||||
|
while (*tmp_line != '\0')
|
||||||
|
{
|
||||||
|
if (*(tmp_line++) == '\n')
|
||||||
|
pset.stmt_lineno++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scan_result == PSCAN_EOL)
|
||||||
|
pset.stmt_lineno++;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send command if semicolon found, or if end of line and we're in
|
* Send command if semicolon found, or if end of line and we're in
|
||||||
* single-line mode.
|
* single-line mode.
|
||||||
@ -256,6 +277,7 @@ MainLoop(FILE *source)
|
|||||||
/* execute query */
|
/* execute query */
|
||||||
success = SendQuery(query_buf->data);
|
success = SendQuery(query_buf->data);
|
||||||
slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
|
slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
|
||||||
|
pset.stmt_lineno = 1;
|
||||||
|
|
||||||
/* transfer query to previous_buf by pointer-swapping */
|
/* transfer query to previous_buf by pointer-swapping */
|
||||||
{
|
{
|
||||||
@ -303,6 +325,7 @@ MainLoop(FILE *source)
|
|||||||
query_buf : previous_buf);
|
query_buf : previous_buf);
|
||||||
|
|
||||||
success = slashCmdStatus != PSQL_CMD_ERROR;
|
success = slashCmdStatus != PSQL_CMD_ERROR;
|
||||||
|
pset.stmt_lineno = 1;
|
||||||
|
|
||||||
if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
|
if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
|
||||||
query_buf->len == 0)
|
query_buf->len == 0)
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
* in prompt2 -, *, ', or ";
|
* in prompt2 -, *, ', or ";
|
||||||
* in prompt3 nothing
|
* in prompt3 nothing
|
||||||
* %x - transaction status: empty, *, !, ? (unknown or no connection)
|
* %x - transaction status: empty, *, !, ? (unknown or no connection)
|
||||||
|
* %l - The line number inside the current statement, starting from 1.
|
||||||
* %? - the error code of the last query (not yet implemented)
|
* %? - the error code of the last query (not yet implemented)
|
||||||
* %% - a percent sign
|
* %% - a percent sign
|
||||||
*
|
*
|
||||||
@ -229,6 +230,10 @@ get_prompt(promptStatus_t status)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
snprintf(buf, sizeof(buf), UINT64_FORMAT, pset.stmt_lineno);
|
||||||
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
/* not here yet */
|
/* not here yet */
|
||||||
break;
|
break;
|
||||||
|
@ -88,6 +88,7 @@ typedef struct _psqlSettings
|
|||||||
const char *progname; /* in case you renamed psql */
|
const char *progname; /* in case you renamed psql */
|
||||||
char *inputfile; /* file being currently processed, if any */
|
char *inputfile; /* file being currently processed, if any */
|
||||||
uint64 lineno; /* also for error reporting */
|
uint64 lineno; /* also for error reporting */
|
||||||
|
uint64 stmt_lineno; /* line number inside the current statement */
|
||||||
|
|
||||||
bool timing; /* enable timing of all queries */
|
bool timing; /* enable timing of all queries */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user