Skip to content

Commit 51bb795

Browse files
committed
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
1 parent bd3b7a9 commit 51bb795

File tree

5 files changed

+47
-6
lines changed

5 files changed

+47
-6
lines changed

doc/src/sgml/ref/psql-ref.sgml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3315,6 +3315,15 @@ testdb=&gt; <userinput>INSERT INTO my_table VALUES (:'content');</userinput>
33153315
</listitem>
33163316
</varlistentry>
33173317

3318+
<varlistentry>
3319+
<term><literal>%l</literal></term>
3320+
<listitem>
3321+
<para>
3322+
The line number inside the current statement, starting from <literal>1</>.
3323+
</para>
3324+
</listitem>
3325+
</varlistentry>
3326+
33183327
<varlistentry>
33193328
<term><literal>%</literal><replaceable class="parameter">digits</replaceable></term>
33203329
<listitem>

src/bin/psql/copy.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -517,8 +517,8 @@ bool
517517
handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
518518
{
519519
bool OK;
520-
const char *prompt;
521520
char buf[COPYBUFSIZ];
521+
bool showprompt = false;
522522

523523
/*
524524
* Establish longjmp destination for exiting from wait-for-input. (This is
@@ -540,21 +540,20 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
540540
/* Prompt if interactive input */
541541
if (isatty(fileno(copystream)))
542542
{
543+
showprompt = true;
543544
if (!pset.quiet)
544545
puts(_("Enter data to be copied followed by a newline.\n"
545546
"End with a backslash and a period on a line by itself."));
546-
prompt = get_prompt(PROMPT_COPY);
547547
}
548-
else
549-
prompt = NULL;
550548

551549
OK = true;
552550

553551
if (isbinary)
554552
{
555553
/* interactive input probably silly, but give one prompt anyway */
556-
if (prompt)
554+
if (showprompt)
557555
{
556+
const char *prompt = get_prompt(PROMPT_COPY);
558557
fputs(prompt, stdout);
559558
fflush(stdout);
560559
}
@@ -589,8 +588,9 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
589588
bool firstload;
590589
bool linedone;
591590

592-
if (prompt)
591+
if (showprompt)
593592
{
593+
const char *prompt = get_prompt(PROMPT_COPY);
594594
fputs(prompt, stdout);
595595
fflush(stdout);
596596
}
@@ -650,7 +650,10 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
650650
}
651651

652652
if (copystream == pset.cur_cmd_source)
653+
{
653654
pset.lineno++;
655+
pset.stmt_lineno++;
656+
}
654657
}
655658
}
656659

src/bin/psql/mainloop.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ MainLoop(FILE *source)
5858
pset.cur_cmd_source = source;
5959
pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
6060
pset.lineno = 0;
61+
pset.stmt_lineno = 1;
6162

6263
/* Create working state */
6364
scan_state = psql_scan_create();
@@ -110,6 +111,7 @@ MainLoop(FILE *source)
110111
count_eof = 0;
111112
slashCmdStatus = PSQL_CMD_UNKNOWN;
112113
prompt_status = PROMPT_READY;
114+
pset.stmt_lineno = 1;
113115
cancel_pressed = false;
114116

115117
if (pset.cur_cmd_interactive)
@@ -225,7 +227,10 @@ MainLoop(FILE *source)
225227
{
226228
PsqlScanResult scan_result;
227229
promptStatus_t prompt_tmp = prompt_status;
230+
size_t pos_in_query;
231+
char *tmp_line;
228232

233+
pos_in_query = query_buf->len;
229234
scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
230235
prompt_status = prompt_tmp;
231236

@@ -235,6 +240,22 @@ MainLoop(FILE *source)
235240
exit(EXIT_FAILURE);
236241
}
237242

243+
/*
244+
* Increase statement line number counter for each linebreak added
245+
* to the query buffer by the last psql_scan() call. There only
246+
* will be ones to add when navigating to a statement in
247+
* readline's history containing newlines.
248+
*/
249+
tmp_line = query_buf->data + pos_in_query;
250+
while (*tmp_line != '\0')
251+
{
252+
if (*(tmp_line++) == '\n')
253+
pset.stmt_lineno++;
254+
}
255+
256+
if (scan_result == PSCAN_EOL)
257+
pset.stmt_lineno++;
258+
238259
/*
239260
* Send command if semicolon found, or if end of line and we're in
240261
* single-line mode.
@@ -256,6 +277,7 @@ MainLoop(FILE *source)
256277
/* execute query */
257278
success = SendQuery(query_buf->data);
258279
slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
280+
pset.stmt_lineno = 1;
259281

260282
/* transfer query to previous_buf by pointer-swapping */
261283
{
@@ -303,6 +325,7 @@ MainLoop(FILE *source)
303325
query_buf : previous_buf);
304326

305327
success = slashCmdStatus != PSQL_CMD_ERROR;
328+
pset.stmt_lineno = 1;
306329

307330
if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
308331
query_buf->len == 0)

src/bin/psql/prompt.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
* in prompt2 -, *, ', or ";
4545
* in prompt3 nothing
4646
* %x - transaction status: empty, *, !, ? (unknown or no connection)
47+
* %l - The line number inside the current statement, starting from 1.
4748
* %? - the error code of the last query (not yet implemented)
4849
* %% - a percent sign
4950
*
@@ -229,6 +230,10 @@ get_prompt(promptStatus_t status)
229230
}
230231
break;
231232

233+
case 'l':
234+
snprintf(buf, sizeof(buf), UINT64_FORMAT, pset.stmt_lineno);
235+
break;
236+
232237
case '?':
233238
/* not here yet */
234239
break;

src/bin/psql/settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ typedef struct _psqlSettings
8888
const char *progname; /* in case you renamed psql */
8989
char *inputfile; /* file being currently processed, if any */
9090
uint64 lineno; /* also for error reporting */
91+
uint64 stmt_lineno; /* line number inside the current statement */
9192

9293
bool timing; /* enable timing of all queries */
9394

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy