PostgreSQL Source Code: src/bin/psql/input.c Source File (original) (raw)
1
2
3
4
5
6
7
9
10#ifndef WIN32
12#endif
13#include <fcntl.h>
14#include <limits.h>
15
21
22#ifndef WIN32
23#define PSQLHISTORY ".psql_history"
24#else
25#define PSQLHISTORY "psql_history"
26#endif
27
28
29
30#ifdef USE_READLINE
31static bool useReadline;
32static bool useHistory;
33
34static char *psql_history;
35
36static int history_lines_added;
37
38
39
40
41
42
43
44
45
46
47#define NL_IN_HISTORY 0x01
48#endif
49
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66char *
68{
69#ifdef USE_READLINE
70 if (useReadline)
71 {
72 char *result;
73
74
75
76
77
78
79
80
81#ifdef HAVE_RL_RESET_SCREEN_SIZE
82 rl_reset_screen_size();
83#endif
84
85
87
88
90
91 result = readline(prompt);
92
93
95
96
98
99 return result;
100 }
101#endif
102
103 fputs(prompt, stdout);
106}
107
108
109
110
111
112void
114{
115#ifdef USE_READLINE
116 if (useHistory && s)
117 {
119 if (!s[0] || s[strlen(s) - 1] != '\n')
121 }
122#endif
123}
124
125
126
127
128
129
130
131
132
133
134void
136{
137#ifdef USE_READLINE
138 static char *prev_hist = NULL;
139
140 char *s = history_buf->data;
141 int i;
142
143
144 for (i = strlen(s) - 1; i >= 0 && s[i] == '\n'; i--)
145 ;
146 s[i + 1] = '\0';
147
148 if (useHistory && s[0])
149 {
151 s[0] == ' ') ||
153 prev_hist && strcmp(s, prev_hist) == 0))
154 {
155
156 }
157 else
158 {
159
160 free(prev_hist);
162
163 add_history(s);
164
165 history_lines_added++;
166 }
167 }
168
170#endif
171}
172
173
174
175
176
177
178
179
180
181
182
183
184
185char *
187{
189
190 char line[1024];
191
192 if (buffer == NULL)
194 else
196
197 for (;;)
198 {
199 char *result;
200
201
203
204
205 result = fgets(line, sizeof(line), source);
206
207
209
210
211 if (result == NULL)
212 {
214 {
215 pg_log_error("could not read from input file: %m");
216 return NULL;
217 }
218 break;
219 }
220
222
224 {
226 return NULL;
227 }
228
229
230 if (buffer->len > 0 && buffer->data[buffer->len - 1] == '\n')
231 {
232 buffer->data[buffer->len - 1] = '\0';
234 }
235 }
236
237 if (buffer->len > 0)
239
240
241 return NULL;
242}
243
244
245#ifdef USE_READLINE
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277#define BEGIN_ITERATE_HISTORY(VARNAME) \
278 do { \
279 HIST_ENTRY *VARNAME; \
280 bool use_prev_; \
281 \
282 history_set_pos(0); \
283 use_prev_ = (previous_history() != NULL); \
284 history_set_pos(0); \
285 for (VARNAME = current_history(); VARNAME != NULL; \
286 VARNAME = use_prev_ ? previous_history() : next_history()) \
287 { \
288 (void) 0
289
290#define END_ITERATE_HISTORY() \
291 } \
292 } while(0)
293
294
295
296
297
298static void
299encode_history(void)
300{
301 BEGIN_ITERATE_HISTORY(cur_hist);
302 {
303 char *cur_ptr;
304
305
306 for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
307 {
308 if (*cur_ptr == '\n')
309 *cur_ptr = NL_IN_HISTORY;
310 }
311 }
312 END_ITERATE_HISTORY();
313}
314
315
316
317
318static void
319decode_history(void)
320{
321 BEGIN_ITERATE_HISTORY(cur_hist);
322 {
323 char *cur_ptr;
324
325
326 for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++)
327 {
328 if (*cur_ptr == NL_IN_HISTORY)
329 *cur_ptr = '\n';
330 }
331 }
332 END_ITERATE_HISTORY();
333}
334#endif
335
336
337
338
339
340
341
342
343void
345{
346#ifdef USE_READLINE
347 if (flags & 1)
348 {
349 const char *histfile;
351
352 useReadline = true;
353
354
356
357#ifdef HAVE_RL_VARIABLE_BIND
358
359 (void) rl_variable_bind("comment-begin", "-- ");
360#endif
361
362
363 rl_initialize();
364
365 useHistory = true;
366 using_history();
367 history_lines_added = 0;
368
370
371 if (histfile == NULL)
372 {
373 char *envhist;
374
375 envhist = getenv("PSQL_HISTORY");
376 if (envhist != NULL && strlen(envhist) > 0)
377 histfile = envhist;
378 }
379
380 if (histfile == NULL)
381 {
384 }
385 else
386 {
387 psql_history = pg_strdup(histfile);
389 }
390
391 if (psql_history)
392 {
393 read_history(psql_history);
394 decode_history();
395 }
396 }
397#endif
398
400}
401
402
403
404
405
406
407
408
409
410
411#ifdef USE_READLINE
412static bool
413saveHistory(char *fname, int max_lines)
414{
415 int errnum;
416
417
418
419
420
421
422
423 if (strcmp(fname, DEVNULL) != 0)
424 {
425
426
427
428
429
430
431 encode_history();
432
433
434
435
436
437
438
439
440#if defined(HAVE_HISTORY_TRUNCATE_FILE) && defined(HAVE_APPEND_HISTORY)
441 {
442 int nlines;
443 int fd;
444
445
446 if (max_lines >= 0)
447 {
448 nlines = Max(max_lines - history_lines_added, 0);
449 (void) history_truncate_file(fname, nlines);
450 }
451
452 fd = open(fname, O_CREAT | O_WRONLY | PG_BINARY, 0600);
453 if (fd >= 0)
455
456 if (max_lines >= 0)
457 nlines = Min(max_lines, history_lines_added);
458 else
459 nlines = history_lines_added;
460 errnum = append_history(nlines, fname);
461 if (errnum == 0)
462 return true;
463 }
464#else
465 {
466
467 if (max_lines >= 0)
468 stifle_history(max_lines);
469
470 errnum = write_history(fname);
471 if (errnum == 0)
472 return true;
473 }
474#endif
475
476 pg_log_error("could not save history to file \"%s\": %m", fname);
477 }
478 return false;
479}
480#endif
481
482
483
484
485
486
487
488
489
490
491
492
493bool
495{
496#ifdef USE_READLINE
498 bool is_pager;
499
500 if (!useHistory)
501 return false;
502
503 if (fname == NULL)
504 {
505
507 is_pager = true;
508 }
509 else
510 {
511 output = fopen(fname, "w");
513 {
514 pg_log_error("could not save history to file \"%s\": %m", fname);
515 return false;
516 }
517 is_pager = false;
518 }
519
520 BEGIN_ITERATE_HISTORY(cur_hist);
521 {
523 }
524 END_ITERATE_HISTORY();
525
526 if (is_pager)
528 else
530
531 return true;
532#else
533 pg_log_error("history is not supported by this installation");
534 return false;
535#endif
536}
537
538
539static void
541{
542#ifdef USE_READLINE
543 if (useHistory && psql_history)
544 {
545 (void) saveHistory(psql_history, pset.histsize);
546 free(psql_history);
547 psql_history = NULL;
548 }
549#endif
550}
void expand_tilde(char **filename)
volatile sig_atomic_t sigint_interrupt_enabled
#define fprintf(file, fmt, msg)
char * pg_strdup(const char *in)
FILE * PageOutput(int lines, const printTableOpt *topt)
void ClosePager(FILE *pagerpipe)
void pg_send_history(PQExpBuffer history_buf)
bool printHistory(const char *fname, unsigned short int pager)
static void finishInput(void)
char * gets_interactive(const char *prompt, PQExpBuffer query_buf)
char * gets_fromFile(FILE *source)
void initializeInput(int flags)
void pg_append_history(const char *s, PQExpBuffer history_buf)
#define pg_log_error(...)
static rewind_source * source
bool get_home_path(char *ret_path)
PQExpBuffer createPQExpBuffer(void)
void resetPQExpBuffer(PQExpBuffer str)
void appendPQExpBufferChar(PQExpBuffer str, char ch)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
#define PQExpBufferBroken(str)
static int fd(const char *x, int i)
char * psprintf(const char *fmt,...)
void initialize_readline(void)
PQExpBuffer tab_completion_query_buf
const char * GetVariable(VariableSpace space, const char *name)