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)