PageRenderTime 70ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/bin/psql/command.c

http://github.com/postgres/postgres
C | 5166 lines | 4007 code | 457 blank | 702 comment | 766 complexity | 776c5e1253ef696bb31d23c888020b6a MD5 | raw file
Possible License(s): AGPL-3.0
  1. /*
  2. * psql - the PostgreSQL interactive terminal
  3. *
  4. * Copyright (c) 2000-2020, PostgreSQL Global Development Group
  5. *
  6. * src/bin/psql/command.c
  7. */
  8. #include "postgres_fe.h"
  9. #include <ctype.h>
  10. #include <time.h>
  11. #include <pwd.h>
  12. #ifndef WIN32
  13. #include <sys/stat.h> /* for stat() */
  14. #include <fcntl.h> /* open() flags */
  15. #include <unistd.h> /* for geteuid(), getpid(), stat() */
  16. #else
  17. #include <win32.h>
  18. #include <io.h>
  19. #include <fcntl.h>
  20. #include <direct.h>
  21. #include <sys/stat.h> /* for stat() */
  22. #endif
  23. #include "catalog/pg_class_d.h"
  24. #include "command.h"
  25. #include "common.h"
  26. #include "common/logging.h"
  27. #include "copy.h"
  28. #include "crosstabview.h"
  29. #include "describe.h"
  30. #include "fe_utils/cancel.h"
  31. #include "fe_utils/print.h"
  32. #include "fe_utils/string_utils.h"
  33. #include "help.h"
  34. #include "input.h"
  35. #include "large_obj.h"
  36. #include "libpq-fe.h"
  37. #include "mainloop.h"
  38. #include "portability/instr_time.h"
  39. #include "pqexpbuffer.h"
  40. #include "psqlscanslash.h"
  41. #include "settings.h"
  42. #include "variables.h"
  43. /*
  44. * Editable database object types.
  45. */
  46. typedef enum EditableObjectType
  47. {
  48. EditableFunction,
  49. EditableView
  50. } EditableObjectType;
  51. /* local function declarations */
  52. static backslashResult exec_command(const char *cmd,
  53. PsqlScanState scan_state,
  54. ConditionalStack cstack,
  55. PQExpBuffer query_buf,
  56. PQExpBuffer previous_buf);
  57. static backslashResult exec_command_a(PsqlScanState scan_state, bool active_branch);
  58. static backslashResult exec_command_C(PsqlScanState scan_state, bool active_branch);
  59. static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
  60. static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
  61. const char *cmd);
  62. static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
  63. static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
  64. static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
  65. static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
  66. static backslashResult exec_command_d(PsqlScanState scan_state, bool active_branch,
  67. const char *cmd);
  68. static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch,
  69. PQExpBuffer query_buf, PQExpBuffer previous_buf);
  70. static backslashResult exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
  71. PQExpBuffer query_buf, bool is_func);
  72. static backslashResult exec_command_echo(PsqlScanState scan_state, bool active_branch,
  73. const char *cmd);
  74. static backslashResult exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
  75. PQExpBuffer query_buf);
  76. static backslashResult exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
  77. PQExpBuffer query_buf);
  78. static backslashResult exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
  79. PQExpBuffer query_buf);
  80. static backslashResult exec_command_encoding(PsqlScanState scan_state, bool active_branch);
  81. static backslashResult exec_command_errverbose(PsqlScanState scan_state, bool active_branch);
  82. static backslashResult exec_command_f(PsqlScanState scan_state, bool active_branch);
  83. static backslashResult exec_command_g(PsqlScanState scan_state, bool active_branch,
  84. const char *cmd);
  85. static backslashResult process_command_g_options(char *first_option,
  86. PsqlScanState scan_state,
  87. bool active_branch,
  88. const char *cmd);
  89. static backslashResult exec_command_gdesc(PsqlScanState scan_state, bool active_branch);
  90. static backslashResult exec_command_gexec(PsqlScanState scan_state, bool active_branch);
  91. static backslashResult exec_command_gset(PsqlScanState scan_state, bool active_branch);
  92. static backslashResult exec_command_help(PsqlScanState scan_state, bool active_branch);
  93. static backslashResult exec_command_html(PsqlScanState scan_state, bool active_branch);
  94. static backslashResult exec_command_include(PsqlScanState scan_state, bool active_branch,
  95. const char *cmd);
  96. static backslashResult exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
  97. PQExpBuffer query_buf);
  98. static backslashResult exec_command_list(PsqlScanState scan_state, bool active_branch,
  99. const char *cmd);
  100. static backslashResult exec_command_lo(PsqlScanState scan_state, bool active_branch,
  101. const char *cmd);
  102. static backslashResult exec_command_out(PsqlScanState scan_state, bool active_branch);
  103. static backslashResult exec_command_print(PsqlScanState scan_state, bool active_branch,
  104. PQExpBuffer query_buf, PQExpBuffer previous_buf);
  105. static backslashResult exec_command_password(PsqlScanState scan_state, bool active_branch);
  106. static backslashResult exec_command_prompt(PsqlScanState scan_state, bool active_branch,
  107. const char *cmd);
  108. static backslashResult exec_command_pset(PsqlScanState scan_state, bool active_branch);
  109. static backslashResult exec_command_quit(PsqlScanState scan_state, bool active_branch);
  110. static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch,
  111. PQExpBuffer query_buf);
  112. static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch);
  113. static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch);
  114. static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch,
  115. const char *cmd);
  116. static backslashResult exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
  117. const char *cmd, bool is_func);
  118. static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch);
  119. static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch);
  120. static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch);
  121. static backslashResult exec_command_unset(PsqlScanState scan_state, bool active_branch,
  122. const char *cmd);
  123. static backslashResult exec_command_write(PsqlScanState scan_state, bool active_branch,
  124. const char *cmd,
  125. PQExpBuffer query_buf, PQExpBuffer previous_buf);
  126. static backslashResult exec_command_watch(PsqlScanState scan_state, bool active_branch,
  127. PQExpBuffer query_buf, PQExpBuffer previous_buf);
  128. static backslashResult exec_command_x(PsqlScanState scan_state, bool active_branch);
  129. static backslashResult exec_command_z(PsqlScanState scan_state, bool active_branch);
  130. static backslashResult exec_command_shell_escape(PsqlScanState scan_state, bool active_branch);
  131. static backslashResult exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch);
  132. static char *read_connect_arg(PsqlScanState scan_state);
  133. static PQExpBuffer gather_boolean_expression(PsqlScanState scan_state);
  134. static bool is_true_boolean_expression(PsqlScanState scan_state, const char *name);
  135. static void ignore_boolean_expression(PsqlScanState scan_state);
  136. static void ignore_slash_options(PsqlScanState scan_state);
  137. static void ignore_slash_filepipe(PsqlScanState scan_state);
  138. static void ignore_slash_whole_line(PsqlScanState scan_state);
  139. static bool is_branching_command(const char *cmd);
  140. static void save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
  141. PQExpBuffer query_buf);
  142. static void discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
  143. PQExpBuffer query_buf);
  144. static void copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf);
  145. static bool do_connect(enum trivalue reuse_previous_specification,
  146. char *dbname, char *user, char *host, char *port);
  147. static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
  148. int lineno, bool *edited);
  149. static bool do_shell(const char *command);
  150. static bool do_watch(PQExpBuffer query_buf, double sleep);
  151. static bool lookup_object_oid(EditableObjectType obj_type, const char *desc,
  152. Oid *obj_oid);
  153. static bool get_create_object_cmd(EditableObjectType obj_type, Oid oid,
  154. PQExpBuffer buf);
  155. static int strip_lineno_from_objdesc(char *obj);
  156. static int count_lines_in_buf(PQExpBuffer buf);
  157. static void print_with_linenumbers(FILE *output, char *lines,
  158. const char *header_keyword);
  159. static void minimal_error_message(PGresult *res);
  160. static void printSSLInfo(void);
  161. static void printGSSInfo(void);
  162. static bool printPsetInfo(const char *param, printQueryOpt *popt);
  163. static char *pset_value_string(const char *param, printQueryOpt *popt);
  164. #ifdef WIN32
  165. static void checkWin32Codepage(void);
  166. #endif
  167. /*----------
  168. * HandleSlashCmds:
  169. *
  170. * Handles all the different commands that start with '\'.
  171. * Ordinarily called by MainLoop().
  172. *
  173. * scan_state is a lexer working state that is set to continue scanning
  174. * just after the '\'. The lexer is advanced past the command and all
  175. * arguments on return.
  176. *
  177. * cstack is the current \if stack state. This will be examined, and
  178. * possibly modified by conditional commands.
  179. *
  180. * query_buf contains the query-so-far, which may be modified by
  181. * execution of the backslash command (for example, \r clears it).
  182. *
  183. * previous_buf contains the query most recently sent to the server
  184. * (empty if none yet). This should not be modified here, but some
  185. * commands copy its content into query_buf.
  186. *
  187. * query_buf and previous_buf will be NULL when executing a "-c"
  188. * command-line option.
  189. *
  190. * Returns a status code indicating what action is desired, see command.h.
  191. *----------
  192. */
  193. backslashResult
  194. HandleSlashCmds(PsqlScanState scan_state,
  195. ConditionalStack cstack,
  196. PQExpBuffer query_buf,
  197. PQExpBuffer previous_buf)
  198. {
  199. backslashResult status;
  200. char *cmd;
  201. char *arg;
  202. Assert(scan_state != NULL);
  203. Assert(cstack != NULL);
  204. /* Parse off the command name */
  205. cmd = psql_scan_slash_command(scan_state);
  206. /* And try to execute it */
  207. status = exec_command(cmd, scan_state, cstack, query_buf, previous_buf);
  208. if (status == PSQL_CMD_UNKNOWN)
  209. {
  210. pg_log_error("invalid command \\%s", cmd);
  211. if (pset.cur_cmd_interactive)
  212. pg_log_info("Try \\? for help.");
  213. status = PSQL_CMD_ERROR;
  214. }
  215. if (status != PSQL_CMD_ERROR)
  216. {
  217. /*
  218. * Eat any remaining arguments after a valid command. We want to
  219. * suppress evaluation of backticks in this situation, so transiently
  220. * push an inactive conditional-stack entry.
  221. */
  222. bool active_branch = conditional_active(cstack);
  223. conditional_stack_push(cstack, IFSTATE_IGNORED);
  224. while ((arg = psql_scan_slash_option(scan_state,
  225. OT_NORMAL, NULL, false)))
  226. {
  227. if (active_branch)
  228. pg_log_warning("\\%s: extra argument \"%s\" ignored", cmd, arg);
  229. free(arg);
  230. }
  231. conditional_stack_pop(cstack);
  232. }
  233. else
  234. {
  235. /* silently throw away rest of line after an erroneous command */
  236. while ((arg = psql_scan_slash_option(scan_state,
  237. OT_WHOLE_LINE, NULL, false)))
  238. free(arg);
  239. }
  240. /* if there is a trailing \\, swallow it */
  241. psql_scan_slash_command_end(scan_state);
  242. free(cmd);
  243. /* some commands write to queryFout, so make sure output is sent */
  244. fflush(pset.queryFout);
  245. return status;
  246. }
  247. /*
  248. * Subroutine to actually try to execute a backslash command.
  249. *
  250. * The typical "success" result code is PSQL_CMD_SKIP_LINE, although some
  251. * commands return something else. Failure results are PSQL_CMD_ERROR,
  252. * unless PSQL_CMD_UNKNOWN is more appropriate.
  253. */
  254. static backslashResult
  255. exec_command(const char *cmd,
  256. PsqlScanState scan_state,
  257. ConditionalStack cstack,
  258. PQExpBuffer query_buf,
  259. PQExpBuffer previous_buf)
  260. {
  261. backslashResult status;
  262. bool active_branch = conditional_active(cstack);
  263. /*
  264. * In interactive mode, warn when we're ignoring a command within a false
  265. * \if-branch. But we continue on, so as to parse and discard the right
  266. * amount of parameter text. Each individual backslash command subroutine
  267. * is responsible for doing nothing after discarding appropriate
  268. * arguments, if !active_branch.
  269. */
  270. if (pset.cur_cmd_interactive && !active_branch &&
  271. !is_branching_command(cmd))
  272. {
  273. pg_log_warning("\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block",
  274. cmd);
  275. }
  276. if (strcmp(cmd, "a") == 0)
  277. status = exec_command_a(scan_state, active_branch);
  278. else if (strcmp(cmd, "C") == 0)
  279. status = exec_command_C(scan_state, active_branch);
  280. else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
  281. status = exec_command_connect(scan_state, active_branch);
  282. else if (strcmp(cmd, "cd") == 0)
  283. status = exec_command_cd(scan_state, active_branch, cmd);
  284. else if (strcmp(cmd, "conninfo") == 0)
  285. status = exec_command_conninfo(scan_state, active_branch);
  286. else if (pg_strcasecmp(cmd, "copy") == 0)
  287. status = exec_command_copy(scan_state, active_branch);
  288. else if (strcmp(cmd, "copyright") == 0)
  289. status = exec_command_copyright(scan_state, active_branch);
  290. else if (strcmp(cmd, "crosstabview") == 0)
  291. status = exec_command_crosstabview(scan_state, active_branch);
  292. else if (cmd[0] == 'd')
  293. status = exec_command_d(scan_state, active_branch, cmd);
  294. else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
  295. status = exec_command_edit(scan_state, active_branch,
  296. query_buf, previous_buf);
  297. else if (strcmp(cmd, "ef") == 0)
  298. status = exec_command_ef_ev(scan_state, active_branch, query_buf, true);
  299. else if (strcmp(cmd, "ev") == 0)
  300. status = exec_command_ef_ev(scan_state, active_branch, query_buf, false);
  301. else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0 ||
  302. strcmp(cmd, "warn") == 0)
  303. status = exec_command_echo(scan_state, active_branch, cmd);
  304. else if (strcmp(cmd, "elif") == 0)
  305. status = exec_command_elif(scan_state, cstack, query_buf);
  306. else if (strcmp(cmd, "else") == 0)
  307. status = exec_command_else(scan_state, cstack, query_buf);
  308. else if (strcmp(cmd, "endif") == 0)
  309. status = exec_command_endif(scan_state, cstack, query_buf);
  310. else if (strcmp(cmd, "encoding") == 0)
  311. status = exec_command_encoding(scan_state, active_branch);
  312. else if (strcmp(cmd, "errverbose") == 0)
  313. status = exec_command_errverbose(scan_state, active_branch);
  314. else if (strcmp(cmd, "f") == 0)
  315. status = exec_command_f(scan_state, active_branch);
  316. else if (strcmp(cmd, "g") == 0 || strcmp(cmd, "gx") == 0)
  317. status = exec_command_g(scan_state, active_branch, cmd);
  318. else if (strcmp(cmd, "gdesc") == 0)
  319. status = exec_command_gdesc(scan_state, active_branch);
  320. else if (strcmp(cmd, "gexec") == 0)
  321. status = exec_command_gexec(scan_state, active_branch);
  322. else if (strcmp(cmd, "gset") == 0)
  323. status = exec_command_gset(scan_state, active_branch);
  324. else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
  325. status = exec_command_help(scan_state, active_branch);
  326. else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
  327. status = exec_command_html(scan_state, active_branch);
  328. else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0 ||
  329. strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
  330. status = exec_command_include(scan_state, active_branch, cmd);
  331. else if (strcmp(cmd, "if") == 0)
  332. status = exec_command_if(scan_state, cstack, query_buf);
  333. else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 ||
  334. strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
  335. status = exec_command_list(scan_state, active_branch, cmd);
  336. else if (strncmp(cmd, "lo_", 3) == 0)
  337. status = exec_command_lo(scan_state, active_branch, cmd);
  338. else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
  339. status = exec_command_out(scan_state, active_branch);
  340. else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
  341. status = exec_command_print(scan_state, active_branch,
  342. query_buf, previous_buf);
  343. else if (strcmp(cmd, "password") == 0)
  344. status = exec_command_password(scan_state, active_branch);
  345. else if (strcmp(cmd, "prompt") == 0)
  346. status = exec_command_prompt(scan_state, active_branch, cmd);
  347. else if (strcmp(cmd, "pset") == 0)
  348. status = exec_command_pset(scan_state, active_branch);
  349. else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
  350. status = exec_command_quit(scan_state, active_branch);
  351. else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
  352. status = exec_command_reset(scan_state, active_branch, query_buf);
  353. else if (strcmp(cmd, "s") == 0)
  354. status = exec_command_s(scan_state, active_branch);
  355. else if (strcmp(cmd, "set") == 0)
  356. status = exec_command_set(scan_state, active_branch);
  357. else if (strcmp(cmd, "setenv") == 0)
  358. status = exec_command_setenv(scan_state, active_branch, cmd);
  359. else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
  360. status = exec_command_sf_sv(scan_state, active_branch, cmd, true);
  361. else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0)
  362. status = exec_command_sf_sv(scan_state, active_branch, cmd, false);
  363. else if (strcmp(cmd, "t") == 0)
  364. status = exec_command_t(scan_state, active_branch);
  365. else if (strcmp(cmd, "T") == 0)
  366. status = exec_command_T(scan_state, active_branch);
  367. else if (strcmp(cmd, "timing") == 0)
  368. status = exec_command_timing(scan_state, active_branch);
  369. else if (strcmp(cmd, "unset") == 0)
  370. status = exec_command_unset(scan_state, active_branch, cmd);
  371. else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
  372. status = exec_command_write(scan_state, active_branch, cmd,
  373. query_buf, previous_buf);
  374. else if (strcmp(cmd, "watch") == 0)
  375. status = exec_command_watch(scan_state, active_branch,
  376. query_buf, previous_buf);
  377. else if (strcmp(cmd, "x") == 0)
  378. status = exec_command_x(scan_state, active_branch);
  379. else if (strcmp(cmd, "z") == 0)
  380. status = exec_command_z(scan_state, active_branch);
  381. else if (strcmp(cmd, "!") == 0)
  382. status = exec_command_shell_escape(scan_state, active_branch);
  383. else if (strcmp(cmd, "?") == 0)
  384. status = exec_command_slash_command_help(scan_state, active_branch);
  385. else
  386. status = PSQL_CMD_UNKNOWN;
  387. /*
  388. * All the commands that return PSQL_CMD_SEND want to execute previous_buf
  389. * if query_buf is empty. For convenience we implement that here, not in
  390. * the individual command subroutines.
  391. */
  392. if (status == PSQL_CMD_SEND)
  393. copy_previous_query(query_buf, previous_buf);
  394. return status;
  395. }
  396. /*
  397. * \a -- toggle field alignment
  398. *
  399. * This makes little sense but we keep it around.
  400. */
  401. static backslashResult
  402. exec_command_a(PsqlScanState scan_state, bool active_branch)
  403. {
  404. bool success = true;
  405. if (active_branch)
  406. {
  407. if (pset.popt.topt.format != PRINT_ALIGNED)
  408. success = do_pset("format", "aligned", &pset.popt, pset.quiet);
  409. else
  410. success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
  411. }
  412. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  413. }
  414. /*
  415. * \C -- override table title (formerly change HTML caption)
  416. */
  417. static backslashResult
  418. exec_command_C(PsqlScanState scan_state, bool active_branch)
  419. {
  420. bool success = true;
  421. if (active_branch)
  422. {
  423. char *opt = psql_scan_slash_option(scan_state,
  424. OT_NORMAL, NULL, true);
  425. success = do_pset("title", opt, &pset.popt, pset.quiet);
  426. free(opt);
  427. }
  428. else
  429. ignore_slash_options(scan_state);
  430. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  431. }
  432. /*
  433. * \c or \connect -- connect to database using the specified parameters.
  434. *
  435. * \c [-reuse-previous=BOOL] dbname user host port
  436. *
  437. * Specifying a parameter as '-' is equivalent to omitting it. Examples:
  438. *
  439. * \c - - hst Connect to current database on current port of
  440. * host "hst" as current user.
  441. * \c - usr - prt Connect to current database on port "prt" of current host
  442. * as user "usr".
  443. * \c dbs Connect to database "dbs" on current port of current host
  444. * as current user.
  445. */
  446. static backslashResult
  447. exec_command_connect(PsqlScanState scan_state, bool active_branch)
  448. {
  449. bool success = true;
  450. if (active_branch)
  451. {
  452. static const char prefix[] = "-reuse-previous=";
  453. char *opt1,
  454. *opt2,
  455. *opt3,
  456. *opt4;
  457. enum trivalue reuse_previous = TRI_DEFAULT;
  458. opt1 = read_connect_arg(scan_state);
  459. if (opt1 != NULL && strncmp(opt1, prefix, sizeof(prefix) - 1) == 0)
  460. {
  461. bool on_off;
  462. success = ParseVariableBool(opt1 + sizeof(prefix) - 1,
  463. "-reuse-previous",
  464. &on_off);
  465. if (success)
  466. {
  467. reuse_previous = on_off ? TRI_YES : TRI_NO;
  468. free(opt1);
  469. opt1 = read_connect_arg(scan_state);
  470. }
  471. }
  472. if (success) /* give up if reuse_previous was invalid */
  473. {
  474. opt2 = read_connect_arg(scan_state);
  475. opt3 = read_connect_arg(scan_state);
  476. opt4 = read_connect_arg(scan_state);
  477. success = do_connect(reuse_previous, opt1, opt2, opt3, opt4);
  478. free(opt2);
  479. free(opt3);
  480. free(opt4);
  481. }
  482. free(opt1);
  483. }
  484. else
  485. ignore_slash_options(scan_state);
  486. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  487. }
  488. /*
  489. * \cd -- change directory
  490. */
  491. static backslashResult
  492. exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
  493. {
  494. bool success = true;
  495. if (active_branch)
  496. {
  497. char *opt = psql_scan_slash_option(scan_state,
  498. OT_NORMAL, NULL, true);
  499. char *dir;
  500. if (opt)
  501. dir = opt;
  502. else
  503. {
  504. #ifndef WIN32
  505. struct passwd *pw;
  506. uid_t user_id = geteuid();
  507. errno = 0; /* clear errno before call */
  508. pw = getpwuid(user_id);
  509. if (!pw)
  510. {
  511. pg_log_error("could not get home directory for user ID %ld: %s",
  512. (long) user_id,
  513. errno ? strerror(errno) : _("user does not exist"));
  514. exit(EXIT_FAILURE);
  515. }
  516. dir = pw->pw_dir;
  517. #else /* WIN32 */
  518. /*
  519. * On Windows, 'cd' without arguments prints the current
  520. * directory, so if someone wants to code this here instead...
  521. */
  522. dir = "/";
  523. #endif /* WIN32 */
  524. }
  525. if (chdir(dir) == -1)
  526. {
  527. pg_log_error("\\%s: could not change directory to \"%s\": %m",
  528. cmd, dir);
  529. success = false;
  530. }
  531. if (opt)
  532. free(opt);
  533. }
  534. else
  535. ignore_slash_options(scan_state);
  536. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  537. }
  538. /*
  539. * \conninfo -- display information about the current connection
  540. */
  541. static backslashResult
  542. exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
  543. {
  544. if (active_branch)
  545. {
  546. char *db = PQdb(pset.db);
  547. if (db == NULL)
  548. printf(_("You are currently not connected to a database.\n"));
  549. else
  550. {
  551. char *host = PQhost(pset.db);
  552. char *hostaddr = PQhostaddr(pset.db);
  553. /*
  554. * If the host is an absolute path, the connection is via socket
  555. * unless overridden by hostaddr
  556. */
  557. if (is_absolute_path(host))
  558. {
  559. if (hostaddr && *hostaddr)
  560. printf(_("You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"),
  561. db, PQuser(pset.db), hostaddr, PQport(pset.db));
  562. else
  563. printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
  564. db, PQuser(pset.db), host, PQport(pset.db));
  565. }
  566. else
  567. {
  568. if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0)
  569. printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"),
  570. db, PQuser(pset.db), host, hostaddr, PQport(pset.db));
  571. else
  572. printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
  573. db, PQuser(pset.db), host, PQport(pset.db));
  574. }
  575. printSSLInfo();
  576. printGSSInfo();
  577. }
  578. }
  579. return PSQL_CMD_SKIP_LINE;
  580. }
  581. /*
  582. * \copy -- run a COPY command
  583. */
  584. static backslashResult
  585. exec_command_copy(PsqlScanState scan_state, bool active_branch)
  586. {
  587. bool success = true;
  588. if (active_branch)
  589. {
  590. char *opt = psql_scan_slash_option(scan_state,
  591. OT_WHOLE_LINE, NULL, false);
  592. success = do_copy(opt);
  593. free(opt);
  594. }
  595. else
  596. ignore_slash_whole_line(scan_state);
  597. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  598. }
  599. /*
  600. * \copyright -- print copyright notice
  601. */
  602. static backslashResult
  603. exec_command_copyright(PsqlScanState scan_state, bool active_branch)
  604. {
  605. if (active_branch)
  606. print_copyright();
  607. return PSQL_CMD_SKIP_LINE;
  608. }
  609. /*
  610. * \crosstabview -- execute a query and display results in crosstab
  611. */
  612. static backslashResult
  613. exec_command_crosstabview(PsqlScanState scan_state, bool active_branch)
  614. {
  615. backslashResult status = PSQL_CMD_SKIP_LINE;
  616. if (active_branch)
  617. {
  618. int i;
  619. for (i = 0; i < lengthof(pset.ctv_args); i++)
  620. pset.ctv_args[i] = psql_scan_slash_option(scan_state,
  621. OT_NORMAL, NULL, true);
  622. pset.crosstab_flag = true;
  623. status = PSQL_CMD_SEND;
  624. }
  625. else
  626. ignore_slash_options(scan_state);
  627. return status;
  628. }
  629. /*
  630. * \d* commands
  631. */
  632. static backslashResult
  633. exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
  634. {
  635. backslashResult status = PSQL_CMD_SKIP_LINE;
  636. bool success = true;
  637. if (active_branch)
  638. {
  639. char *pattern;
  640. bool show_verbose,
  641. show_system;
  642. /* We don't do SQLID reduction on the pattern yet */
  643. pattern = psql_scan_slash_option(scan_state,
  644. OT_NORMAL, NULL, true);
  645. show_verbose = strchr(cmd, '+') ? true : false;
  646. show_system = strchr(cmd, 'S') ? true : false;
  647. switch (cmd[1])
  648. {
  649. case '\0':
  650. case '+':
  651. case 'S':
  652. if (pattern)
  653. success = describeTableDetails(pattern, show_verbose, show_system);
  654. else
  655. /* standard listing of interesting things */
  656. success = listTables("tvmsE", NULL, show_verbose, show_system);
  657. break;
  658. case 'A':
  659. {
  660. char *pattern2 = NULL;
  661. if (pattern && cmd[2] != '\0' && cmd[2] != '+')
  662. pattern2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
  663. switch (cmd[2])
  664. {
  665. case '\0':
  666. case '+':
  667. success = describeAccessMethods(pattern, show_verbose);
  668. break;
  669. case 'c':
  670. success = listOperatorClasses(pattern, pattern2, show_verbose);
  671. break;
  672. case 'f':
  673. success = listOperatorFamilies(pattern, pattern2, show_verbose);
  674. break;
  675. case 'o':
  676. success = listOpFamilyOperators(pattern, pattern2, show_verbose);
  677. break;
  678. case 'p':
  679. success = listOpFamilyProcedures(pattern, pattern2);
  680. break;
  681. default:
  682. status = PSQL_CMD_UNKNOWN;
  683. break;
  684. }
  685. if (pattern2)
  686. free(pattern2);
  687. }
  688. break;
  689. case 'a':
  690. success = describeAggregates(pattern, show_verbose, show_system);
  691. break;
  692. case 'b':
  693. success = describeTablespaces(pattern, show_verbose);
  694. break;
  695. case 'c':
  696. success = listConversions(pattern, show_verbose, show_system);
  697. break;
  698. case 'C':
  699. success = listCasts(pattern, show_verbose);
  700. break;
  701. case 'd':
  702. if (strncmp(cmd, "ddp", 3) == 0)
  703. success = listDefaultACLs(pattern);
  704. else
  705. success = objectDescription(pattern, show_system);
  706. break;
  707. case 'D':
  708. success = listDomains(pattern, show_verbose, show_system);
  709. break;
  710. case 'f': /* function subsystem */
  711. switch (cmd[2])
  712. {
  713. case '\0':
  714. case '+':
  715. case 'S':
  716. case 'a':
  717. case 'n':
  718. case 'p':
  719. case 't':
  720. case 'w':
  721. success = describeFunctions(&cmd[2], pattern, show_verbose, show_system);
  722. break;
  723. default:
  724. status = PSQL_CMD_UNKNOWN;
  725. break;
  726. }
  727. break;
  728. case 'g':
  729. /* no longer distinct from \du */
  730. success = describeRoles(pattern, show_verbose, show_system);
  731. break;
  732. case 'l':
  733. success = do_lo_list();
  734. break;
  735. case 'L':
  736. success = listLanguages(pattern, show_verbose, show_system);
  737. break;
  738. case 'n':
  739. success = listSchemas(pattern, show_verbose, show_system);
  740. break;
  741. case 'o':
  742. success = describeOperators(pattern, show_verbose, show_system);
  743. break;
  744. case 'O':
  745. success = listCollations(pattern, show_verbose, show_system);
  746. break;
  747. case 'p':
  748. success = permissionsList(pattern);
  749. break;
  750. case 'P':
  751. {
  752. switch (cmd[2])
  753. {
  754. case '\0':
  755. case '+':
  756. case 't':
  757. case 'i':
  758. case 'n':
  759. success = listPartitionedTables(&cmd[2], pattern, show_verbose);
  760. break;
  761. default:
  762. status = PSQL_CMD_UNKNOWN;
  763. break;
  764. }
  765. }
  766. break;
  767. case 'T':
  768. success = describeTypes(pattern, show_verbose, show_system);
  769. break;
  770. case 't':
  771. case 'v':
  772. case 'm':
  773. case 'i':
  774. case 's':
  775. case 'E':
  776. success = listTables(&cmd[1], pattern, show_verbose, show_system);
  777. break;
  778. case 'r':
  779. if (cmd[2] == 'd' && cmd[3] == 's')
  780. {
  781. char *pattern2 = NULL;
  782. if (pattern)
  783. pattern2 = psql_scan_slash_option(scan_state,
  784. OT_NORMAL, NULL, true);
  785. success = listDbRoleSettings(pattern, pattern2);
  786. if (pattern2)
  787. free(pattern2);
  788. }
  789. else
  790. status = PSQL_CMD_UNKNOWN;
  791. break;
  792. case 'R':
  793. switch (cmd[2])
  794. {
  795. case 'p':
  796. if (show_verbose)
  797. success = describePublications(pattern);
  798. else
  799. success = listPublications(pattern);
  800. break;
  801. case 's':
  802. success = describeSubscriptions(pattern, show_verbose);
  803. break;
  804. default:
  805. status = PSQL_CMD_UNKNOWN;
  806. }
  807. break;
  808. case 'u':
  809. success = describeRoles(pattern, show_verbose, show_system);
  810. break;
  811. case 'F': /* text search subsystem */
  812. switch (cmd[2])
  813. {
  814. case '\0':
  815. case '+':
  816. success = listTSConfigs(pattern, show_verbose);
  817. break;
  818. case 'p':
  819. success = listTSParsers(pattern, show_verbose);
  820. break;
  821. case 'd':
  822. success = listTSDictionaries(pattern, show_verbose);
  823. break;
  824. case 't':
  825. success = listTSTemplates(pattern, show_verbose);
  826. break;
  827. default:
  828. status = PSQL_CMD_UNKNOWN;
  829. break;
  830. }
  831. break;
  832. case 'e': /* SQL/MED subsystem */
  833. switch (cmd[2])
  834. {
  835. case 's':
  836. success = listForeignServers(pattern, show_verbose);
  837. break;
  838. case 'u':
  839. success = listUserMappings(pattern, show_verbose);
  840. break;
  841. case 'w':
  842. success = listForeignDataWrappers(pattern, show_verbose);
  843. break;
  844. case 't':
  845. success = listForeignTables(pattern, show_verbose);
  846. break;
  847. default:
  848. status = PSQL_CMD_UNKNOWN;
  849. break;
  850. }
  851. break;
  852. case 'x': /* Extensions */
  853. if (show_verbose)
  854. success = listExtensionContents(pattern);
  855. else
  856. success = listExtensions(pattern);
  857. break;
  858. case 'y': /* Event Triggers */
  859. success = listEventTriggers(pattern, show_verbose);
  860. break;
  861. default:
  862. status = PSQL_CMD_UNKNOWN;
  863. }
  864. if (pattern)
  865. free(pattern);
  866. }
  867. else
  868. ignore_slash_options(scan_state);
  869. if (!success)
  870. status = PSQL_CMD_ERROR;
  871. return status;
  872. }
  873. /*
  874. * \e or \edit -- edit the current query buffer, or edit a file and
  875. * make it the query buffer
  876. */
  877. static backslashResult
  878. exec_command_edit(PsqlScanState scan_state, bool active_branch,
  879. PQExpBuffer query_buf, PQExpBuffer previous_buf)
  880. {
  881. backslashResult status = PSQL_CMD_SKIP_LINE;
  882. if (active_branch)
  883. {
  884. if (!query_buf)
  885. {
  886. pg_log_error("no query buffer");
  887. status = PSQL_CMD_ERROR;
  888. }
  889. else
  890. {
  891. char *fname;
  892. char *ln = NULL;
  893. int lineno = -1;
  894. fname = psql_scan_slash_option(scan_state,
  895. OT_NORMAL, NULL, true);
  896. if (fname)
  897. {
  898. /* try to get separate lineno arg */
  899. ln = psql_scan_slash_option(scan_state,
  900. OT_NORMAL, NULL, true);
  901. if (ln == NULL)
  902. {
  903. /* only one arg; maybe it is lineno not fname */
  904. if (fname[0] &&
  905. strspn(fname, "0123456789") == strlen(fname))
  906. {
  907. /* all digits, so assume it is lineno */
  908. ln = fname;
  909. fname = NULL;
  910. }
  911. }
  912. }
  913. if (ln)
  914. {
  915. lineno = atoi(ln);
  916. if (lineno < 1)
  917. {
  918. pg_log_error("invalid line number: %s", ln);
  919. status = PSQL_CMD_ERROR;
  920. }
  921. }
  922. if (status != PSQL_CMD_ERROR)
  923. {
  924. expand_tilde(&fname);
  925. if (fname)
  926. canonicalize_path(fname);
  927. /* If query_buf is empty, recall previous query for editing */
  928. copy_previous_query(query_buf, previous_buf);
  929. if (do_edit(fname, query_buf, lineno, NULL))
  930. status = PSQL_CMD_NEWEDIT;
  931. else
  932. status = PSQL_CMD_ERROR;
  933. }
  934. if (fname)
  935. free(fname);
  936. if (ln)
  937. free(ln);
  938. }
  939. }
  940. else
  941. ignore_slash_options(scan_state);
  942. return status;
  943. }
  944. /*
  945. * \ef/\ev -- edit the named function/view, or
  946. * present a blank CREATE FUNCTION/VIEW template if no argument is given
  947. */
  948. static backslashResult
  949. exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
  950. PQExpBuffer query_buf, bool is_func)
  951. {
  952. backslashResult status = PSQL_CMD_SKIP_LINE;
  953. if (active_branch)
  954. {
  955. char *obj_desc = psql_scan_slash_option(scan_state,
  956. OT_WHOLE_LINE,
  957. NULL, true);
  958. int lineno = -1;
  959. if (pset.sversion < (is_func ? 80400 : 70400))
  960. {
  961. char sverbuf[32];
  962. formatPGVersionNumber(pset.sversion, false,
  963. sverbuf, sizeof(sverbuf));
  964. if (is_func)
  965. pg_log_error("The server (version %s) does not support editing function source.",
  966. sverbuf);
  967. else
  968. pg_log_error("The server (version %s) does not support editing view definitions.",
  969. sverbuf);
  970. status = PSQL_CMD_ERROR;
  971. }
  972. else if (!query_buf)
  973. {
  974. pg_log_error("no query buffer");
  975. status = PSQL_CMD_ERROR;
  976. }
  977. else
  978. {
  979. Oid obj_oid = InvalidOid;
  980. EditableObjectType eot = is_func ? EditableFunction : EditableView;
  981. lineno = strip_lineno_from_objdesc(obj_desc);
  982. if (lineno == 0)
  983. {
  984. /* error already reported */
  985. status = PSQL_CMD_ERROR;
  986. }
  987. else if (!obj_desc)
  988. {
  989. /* set up an empty command to fill in */
  990. resetPQExpBuffer(query_buf);
  991. if (is_func)
  992. appendPQExpBufferStr(query_buf,
  993. "CREATE FUNCTION ( )\n"
  994. " RETURNS \n"
  995. " LANGUAGE \n"
  996. " -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n"
  997. "AS $function$\n"
  998. "\n$function$\n");
  999. else
  1000. appendPQExpBufferStr(query_buf,
  1001. "CREATE VIEW AS\n"
  1002. " SELECT \n"
  1003. " -- something...\n");
  1004. }
  1005. else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
  1006. {
  1007. /* error already reported */
  1008. status = PSQL_CMD_ERROR;
  1009. }
  1010. else if (!get_create_object_cmd(eot, obj_oid, query_buf))
  1011. {
  1012. /* error already reported */
  1013. status = PSQL_CMD_ERROR;
  1014. }
  1015. else if (is_func && lineno > 0)
  1016. {
  1017. /*
  1018. * lineno "1" should correspond to the first line of the
  1019. * function body. We expect that pg_get_functiondef() will
  1020. * emit that on a line beginning with "AS ", and that there
  1021. * can be no such line before the real start of the function
  1022. * body. Increment lineno by the number of lines before that
  1023. * line, so that it becomes relative to the first line of the
  1024. * function definition.
  1025. */
  1026. const char *lines = query_buf->data;
  1027. while (*lines != '\0')
  1028. {
  1029. if (strncmp(lines, "AS ", 3) == 0)
  1030. break;
  1031. lineno++;
  1032. /* find start of next line */
  1033. lines = strchr(lines, '\n');
  1034. if (!lines)
  1035. break;
  1036. lines++;
  1037. }
  1038. }
  1039. }
  1040. if (status != PSQL_CMD_ERROR)
  1041. {
  1042. bool edited = false;
  1043. if (!do_edit(NULL, query_buf, lineno, &edited))
  1044. status = PSQL_CMD_ERROR;
  1045. else if (!edited)
  1046. puts(_("No changes"));
  1047. else
  1048. status = PSQL_CMD_NEWEDIT;
  1049. }
  1050. if (obj_desc)
  1051. free(obj_desc);
  1052. }
  1053. else
  1054. ignore_slash_whole_line(scan_state);
  1055. return status;
  1056. }
  1057. /*
  1058. * \echo, \qecho, and \warn -- echo arguments to stdout, query output, or stderr
  1059. */
  1060. static backslashResult
  1061. exec_command_echo(PsqlScanState scan_state, bool active_branch, const char *cmd)
  1062. {
  1063. if (active_branch)
  1064. {
  1065. char *value;
  1066. char quoted;
  1067. bool no_newline = false;
  1068. bool first = true;
  1069. FILE *fout;
  1070. if (strcmp(cmd, "qecho") == 0)
  1071. fout = pset.queryFout;
  1072. else if (strcmp(cmd, "warn") == 0)
  1073. fout = stderr;
  1074. else
  1075. fout = stdout;
  1076. while ((value = psql_scan_slash_option(scan_state,
  1077. OT_NORMAL, &quoted, false)))
  1078. {
  1079. if (first && !no_newline && !quoted && strcmp(value, "-n") == 0)
  1080. no_newline = true;
  1081. else
  1082. {
  1083. if (first)
  1084. first = false;
  1085. else
  1086. fputc(' ', fout);
  1087. fputs(value, fout);
  1088. }
  1089. free(value);
  1090. }
  1091. if (!no_newline)
  1092. fputs("\n", fout);
  1093. }
  1094. else
  1095. ignore_slash_options(scan_state);
  1096. return PSQL_CMD_SKIP_LINE;
  1097. }
  1098. /*
  1099. * \encoding -- set/show client side encoding
  1100. */
  1101. static backslashResult
  1102. exec_command_encoding(PsqlScanState scan_state, bool active_branch)
  1103. {
  1104. if (active_branch)
  1105. {
  1106. char *encoding = psql_scan_slash_option(scan_state,
  1107. OT_NORMAL, NULL, false);
  1108. if (!encoding)
  1109. {
  1110. /* show encoding */
  1111. puts(pg_encoding_to_char(pset.encoding));
  1112. }
  1113. else
  1114. {
  1115. /* set encoding */
  1116. if (PQsetClientEncoding(pset.db, encoding) == -1)
  1117. pg_log_error("%s: invalid encoding name or conversion procedure not found", encoding);
  1118. else
  1119. {
  1120. /* save encoding info into psql internal data */
  1121. pset.encoding = PQclientEncoding(pset.db);
  1122. pset.popt.topt.encoding = pset.encoding;
  1123. SetVariable(pset.vars, "ENCODING",
  1124. pg_encoding_to_char(pset.encoding));
  1125. }
  1126. free(encoding);
  1127. }
  1128. }
  1129. else
  1130. ignore_slash_options(scan_state);
  1131. return PSQL_CMD_SKIP_LINE;
  1132. }
  1133. /*
  1134. * \errverbose -- display verbose message from last failed query
  1135. */
  1136. static backslashResult
  1137. exec_command_errverbose(PsqlScanState scan_state, bool active_branch)
  1138. {
  1139. if (active_branch)
  1140. {
  1141. if (pset.last_error_result)
  1142. {
  1143. char *msg;
  1144. msg = PQresultVerboseErrorMessage(pset.last_error_result,
  1145. PQERRORS_VERBOSE,
  1146. PQSHOW_CONTEXT_ALWAYS);
  1147. if (msg)
  1148. {
  1149. pg_log_error("%s", msg);
  1150. PQfreemem(msg);
  1151. }
  1152. else
  1153. puts(_("out of memory"));
  1154. }
  1155. else
  1156. puts(_("There is no previous error."));
  1157. }
  1158. return PSQL_CMD_SKIP_LINE;
  1159. }
  1160. /*
  1161. * \f -- change field separator
  1162. */
  1163. static backslashResult
  1164. exec_command_f(PsqlScanState scan_state, bool active_branch)
  1165. {
  1166. bool success = true;
  1167. if (active_branch)
  1168. {
  1169. char *fname = psql_scan_slash_option(scan_state,
  1170. OT_NORMAL, NULL, false);
  1171. success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
  1172. free(fname);
  1173. }
  1174. else
  1175. ignore_slash_options(scan_state);
  1176. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1177. }
  1178. /*
  1179. * \g [(pset-option[=pset-value] ...)] [filename/shell-command]
  1180. * \gx [(pset-option[=pset-value] ...)] [filename/shell-command]
  1181. *
  1182. * Send the current query. If pset options are specified, they are made
  1183. * active just for this query. If a filename or pipe command is given,
  1184. * the query output goes there. \gx implicitly sets "expanded=on" along
  1185. * with any other pset options that are specified.
  1186. */
  1187. static backslashResult
  1188. exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
  1189. {
  1190. backslashResult status = PSQL_CMD_SKIP_LINE;
  1191. char *fname;
  1192. /*
  1193. * Because the option processing for this is fairly complicated, we do it
  1194. * and then decide whether the branch is active.
  1195. */
  1196. fname = psql_scan_slash_option(scan_state,
  1197. OT_FILEPIPE, NULL, false);
  1198. if (fname && fname[0] == '(')
  1199. {
  1200. /* Consume pset options through trailing ')' ... */
  1201. status = process_command_g_options(fname + 1, scan_state,
  1202. active_branch, cmd);
  1203. free(fname);
  1204. /* ... and again attempt to scan the filename. */
  1205. fname = psql_scan_slash_option(scan_state,
  1206. OT_FILEPIPE, NULL, false);
  1207. }
  1208. if (status == PSQL_CMD_SKIP_LINE && active_branch)
  1209. {
  1210. if (!fname)
  1211. pset.gfname = NULL;
  1212. else
  1213. {
  1214. expand_tilde(&fname);
  1215. pset.gfname = pg_strdup(fname);
  1216. }
  1217. if (strcmp(cmd, "gx") == 0)
  1218. {
  1219. /* save settings if not done already, then force expanded=on */
  1220. if (pset.gsavepopt == NULL)
  1221. pset.gsavepopt = savePsetInfo(&pset.popt);
  1222. pset.popt.topt.expanded = 1;
  1223. }
  1224. status = PSQL_CMD_SEND;
  1225. }
  1226. free(fname);
  1227. return status;
  1228. }
  1229. /*
  1230. * Process parenthesized pset options for \g
  1231. *
  1232. * Note: okay to modify first_option, but not to free it; caller does that
  1233. */
  1234. static backslashResult
  1235. process_command_g_options(char *first_option, PsqlScanState scan_state,
  1236. bool active_branch, const char *cmd)
  1237. {
  1238. bool success = true;
  1239. bool found_r_paren = false;
  1240. do
  1241. {
  1242. char *option;
  1243. size_t optlen;
  1244. /* If not first time through, collect a new option */
  1245. if (first_option)
  1246. option = first_option;
  1247. else
  1248. {
  1249. option = psql_scan_slash_option(scan_state,
  1250. OT_NORMAL, NULL, false);
  1251. if (!option)
  1252. {
  1253. if (active_branch)
  1254. {
  1255. pg_log_error("\\%s: missing right parenthesis", cmd);
  1256. success = false;
  1257. }
  1258. break;
  1259. }
  1260. }
  1261. /* Check for terminating right paren, and remove it from string */
  1262. optlen = strlen(option);
  1263. if (optlen > 0 && option[optlen - 1] == ')')
  1264. {
  1265. option[--optlen] = '\0';
  1266. found_r_paren = true;
  1267. }
  1268. /* If there was anything besides parentheses, parse/execute it */
  1269. if (optlen > 0)
  1270. {
  1271. /* We can have either "name" or "name=value" */
  1272. char *valptr = strchr(option, '=');
  1273. if (valptr)
  1274. *valptr++ = '\0';
  1275. if (active_branch)
  1276. {
  1277. /* save settings if not done already, then apply option */
  1278. if (pset.gsavepopt == NULL)
  1279. pset.gsavepopt = savePsetInfo(&pset.popt);
  1280. success &= do_pset(option, valptr, &pset.popt, true);
  1281. }
  1282. }
  1283. /* Clean up after this option. We should not free first_option. */
  1284. if (first_option)
  1285. first_option = NULL;
  1286. else
  1287. free(option);
  1288. } while (!found_r_paren);
  1289. /* If we failed after already changing some options, undo side-effects */
  1290. if (!success && active_branch && pset.gsavepopt)
  1291. {
  1292. restorePsetInfo(&pset.popt, pset.gsavepopt);
  1293. pset.gsavepopt = NULL;
  1294. }
  1295. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1296. }
  1297. /*
  1298. * \gdesc -- describe query result
  1299. */
  1300. static backslashResult
  1301. exec_command_gdesc(PsqlScanState scan_state, bool active_branch)
  1302. {
  1303. backslashResult status = PSQL_CMD_SKIP_LINE;
  1304. if (active_branch)
  1305. {
  1306. pset.gdesc_flag = true;
  1307. status = PSQL_CMD_SEND;
  1308. }
  1309. return status;
  1310. }
  1311. /*
  1312. * \gexec -- send query and execute each field of result
  1313. */
  1314. static backslashResult
  1315. exec_command_gexec(PsqlScanState scan_state, bool active_branch)
  1316. {
  1317. backslashResult status = PSQL_CMD_SKIP_LINE;
  1318. if (active_branch)
  1319. {
  1320. pset.gexec_flag = true;
  1321. status = PSQL_CMD_SEND;
  1322. }
  1323. return status;
  1324. }
  1325. /*
  1326. * \gset [prefix] -- send query and store result into variables
  1327. */
  1328. static backslashResult
  1329. exec_command_gset(PsqlScanState scan_state, bool active_branch)
  1330. {
  1331. backslashResult status = PSQL_CMD_SKIP_LINE;
  1332. if (active_branch)
  1333. {
  1334. char *prefix = psql_scan_slash_option(scan_state,
  1335. OT_NORMAL, NULL, false);
  1336. if (prefix)
  1337. pset.gset_prefix = prefix;
  1338. else
  1339. {
  1340. /* we must set a non-NULL prefix to trigger storing */
  1341. pset.gset_prefix = pg_strdup("");
  1342. }
  1343. /* gset_prefix is freed later */
  1344. status = PSQL_CMD_SEND;
  1345. }
  1346. else
  1347. ignore_slash_options(scan_state);
  1348. return status;
  1349. }
  1350. /*
  1351. * \help [topic] -- print help about SQL commands
  1352. */
  1353. static backslashResult
  1354. exec_command_help(PsqlScanState scan_state, bool active_branch)
  1355. {
  1356. if (active_branch)
  1357. {
  1358. char *opt = psql_scan_slash_option(scan_state,
  1359. OT_WHOLE_LINE, NULL, false);
  1360. size_t len;
  1361. /* strip any trailing spaces and semicolons */
  1362. if (opt)
  1363. {
  1364. len = strlen(opt);
  1365. while (len > 0 &&
  1366. (isspace((unsigned char) opt[len - 1])
  1367. || opt[len - 1] == ';'))
  1368. opt[--len] = '\0';
  1369. }
  1370. helpSQL(opt, pset.popt.topt.pager);
  1371. free(opt);
  1372. }
  1373. else
  1374. ignore_slash_whole_line(scan_state);
  1375. return PSQL_CMD_SKIP_LINE;
  1376. }
  1377. /*
  1378. * \H and \html -- toggle HTML formatting
  1379. */
  1380. static backslashResult
  1381. exec_command_html(PsqlScanState scan_state, bool active_branch)
  1382. {
  1383. bool success = true;
  1384. if (active_branch)
  1385. {
  1386. if (pset.popt.topt.format != PRINT_HTML)
  1387. success = do_pset("format", "html", &pset.popt, pset.quiet);
  1388. else
  1389. success = do_pset("format", "aligned", &pset.popt, pset.quiet);
  1390. }
  1391. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1392. }
  1393. /*
  1394. * \i and \ir -- include a file
  1395. */
  1396. static backslashResult
  1397. exec_command_include(PsqlScanState scan_state, bool active_branch, const char *cmd)
  1398. {
  1399. bool success = true;
  1400. if (active_branch)
  1401. {
  1402. char *fname = psql_scan_slash_option(scan_state,
  1403. OT_NORMAL, NULL, true);
  1404. if (!fname)
  1405. {
  1406. pg_log_error("\\%s: missing required argument", cmd);
  1407. success = false;
  1408. }
  1409. else
  1410. {
  1411. bool include_relative;
  1412. include_relative = (strcmp(cmd, "ir") == 0
  1413. || strcmp(cmd, "include_relative") == 0);
  1414. expand_tilde(&fname);
  1415. success = (process_file(fname, include_relative) == EXIT_SUCCESS);
  1416. free(fname);
  1417. }
  1418. }
  1419. else
  1420. ignore_slash_options(scan_state);
  1421. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1422. }
  1423. /*
  1424. * \if <expr> -- beginning of an \if..\endif block
  1425. *
  1426. * <expr> is parsed as a boolean expression. Invalid expressions will emit a
  1427. * warning and be treated as false. Statements that follow a false expression
  1428. * will be parsed but ignored. Note that in the case where an \if statement
  1429. * is itself within an inactive section of a block, then the entire inner
  1430. * \if..\endif block will be parsed but ignored.
  1431. */
  1432. static backslashResult
  1433. exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
  1434. PQExpBuffer query_buf)
  1435. {
  1436. if (conditional_active(cstack))
  1437. {
  1438. /*
  1439. * First, push a new active stack entry; this ensures that the lexer
  1440. * will perform variable substitution and backtick evaluation while
  1441. * scanning the expression. (That should happen anyway, since we know
  1442. * we're in an active outer branch, but let's be sure.)
  1443. */
  1444. conditional_stack_push(cstack, IFSTATE_TRUE);
  1445. /* Remember current query state in case we need to restore later */
  1446. save_query_text_state(scan_state, cstack, query_buf);
  1447. /*
  1448. * Evaluate the expression; if it's false, change to inactive state.
  1449. */
  1450. if (!is_true_boolean_expression(scan_state, "\\if expression"))
  1451. conditional_stack_poke(cstack, IFSTATE_FALSE);
  1452. }
  1453. else
  1454. {
  1455. /*
  1456. * We're within an inactive outer branch, so this entire \if block
  1457. * will be ignored. We don't want to evaluate the expression, so push
  1458. * the "ignored" stack state before scanning it.
  1459. */
  1460. conditional_stack_push(cstack, IFSTATE_IGNORED);
  1461. /* Remember current query state in case we need to restore later */
  1462. save_query_text_state(scan_state, cstack, query_buf);
  1463. ignore_boolean_expression(scan_state);
  1464. }
  1465. return PSQL_CMD_SKIP_LINE;
  1466. }
  1467. /*
  1468. * \elif <expr> -- alternative branch in an \if..\endif block
  1469. *
  1470. * <expr> is evaluated the same as in \if <expr>.
  1471. */
  1472. static backslashResult
  1473. exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
  1474. PQExpBuffer query_buf)
  1475. {
  1476. bool success = true;
  1477. switch (conditional_stack_peek(cstack))
  1478. {
  1479. case IFSTATE_TRUE:
  1480. /*
  1481. * Just finished active branch of this \if block. Update saved
  1482. * state so we will keep whatever data was put in query_buf by the
  1483. * active branch.
  1484. */
  1485. save_query_text_state(scan_state, cstack, query_buf);
  1486. /*
  1487. * Discard \elif expression and ignore the rest until \endif.
  1488. * Switch state before reading expression to ensure proper lexer
  1489. * behavior.
  1490. */
  1491. conditional_stack_poke(cstack, IFSTATE_IGNORED);
  1492. ignore_boolean_expression(scan_state);
  1493. break;
  1494. case IFSTATE_FALSE:
  1495. /*
  1496. * Discard any query text added by the just-skipped branch.
  1497. */
  1498. discard_query_text(scan_state, cstack, query_buf);
  1499. /*
  1500. * Have not yet found a true expression in this \if block, so this
  1501. * might be the first. We have to change state before examining
  1502. * the expression, or the lexer won't do the right thing.
  1503. */
  1504. conditional_stack_poke(cstack, IFSTATE_TRUE);
  1505. if (!is_true_boolean_expression(scan_state, "\\elif expression"))
  1506. conditional_stack_poke(cstack, IFSTATE_FALSE);
  1507. break;
  1508. case IFSTATE_IGNORED:
  1509. /*
  1510. * Discard any query text added by the just-skipped branch.
  1511. */
  1512. discard_query_text(scan_state, cstack, query_buf);
  1513. /*
  1514. * Skip expression and move on. Either the \if block already had
  1515. * an active section, or whole block is being skipped.
  1516. */
  1517. ignore_boolean_expression(scan_state);
  1518. break;
  1519. case IFSTATE_ELSE_TRUE:
  1520. case IFSTATE_ELSE_FALSE:
  1521. pg_log_error("\\elif: cannot occur after \\else");
  1522. success = false;
  1523. break;
  1524. case IFSTATE_NONE:
  1525. /* no \if to elif from */
  1526. pg_log_error("\\elif: no matching \\if");
  1527. success = false;
  1528. break;
  1529. }
  1530. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1531. }
  1532. /*
  1533. * \else -- final alternative in an \if..\endif block
  1534. *
  1535. * Statements within an \else branch will only be executed if
  1536. * all previous \if and \elif expressions evaluated to false
  1537. * and the block was not itself being ignored.
  1538. */
  1539. static backslashResult
  1540. exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
  1541. PQExpBuffer query_buf)
  1542. {
  1543. bool success = true;
  1544. switch (conditional_stack_peek(cstack))
  1545. {
  1546. case IFSTATE_TRUE:
  1547. /*
  1548. * Just finished active branch of this \if block. Update saved
  1549. * state so we will keep whatever data was put in query_buf by the
  1550. * active branch.
  1551. */
  1552. save_query_text_state(scan_state, cstack, query_buf);
  1553. /* Now skip the \else branch */
  1554. conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
  1555. break;
  1556. case IFSTATE_FALSE:
  1557. /*
  1558. * Discard any query text added by the just-skipped branch.
  1559. */
  1560. discard_query_text(scan_state, cstack, query_buf);
  1561. /*
  1562. * We've not found any true \if or \elif expression, so execute
  1563. * the \else branch.
  1564. */
  1565. conditional_stack_poke(cstack, IFSTATE_ELSE_TRUE);
  1566. break;
  1567. case IFSTATE_IGNORED:
  1568. /*
  1569. * Discard any query text added by the just-skipped branch.
  1570. */
  1571. discard_query_text(scan_state, cstack, query_buf);
  1572. /*
  1573. * Either we previously processed the active branch of this \if,
  1574. * or the whole \if block is being skipped. Either way, skip the
  1575. * \else branch.
  1576. */
  1577. conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
  1578. break;
  1579. case IFSTATE_ELSE_TRUE:
  1580. case IFSTATE_ELSE_FALSE:
  1581. pg_log_error("\\else: cannot occur after \\else");
  1582. success = false;
  1583. break;
  1584. case IFSTATE_NONE:
  1585. /* no \if to else from */
  1586. pg_log_error("\\else: no matching \\if");
  1587. success = false;
  1588. break;
  1589. }
  1590. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1591. }
  1592. /*
  1593. * \endif -- ends an \if...\endif block
  1594. */
  1595. static backslashResult
  1596. exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
  1597. PQExpBuffer query_buf)
  1598. {
  1599. bool success = true;
  1600. switch (conditional_stack_peek(cstack))
  1601. {
  1602. case IFSTATE_TRUE:
  1603. case IFSTATE_ELSE_TRUE:
  1604. /* Close the \if block, keeping the query text */
  1605. success = conditional_stack_pop(cstack);
  1606. Assert(success);
  1607. break;
  1608. case IFSTATE_FALSE:
  1609. case IFSTATE_IGNORED:
  1610. case IFSTATE_ELSE_FALSE:
  1611. /*
  1612. * Discard any query text added by the just-skipped branch.
  1613. */
  1614. discard_query_text(scan_state, cstack, query_buf);
  1615. /* Close the \if block */
  1616. success = conditional_stack_pop(cstack);
  1617. Assert(success);
  1618. break;
  1619. case IFSTATE_NONE:
  1620. /* no \if to end */
  1621. pg_log_error("\\endif: no matching \\if");
  1622. success = false;
  1623. break;
  1624. }
  1625. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1626. }
  1627. /*
  1628. * \l -- list databases
  1629. */
  1630. static backslashResult
  1631. exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd)
  1632. {
  1633. bool success = true;
  1634. if (active_branch)
  1635. {
  1636. char *pattern;
  1637. bool show_verbose;
  1638. pattern = psql_scan_slash_option(scan_state,
  1639. OT_NORMAL, NULL, true);
  1640. show_verbose = strchr(cmd, '+') ? true : false;
  1641. success = listAllDbs(pattern, show_verbose);
  1642. if (pattern)
  1643. free(pattern);
  1644. }
  1645. else
  1646. ignore_slash_options(scan_state);
  1647. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1648. }
  1649. /*
  1650. * \lo_* -- large object operations
  1651. */
  1652. static backslashResult
  1653. exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
  1654. {
  1655. backslashResult status = PSQL_CMD_SKIP_LINE;
  1656. bool success = true;
  1657. if (active_branch)
  1658. {
  1659. char *opt1,
  1660. *opt2;
  1661. opt1 = psql_scan_slash_option(scan_state,
  1662. OT_NORMAL, NULL, true);
  1663. opt2 = psql_scan_slash_option(scan_state,
  1664. OT_NORMAL, NULL, true);
  1665. if (strcmp(cmd + 3, "export") == 0)
  1666. {
  1667. if (!opt2)
  1668. {
  1669. pg_log_error("\\%s: missing required argument", cmd);
  1670. success = false;
  1671. }
  1672. else
  1673. {
  1674. expand_tilde(&opt2);
  1675. success = do_lo_export(opt1, opt2);
  1676. }
  1677. }
  1678. else if (strcmp(cmd + 3, "import") == 0)
  1679. {
  1680. if (!opt1)
  1681. {
  1682. pg_log_error("\\%s: missing required argument", cmd);
  1683. success = false;
  1684. }
  1685. else
  1686. {
  1687. expand_tilde(&opt1);
  1688. success = do_lo_import(opt1, opt2);
  1689. }
  1690. }
  1691. else if (strcmp(cmd + 3, "list") == 0)
  1692. success = do_lo_list();
  1693. else if (strcmp(cmd + 3, "unlink") == 0)
  1694. {
  1695. if (!opt1)
  1696. {
  1697. pg_log_error("\\%s: missing required argument", cmd);
  1698. success = false;
  1699. }
  1700. else
  1701. success = do_lo_unlink(opt1);
  1702. }
  1703. else
  1704. status = PSQL_CMD_UNKNOWN;
  1705. free(opt1);
  1706. free(opt2);
  1707. }
  1708. else
  1709. ignore_slash_options(scan_state);
  1710. if (!success)
  1711. status = PSQL_CMD_ERROR;
  1712. return status;
  1713. }
  1714. /*
  1715. * \o -- set query output
  1716. */
  1717. static backslashResult
  1718. exec_command_out(PsqlScanState scan_state, bool active_branch)
  1719. {
  1720. bool success = true;
  1721. if (active_branch)
  1722. {
  1723. char *fname = psql_scan_slash_option(scan_state,
  1724. OT_FILEPIPE, NULL, true);
  1725. expand_tilde(&fname);
  1726. success = setQFout(fname);
  1727. free(fname);
  1728. }
  1729. else
  1730. ignore_slash_filepipe(scan_state);
  1731. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1732. }
  1733. /*
  1734. * \p -- print the current query buffer
  1735. */
  1736. static backslashResult
  1737. exec_command_print(PsqlScanState scan_state, bool active_branch,
  1738. PQExpBuffer query_buf, PQExpBuffer previous_buf)
  1739. {
  1740. if (active_branch)
  1741. {
  1742. /*
  1743. * We want to print the same thing \g would execute, but not to change
  1744. * the query buffer state; so we can't use copy_previous_query().
  1745. * Also, beware of possibility that buffer pointers are NULL.
  1746. */
  1747. if (query_buf && query_buf->len > 0)
  1748. puts(query_buf->data);
  1749. else if (previous_buf && previous_buf->len > 0)
  1750. puts(previous_buf->data);
  1751. else if (!pset.quiet)
  1752. puts(_("Query buffer is empty."));
  1753. fflush(stdout);
  1754. }
  1755. return PSQL_CMD_SKIP_LINE;
  1756. }
  1757. /*
  1758. * \password -- set user password
  1759. */
  1760. static backslashResult
  1761. exec_command_password(PsqlScanState scan_state, bool active_branch)
  1762. {
  1763. bool success = true;
  1764. if (active_branch)
  1765. {
  1766. char *opt0 = psql_scan_slash_option(scan_state,
  1767. OT_SQLID, NULL, true);
  1768. char pw1[100];
  1769. char pw2[100];
  1770. simple_prompt("Enter new password: ", pw1, sizeof(pw1), false);
  1771. simple_prompt("Enter it again: ", pw2, sizeof(pw2), false);
  1772. if (strcmp(pw1, pw2) != 0)
  1773. {
  1774. pg_log_error("Passwords didn't match.");
  1775. success = false;
  1776. }
  1777. else
  1778. {
  1779. char *user;
  1780. char *encrypted_password;
  1781. if (opt0)
  1782. user = opt0;
  1783. else
  1784. user = PQuser(pset.db);
  1785. encrypted_password = PQencryptPasswordConn(pset.db, pw1, user, NULL);
  1786. if (!encrypted_password)
  1787. {
  1788. pg_log_info("%s", PQerrorMessage(pset.db));
  1789. success = false;
  1790. }
  1791. else
  1792. {
  1793. PQExpBufferData buf;
  1794. PGresult *res;
  1795. initPQExpBuffer(&buf);
  1796. printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
  1797. fmtId(user));
  1798. appendStringLiteralConn(&buf, encrypted_password, pset.db);
  1799. res = PSQLexec(buf.data);
  1800. termPQExpBuffer(&buf);
  1801. if (!res)
  1802. success = false;
  1803. else
  1804. PQclear(res);
  1805. PQfreemem(encrypted_password);
  1806. }
  1807. }
  1808. if (opt0)
  1809. free(opt0);
  1810. }
  1811. else
  1812. ignore_slash_options(scan_state);
  1813. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1814. }
  1815. /*
  1816. * \prompt -- prompt and set variable
  1817. */
  1818. static backslashResult
  1819. exec_command_prompt(PsqlScanState scan_state, bool active_branch,
  1820. const char *cmd)
  1821. {
  1822. bool success = true;
  1823. if (active_branch)
  1824. {
  1825. char *opt,
  1826. *prompt_text = NULL;
  1827. char *arg1,
  1828. *arg2;
  1829. arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
  1830. arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
  1831. if (!arg1)
  1832. {
  1833. pg_log_error("\\%s: missing required argument", cmd);
  1834. success = false;
  1835. }
  1836. else
  1837. {
  1838. char *result;
  1839. if (arg2)
  1840. {
  1841. prompt_text = arg1;
  1842. opt = arg2;
  1843. }
  1844. else
  1845. opt = arg1;
  1846. if (!pset.inputfile)
  1847. {
  1848. result = (char *) pg_malloc(4096);
  1849. simple_prompt(prompt_text, result, 4096, true);
  1850. }
  1851. else
  1852. {
  1853. if (prompt_text)
  1854. {
  1855. fputs(prompt_text, stdout);
  1856. fflush(stdout);
  1857. }
  1858. result = gets_fromFile(stdin);
  1859. if (!result)
  1860. {
  1861. pg_log_error("\\%s: could not read value for variable",
  1862. cmd);
  1863. success = false;
  1864. }
  1865. }
  1866. if (result &&
  1867. !SetVariable(pset.vars, opt, result))
  1868. success = false;
  1869. if (result)
  1870. free(result);
  1871. if (prompt_text)
  1872. free(prompt_text);
  1873. free(opt);
  1874. }
  1875. }
  1876. else
  1877. ignore_slash_options(scan_state);
  1878. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1879. }
  1880. /*
  1881. * \pset -- set printing parameters
  1882. */
  1883. static backslashResult
  1884. exec_command_pset(PsqlScanState scan_state, bool active_branch)
  1885. {
  1886. bool success = true;
  1887. if (active_branch)
  1888. {
  1889. char *opt0 = psql_scan_slash_option(scan_state,
  1890. OT_NORMAL, NULL, false);
  1891. char *opt1 = psql_scan_slash_option(scan_state,
  1892. OT_NORMAL, NULL, false);
  1893. if (!opt0)
  1894. {
  1895. /* list all variables */
  1896. int i;
  1897. static const char *const my_list[] = {
  1898. "border", "columns", "csv_fieldsep", "expanded", "fieldsep",
  1899. "fieldsep_zero", "footer", "format", "linestyle", "null",
  1900. "numericlocale", "pager", "pager_min_lines",
  1901. "recordsep", "recordsep_zero",
  1902. "tableattr", "title", "tuples_only",
  1903. "unicode_border_linestyle",
  1904. "unicode_column_linestyle",
  1905. "unicode_header_linestyle",
  1906. NULL
  1907. };
  1908. for (i = 0; my_list[i] != NULL; i++)
  1909. {
  1910. char *val = pset_value_string(my_list[i], &pset.popt);
  1911. printf("%-24s %s\n", my_list[i], val);
  1912. free(val);
  1913. }
  1914. success = true;
  1915. }
  1916. else
  1917. success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
  1918. free(opt0);
  1919. free(opt1);
  1920. }
  1921. else
  1922. ignore_slash_options(scan_state);
  1923. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1924. }
  1925. /*
  1926. * \q or \quit -- exit psql
  1927. */
  1928. static backslashResult
  1929. exec_command_quit(PsqlScanState scan_state, bool active_branch)
  1930. {
  1931. backslashResult status = PSQL_CMD_SKIP_LINE;
  1932. if (active_branch)
  1933. status = PSQL_CMD_TERMINATE;
  1934. return status;
  1935. }
  1936. /*
  1937. * \r -- reset (clear) the query buffer
  1938. */
  1939. static backslashResult
  1940. exec_command_reset(PsqlScanState scan_state, bool active_branch,
  1941. PQExpBuffer query_buf)
  1942. {
  1943. if (active_branch)
  1944. {
  1945. resetPQExpBuffer(query_buf);
  1946. psql_scan_reset(scan_state);
  1947. if (!pset.quiet)
  1948. puts(_("Query buffer reset (cleared)."));
  1949. }
  1950. return PSQL_CMD_SKIP_LINE;
  1951. }
  1952. /*
  1953. * \s -- save history in a file or show it on the screen
  1954. */
  1955. static backslashResult
  1956. exec_command_s(PsqlScanState scan_state, bool active_branch)
  1957. {
  1958. bool success = true;
  1959. if (active_branch)
  1960. {
  1961. char *fname = psql_scan_slash_option(scan_state,
  1962. OT_NORMAL, NULL, true);
  1963. expand_tilde(&fname);
  1964. success = printHistory(fname, pset.popt.topt.pager);
  1965. if (success && !pset.quiet && fname)
  1966. printf(_("Wrote history to file \"%s\".\n"), fname);
  1967. if (!fname)
  1968. putchar('\n');
  1969. free(fname);
  1970. }
  1971. else
  1972. ignore_slash_options(scan_state);
  1973. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  1974. }
  1975. /*
  1976. * \set -- set variable
  1977. */
  1978. static backslashResult
  1979. exec_command_set(PsqlScanState scan_state, bool active_branch)
  1980. {
  1981. bool success = true;
  1982. if (active_branch)
  1983. {
  1984. char *opt0 = psql_scan_slash_option(scan_state,
  1985. OT_NORMAL, NULL, false);
  1986. if (!opt0)
  1987. {
  1988. /* list all variables */
  1989. PrintVariables(pset.vars);
  1990. success = true;
  1991. }
  1992. else
  1993. {
  1994. /*
  1995. * Set variable to the concatenation of the arguments.
  1996. */
  1997. char *newval;
  1998. char *opt;
  1999. opt = psql_scan_slash_option(scan_state,
  2000. OT_NORMAL, NULL, false);
  2001. newval = pg_strdup(opt ? opt : "");
  2002. free(opt);
  2003. while ((opt = psql_scan_slash_option(scan_state,
  2004. OT_NORMAL, NULL, false)))
  2005. {
  2006. newval = pg_realloc(newval, strlen(newval) + strlen(opt) + 1);
  2007. strcat(newval, opt);
  2008. free(opt);
  2009. }
  2010. if (!SetVariable(pset.vars, opt0, newval))
  2011. success = false;
  2012. free(newval);
  2013. }
  2014. free(opt0);
  2015. }
  2016. else
  2017. ignore_slash_options(scan_state);
  2018. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2019. }
  2020. /*
  2021. * \setenv -- set environment variable
  2022. */
  2023. static backslashResult
  2024. exec_command_setenv(PsqlScanState scan_state, bool active_branch,
  2025. const char *cmd)
  2026. {
  2027. bool success = true;
  2028. if (active_branch)
  2029. {
  2030. char *envvar = psql_scan_slash_option(scan_state,
  2031. OT_NORMAL, NULL, false);
  2032. char *envval = psql_scan_slash_option(scan_state,
  2033. OT_NORMAL, NULL, false);
  2034. if (!envvar)
  2035. {
  2036. pg_log_error("\\%s: missing required argument", cmd);
  2037. success = false;
  2038. }
  2039. else if (strchr(envvar, '=') != NULL)
  2040. {
  2041. pg_log_error("\\%s: environment variable name must not contain \"=\"",
  2042. cmd);
  2043. success = false;
  2044. }
  2045. else if (!envval)
  2046. {
  2047. /* No argument - unset the environment variable */
  2048. unsetenv(envvar);
  2049. success = true;
  2050. }
  2051. else
  2052. {
  2053. /* Set variable to the value of the next argument */
  2054. char *newval;
  2055. newval = psprintf("%s=%s", envvar, envval);
  2056. putenv(newval);
  2057. success = true;
  2058. /*
  2059. * Do not free newval here, it will screw up the environment if
  2060. * you do. See putenv man page for details. That means we leak a
  2061. * bit of memory here, but not enough to worry about.
  2062. */
  2063. }
  2064. free(envvar);
  2065. free(envval);
  2066. }
  2067. else
  2068. ignore_slash_options(scan_state);
  2069. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2070. }
  2071. /*
  2072. * \sf/\sv -- show a function/view's source code
  2073. */
  2074. static backslashResult
  2075. exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
  2076. const char *cmd, bool is_func)
  2077. {
  2078. backslashResult status = PSQL_CMD_SKIP_LINE;
  2079. if (active_branch)
  2080. {
  2081. bool show_linenumbers = (strchr(cmd, '+') != NULL);
  2082. PQExpBuffer buf;
  2083. char *obj_desc;
  2084. Oid obj_oid = InvalidOid;
  2085. EditableObjectType eot = is_func ? EditableFunction : EditableView;
  2086. buf = createPQExpBuffer();
  2087. obj_desc = psql_scan_slash_option(scan_state,
  2088. OT_WHOLE_LINE, NULL, true);
  2089. if (pset.sversion < (is_func ? 80400 : 70400))
  2090. {
  2091. char sverbuf[32];
  2092. formatPGVersionNumber(pset.sversion, false,
  2093. sverbuf, sizeof(sverbuf));
  2094. if (is_func)
  2095. pg_log_error("The server (version %s) does not support showing function source.",
  2096. sverbuf);
  2097. else
  2098. pg_log_error("The server (version %s) does not support showing view definitions.",
  2099. sverbuf);
  2100. status = PSQL_CMD_ERROR;
  2101. }
  2102. else if (!obj_desc)
  2103. {
  2104. if (is_func)
  2105. pg_log_error("function name is required");
  2106. else
  2107. pg_log_error("view name is required");
  2108. status = PSQL_CMD_ERROR;
  2109. }
  2110. else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
  2111. {
  2112. /* error already reported */
  2113. status = PSQL_CMD_ERROR;
  2114. }
  2115. else if (!get_create_object_cmd(eot, obj_oid, buf))
  2116. {
  2117. /* error already reported */
  2118. status = PSQL_CMD_ERROR;
  2119. }
  2120. else
  2121. {
  2122. FILE *output;
  2123. bool is_pager;
  2124. /* Select output stream: stdout, pager, or file */
  2125. if (pset.queryFout == stdout)
  2126. {
  2127. /* count lines in function to see if pager is needed */
  2128. int lineno = count_lines_in_buf(buf);
  2129. output = PageOutput(lineno, &(pset.popt.topt));
  2130. is_pager = true;
  2131. }
  2132. else
  2133. {
  2134. /* use previously set output file, without pager */
  2135. output = pset.queryFout;
  2136. is_pager = false;
  2137. }
  2138. if (show_linenumbers)
  2139. {
  2140. /*
  2141. * For functions, lineno "1" should correspond to the first
  2142. * line of the function body. We expect that
  2143. * pg_get_functiondef() will emit that on a line beginning
  2144. * with "AS ", and that there can be no such line before the
  2145. * real start of the function body.
  2146. */
  2147. print_with_linenumbers(output, buf->data,
  2148. is_func ? "AS " : NULL);
  2149. }
  2150. else
  2151. {
  2152. /* just send the definition to output */
  2153. fputs(buf->data, output);
  2154. }
  2155. if (is_pager)
  2156. ClosePager(output);
  2157. }
  2158. if (obj_desc)
  2159. free(obj_desc);
  2160. destroyPQExpBuffer(buf);
  2161. }
  2162. else
  2163. ignore_slash_whole_line(scan_state);
  2164. return status;
  2165. }
  2166. /*
  2167. * \t -- turn off table headers and row count
  2168. */
  2169. static backslashResult
  2170. exec_command_t(PsqlScanState scan_state, bool active_branch)
  2171. {
  2172. bool success = true;
  2173. if (active_branch)
  2174. {
  2175. char *opt = psql_scan_slash_option(scan_state,
  2176. OT_NORMAL, NULL, true);
  2177. success = do_pset("tuples_only", opt, &pset.popt, pset.quiet);
  2178. free(opt);
  2179. }
  2180. else
  2181. ignore_slash_options(scan_state);
  2182. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2183. }
  2184. /*
  2185. * \T -- define html <table ...> attributes
  2186. */
  2187. static backslashResult
  2188. exec_command_T(PsqlScanState scan_state, bool active_branch)
  2189. {
  2190. bool success = true;
  2191. if (active_branch)
  2192. {
  2193. char *value = psql_scan_slash_option(scan_state,
  2194. OT_NORMAL, NULL, false);
  2195. success = do_pset("tableattr", value, &pset.popt, pset.quiet);
  2196. free(value);
  2197. }
  2198. else
  2199. ignore_slash_options(scan_state);
  2200. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2201. }
  2202. /*
  2203. * \timing -- enable/disable timing of queries
  2204. */
  2205. static backslashResult
  2206. exec_command_timing(PsqlScanState scan_state, bool active_branch)
  2207. {
  2208. bool success = true;
  2209. if (active_branch)
  2210. {
  2211. char *opt = psql_scan_slash_option(scan_state,
  2212. OT_NORMAL, NULL, false);
  2213. if (opt)
  2214. success = ParseVariableBool(opt, "\\timing", &pset.timing);
  2215. else
  2216. pset.timing = !pset.timing;
  2217. if (!pset.quiet)
  2218. {
  2219. if (pset.timing)
  2220. puts(_("Timing is on."));
  2221. else
  2222. puts(_("Timing is off."));
  2223. }
  2224. free(opt);
  2225. }
  2226. else
  2227. ignore_slash_options(scan_state);
  2228. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2229. }
  2230. /*
  2231. * \unset -- unset variable
  2232. */
  2233. static backslashResult
  2234. exec_command_unset(PsqlScanState scan_state, bool active_branch,
  2235. const char *cmd)
  2236. {
  2237. bool success = true;
  2238. if (active_branch)
  2239. {
  2240. char *opt = psql_scan_slash_option(scan_state,
  2241. OT_NORMAL, NULL, false);
  2242. if (!opt)
  2243. {
  2244. pg_log_error("\\%s: missing required argument", cmd);
  2245. success = false;
  2246. }
  2247. else if (!SetVariable(pset.vars, opt, NULL))
  2248. success = false;
  2249. free(opt);
  2250. }
  2251. else
  2252. ignore_slash_options(scan_state);
  2253. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2254. }
  2255. /*
  2256. * \w -- write query buffer to file
  2257. */
  2258. static backslashResult
  2259. exec_command_write(PsqlScanState scan_state, bool active_branch,
  2260. const char *cmd,
  2261. PQExpBuffer query_buf, PQExpBuffer previous_buf)
  2262. {
  2263. backslashResult status = PSQL_CMD_SKIP_LINE;
  2264. if (active_branch)
  2265. {
  2266. char *fname = psql_scan_slash_option(scan_state,
  2267. OT_FILEPIPE, NULL, true);
  2268. FILE *fd = NULL;
  2269. bool is_pipe = false;
  2270. if (!query_buf)
  2271. {
  2272. pg_log_error("no query buffer");
  2273. status = PSQL_CMD_ERROR;
  2274. }
  2275. else
  2276. {
  2277. if (!fname)
  2278. {
  2279. pg_log_error("\\%s: missing required argument", cmd);
  2280. status = PSQL_CMD_ERROR;
  2281. }
  2282. else
  2283. {
  2284. expand_tilde(&fname);
  2285. if (fname[0] == '|')
  2286. {
  2287. is_pipe = true;
  2288. disable_sigpipe_trap();
  2289. fd = popen(&fname[1], "w");
  2290. }
  2291. else
  2292. {
  2293. canonicalize_path(fname);
  2294. fd = fopen(fname, "w");
  2295. }
  2296. if (!fd)
  2297. {
  2298. pg_log_error("%s: %m", fname);
  2299. status = PSQL_CMD_ERROR;
  2300. }
  2301. }
  2302. }
  2303. if (fd)
  2304. {
  2305. int result;
  2306. /*
  2307. * We want to print the same thing \g would execute, but not to
  2308. * change the query buffer state; so we can't use
  2309. * copy_previous_query(). Also, beware of possibility that buffer
  2310. * pointers are NULL.
  2311. */
  2312. if (query_buf && query_buf->len > 0)
  2313. fprintf(fd, "%s\n", query_buf->data);
  2314. else if (previous_buf && previous_buf->len > 0)
  2315. fprintf(fd, "%s\n", previous_buf->data);
  2316. if (is_pipe)
  2317. result = pclose(fd);
  2318. else
  2319. result = fclose(fd);
  2320. if (result == EOF)
  2321. {
  2322. pg_log_error("%s: %m", fname);
  2323. status = PSQL_CMD_ERROR;
  2324. }
  2325. }
  2326. if (is_pipe)
  2327. restore_sigpipe_trap();
  2328. free(fname);
  2329. }
  2330. else
  2331. ignore_slash_filepipe(scan_state);
  2332. return status;
  2333. }
  2334. /*
  2335. * \watch -- execute a query every N seconds
  2336. */
  2337. static backslashResult
  2338. exec_command_watch(PsqlScanState scan_state, bool active_branch,
  2339. PQExpBuffer query_buf, PQExpBuffer previous_buf)
  2340. {
  2341. bool success = true;
  2342. if (active_branch)
  2343. {
  2344. char *opt = psql_scan_slash_option(scan_state,
  2345. OT_NORMAL, NULL, true);
  2346. double sleep = 2;
  2347. /* Convert optional sleep-length argument */
  2348. if (opt)
  2349. {
  2350. sleep = strtod(opt, NULL);
  2351. if (sleep <= 0)
  2352. sleep = 1;
  2353. free(opt);
  2354. }
  2355. /* If query_buf is empty, recall and execute previous query */
  2356. copy_previous_query(query_buf, previous_buf);
  2357. success = do_watch(query_buf, sleep);
  2358. /* Reset the query buffer as though for \r */
  2359. resetPQExpBuffer(query_buf);
  2360. psql_scan_reset(scan_state);
  2361. }
  2362. else
  2363. ignore_slash_options(scan_state);
  2364. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2365. }
  2366. /*
  2367. * \x -- set or toggle expanded table representation
  2368. */
  2369. static backslashResult
  2370. exec_command_x(PsqlScanState scan_state, bool active_branch)
  2371. {
  2372. bool success = true;
  2373. if (active_branch)
  2374. {
  2375. char *opt = psql_scan_slash_option(scan_state,
  2376. OT_NORMAL, NULL, true);
  2377. success = do_pset("expanded", opt, &pset.popt, pset.quiet);
  2378. free(opt);
  2379. }
  2380. else
  2381. ignore_slash_options(scan_state);
  2382. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2383. }
  2384. /*
  2385. * \z -- list table privileges (equivalent to \dp)
  2386. */
  2387. static backslashResult
  2388. exec_command_z(PsqlScanState scan_state, bool active_branch)
  2389. {
  2390. bool success = true;
  2391. if (active_branch)
  2392. {
  2393. char *pattern = psql_scan_slash_option(scan_state,
  2394. OT_NORMAL, NULL, true);
  2395. success = permissionsList(pattern);
  2396. if (pattern)
  2397. free(pattern);
  2398. }
  2399. else
  2400. ignore_slash_options(scan_state);
  2401. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2402. }
  2403. /*
  2404. * \! -- execute shell command
  2405. */
  2406. static backslashResult
  2407. exec_command_shell_escape(PsqlScanState scan_state, bool active_branch)
  2408. {
  2409. bool success = true;
  2410. if (active_branch)
  2411. {
  2412. char *opt = psql_scan_slash_option(scan_state,
  2413. OT_WHOLE_LINE, NULL, false);
  2414. success = do_shell(opt);
  2415. free(opt);
  2416. }
  2417. else
  2418. ignore_slash_whole_line(scan_state);
  2419. return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
  2420. }
  2421. /*
  2422. * \? -- print help about backslash commands
  2423. */
  2424. static backslashResult
  2425. exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch)
  2426. {
  2427. if (active_branch)
  2428. {
  2429. char *opt0 = psql_scan_slash_option(scan_state,
  2430. OT_NORMAL, NULL, false);
  2431. if (!opt0 || strcmp(opt0, "commands") == 0)
  2432. slashUsage(pset.popt.topt.pager);
  2433. else if (strcmp(opt0, "options") == 0)
  2434. usage(pset.popt.topt.pager);
  2435. else if (strcmp(opt0, "variables") == 0)
  2436. helpVariables(pset.popt.topt.pager);
  2437. else
  2438. slashUsage(pset.popt.topt.pager);
  2439. if (opt0)
  2440. free(opt0);
  2441. }
  2442. else
  2443. ignore_slash_options(scan_state);
  2444. return PSQL_CMD_SKIP_LINE;
  2445. }
  2446. /*
  2447. * Read and interpret an argument to the \connect slash command.
  2448. *
  2449. * Returns a malloc'd string, or NULL if no/empty argument.
  2450. */
  2451. static char *
  2452. read_connect_arg(PsqlScanState scan_state)
  2453. {
  2454. char *result;
  2455. char quote;
  2456. /*
  2457. * Ideally we should treat the arguments as SQL identifiers. But for
  2458. * backwards compatibility with 7.2 and older pg_dump files, we have to
  2459. * take unquoted arguments verbatim (don't downcase them). For now,
  2460. * double-quoted arguments may be stripped of double quotes (as if SQL
  2461. * identifiers). By 7.4 or so, pg_dump files can be expected to
  2462. * double-quote all mixed-case \connect arguments, and then we can get rid
  2463. * of OT_SQLIDHACK.
  2464. */
  2465. result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, &quote, true);
  2466. if (!result)
  2467. return NULL;
  2468. if (quote)
  2469. return result;
  2470. if (*result == '\0' || strcmp(result, "-") == 0)
  2471. {
  2472. free(result);
  2473. return NULL;
  2474. }
  2475. return result;
  2476. }
  2477. /*
  2478. * Read a boolean expression, return it as a PQExpBuffer string.
  2479. *
  2480. * Note: anything more or less than one token will certainly fail to be
  2481. * parsed by ParseVariableBool, so we don't worry about complaining here.
  2482. * This routine's return data structure will need to be rethought anyway
  2483. * to support likely future extensions such as "\if defined VARNAME".
  2484. */
  2485. static PQExpBuffer
  2486. gather_boolean_expression(PsqlScanState scan_state)
  2487. {
  2488. PQExpBuffer exp_buf = createPQExpBuffer();
  2489. int num_options = 0;
  2490. char *value;
  2491. /* collect all arguments for the conditional command into exp_buf */
  2492. while ((value = psql_scan_slash_option(scan_state,
  2493. OT_NORMAL, NULL, false)) != NULL)
  2494. {
  2495. /* add spaces between tokens */
  2496. if (num_options > 0)
  2497. appendPQExpBufferChar(exp_buf, ' ');
  2498. appendPQExpBufferStr(exp_buf, value);
  2499. num_options++;
  2500. free(value);
  2501. }
  2502. return exp_buf;
  2503. }
  2504. /*
  2505. * Read a boolean expression, return true if the expression
  2506. * was a valid boolean expression that evaluated to true.
  2507. * Otherwise return false.
  2508. *
  2509. * Note: conditional stack's top state must be active, else lexer will
  2510. * fail to expand variables and backticks.
  2511. */
  2512. static bool
  2513. is_true_boolean_expression(PsqlScanState scan_state, const char *name)
  2514. {
  2515. PQExpBuffer buf = gather_boolean_expression(scan_state);
  2516. bool value = false;
  2517. bool success = ParseVariableBool(buf->data, name, &value);
  2518. destroyPQExpBuffer(buf);
  2519. return success && value;
  2520. }
  2521. /*
  2522. * Read a boolean expression, but do nothing with it.
  2523. *
  2524. * Note: conditional stack's top state must be INACTIVE, else lexer will
  2525. * expand variables and backticks, which we do not want here.
  2526. */
  2527. static void
  2528. ignore_boolean_expression(PsqlScanState scan_state)
  2529. {
  2530. PQExpBuffer buf = gather_boolean_expression(scan_state);
  2531. destroyPQExpBuffer(buf);
  2532. }
  2533. /*
  2534. * Read and discard "normal" slash command options.
  2535. *
  2536. * This should be used for inactive-branch processing of any slash command
  2537. * that eats one or more OT_NORMAL, OT_SQLID, or OT_SQLIDHACK parameters.
  2538. * We don't need to worry about exactly how many it would eat, since the
  2539. * cleanup logic in HandleSlashCmds would silently discard any extras anyway.
  2540. */
  2541. static void
  2542. ignore_slash_options(PsqlScanState scan_state)
  2543. {
  2544. char *arg;
  2545. while ((arg = psql_scan_slash_option(scan_state,
  2546. OT_NORMAL, NULL, false)) != NULL)
  2547. free(arg);
  2548. }
  2549. /*
  2550. * Read and discard FILEPIPE slash command argument.
  2551. *
  2552. * This *MUST* be used for inactive-branch processing of any slash command
  2553. * that takes an OT_FILEPIPE option. Otherwise we might consume a different
  2554. * amount of option text in active and inactive cases.
  2555. */
  2556. static void
  2557. ignore_slash_filepipe(PsqlScanState scan_state)
  2558. {
  2559. char *arg = psql_scan_slash_option(scan_state,
  2560. OT_FILEPIPE, NULL, false);
  2561. if (arg)
  2562. free(arg);
  2563. }
  2564. /*
  2565. * Read and discard whole-line slash command argument.
  2566. *
  2567. * This *MUST* be used for inactive-branch processing of any slash command
  2568. * that takes an OT_WHOLE_LINE option. Otherwise we might consume a different
  2569. * amount of option text in active and inactive cases.
  2570. */
  2571. static void
  2572. ignore_slash_whole_line(PsqlScanState scan_state)
  2573. {
  2574. char *arg = psql_scan_slash_option(scan_state,
  2575. OT_WHOLE_LINE, NULL, false);
  2576. if (arg)
  2577. free(arg);
  2578. }
  2579. /*
  2580. * Return true if the command given is a branching command.
  2581. */
  2582. static bool
  2583. is_branching_command(const char *cmd)
  2584. {
  2585. return (strcmp(cmd, "if") == 0 ||
  2586. strcmp(cmd, "elif") == 0 ||
  2587. strcmp(cmd, "else") == 0 ||
  2588. strcmp(cmd, "endif") == 0);
  2589. }
  2590. /*
  2591. * Prepare to possibly restore query buffer to its current state
  2592. * (cf. discard_query_text).
  2593. *
  2594. * We need to remember the length of the query buffer, and the lexer's
  2595. * notion of the parenthesis nesting depth.
  2596. */
  2597. static void
  2598. save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
  2599. PQExpBuffer query_buf)
  2600. {
  2601. if (query_buf)
  2602. conditional_stack_set_query_len(cstack, query_buf->len);
  2603. conditional_stack_set_paren_depth(cstack,
  2604. psql_scan_get_paren_depth(scan_state));
  2605. }
  2606. /*
  2607. * Discard any query text absorbed during an inactive conditional branch.
  2608. *
  2609. * We must discard data that was appended to query_buf during an inactive
  2610. * \if branch. We don't have to do anything there if there's no query_buf.
  2611. *
  2612. * Also, reset the lexer state to the same paren depth there was before.
  2613. * (The rest of its state doesn't need attention, since we could not be
  2614. * inside a comment or literal or partial token.)
  2615. */
  2616. static void
  2617. discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
  2618. PQExpBuffer query_buf)
  2619. {
  2620. if (query_buf)
  2621. {
  2622. int new_len = conditional_stack_get_query_len(cstack);
  2623. Assert(new_len >= 0 && new_len <= query_buf->len);
  2624. query_buf->len = new_len;
  2625. query_buf->data[new_len] = '\0';
  2626. }
  2627. psql_scan_set_paren_depth(scan_state,
  2628. conditional_stack_get_paren_depth(cstack));
  2629. }
  2630. /*
  2631. * If query_buf is empty, copy previous_buf into it.
  2632. *
  2633. * This is used by various slash commands for which re-execution of a
  2634. * previous query is a common usage. For convenience, we allow the
  2635. * case of query_buf == NULL (and do nothing).
  2636. */
  2637. static void
  2638. copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf)
  2639. {
  2640. if (query_buf && query_buf->len == 0)
  2641. appendPQExpBufferStr(query_buf, previous_buf->data);
  2642. }
  2643. /*
  2644. * Ask the user for a password; 'username' is the username the
  2645. * password is for, if one has been explicitly specified. Returns a
  2646. * malloc'd string.
  2647. */
  2648. static char *
  2649. prompt_for_password(const char *username)
  2650. {
  2651. char buf[100];
  2652. if (username == NULL || username[0] == '\0')
  2653. simple_prompt("Password: ", buf, sizeof(buf), false);
  2654. else
  2655. {
  2656. char *prompt_text;
  2657. prompt_text = psprintf(_("Password for user %s: "), username);
  2658. simple_prompt(prompt_text, buf, sizeof(buf), false);
  2659. free(prompt_text);
  2660. }
  2661. return pg_strdup(buf);
  2662. }
  2663. static bool
  2664. param_is_newly_set(const char *old_val, const char *new_val)
  2665. {
  2666. if (new_val == NULL)
  2667. return false;
  2668. if (old_val == NULL || strcmp(old_val, new_val) != 0)
  2669. return true;
  2670. return false;
  2671. }
  2672. /* return whether the connection has 'hostaddr' in its conninfo */
  2673. static bool
  2674. has_hostaddr(PGconn *conn)
  2675. {
  2676. bool used = false;
  2677. PQconninfoOption *ciopt = PQconninfo(conn);
  2678. for (PQconninfoOption *p = ciopt; p->keyword != NULL; p++)
  2679. {
  2680. if (strcmp(p->keyword, "hostaddr") == 0 && p->val != NULL)
  2681. {
  2682. used = true;
  2683. break;
  2684. }
  2685. }
  2686. PQconninfoFree(ciopt);
  2687. return used;
  2688. }
  2689. /*
  2690. * do_connect -- handler for \connect
  2691. *
  2692. * Connects to a database with given parameters. Absent an established
  2693. * connection, all parameters are required. Given -reuse-previous=off or a
  2694. * connection string without -reuse-previous=on, NULL values will pass through
  2695. * to PQconnectdbParams(), so the libpq defaults will be used. Otherwise, NULL
  2696. * values will be replaced with the ones in the current connection.
  2697. *
  2698. * In interactive mode, if connection fails with the given parameters,
  2699. * the old connection will be kept.
  2700. */
  2701. static bool
  2702. do_connect(enum trivalue reuse_previous_specification,
  2703. char *dbname, char *user, char *host, char *port)
  2704. {
  2705. PGconn *o_conn = pset.db,
  2706. *n_conn;
  2707. char *password = NULL;
  2708. char *hostaddr = NULL;
  2709. bool keep_password;
  2710. bool has_connection_string;
  2711. bool reuse_previous;
  2712. PQExpBufferData connstr;
  2713. if (!o_conn && (!dbname || !user || !host || !port))
  2714. {
  2715. /*
  2716. * We don't know the supplied connection parameters and don't want to
  2717. * connect to the wrong database by using defaults, so require all
  2718. * parameters to be specified.
  2719. */
  2720. pg_log_error("All connection parameters must be supplied because no "
  2721. "database connection exists");
  2722. return false;
  2723. }
  2724. has_connection_string = dbname ?
  2725. recognized_connection_string(dbname) : false;
  2726. switch (reuse_previous_specification)
  2727. {
  2728. case TRI_YES:
  2729. reuse_previous = true;
  2730. break;
  2731. case TRI_NO:
  2732. reuse_previous = false;
  2733. break;
  2734. default:
  2735. reuse_previous = !has_connection_string;
  2736. break;
  2737. }
  2738. /* If the old connection does not exist, there is nothing to reuse. */
  2739. if (!o_conn)
  2740. reuse_previous = false;
  2741. /* Silently ignore arguments subsequent to a connection string. */
  2742. if (has_connection_string)
  2743. {
  2744. user = NULL;
  2745. host = NULL;
  2746. port = NULL;
  2747. }
  2748. /*
  2749. * Grab missing values from the old connection. If we grab host (or host
  2750. * is the same as before) and hostaddr was set, grab that too.
  2751. */
  2752. if (reuse_previous)
  2753. {
  2754. if (!user)
  2755. user = PQuser(o_conn);
  2756. if (host && strcmp(host, PQhost(o_conn)) == 0 &&
  2757. has_hostaddr(o_conn))
  2758. {
  2759. hostaddr = PQhostaddr(o_conn);
  2760. }
  2761. if (!host)
  2762. {
  2763. host = PQhost(o_conn);
  2764. if (has_hostaddr(o_conn))
  2765. hostaddr = PQhostaddr(o_conn);
  2766. }
  2767. if (!port)
  2768. port = PQport(o_conn);
  2769. }
  2770. /*
  2771. * Any change in the parameters read above makes us discard the password.
  2772. * We also discard it if we're to use a conninfo rather than the
  2773. * positional syntax.
  2774. */
  2775. if (has_connection_string)
  2776. keep_password = false;
  2777. else
  2778. keep_password =
  2779. (user && PQuser(o_conn) && strcmp(user, PQuser(o_conn)) == 0) &&
  2780. (host && PQhost(o_conn) && strcmp(host, PQhost(o_conn)) == 0) &&
  2781. (port && PQport(o_conn) && strcmp(port, PQport(o_conn)) == 0);
  2782. /*
  2783. * Grab missing dbname from old connection. No password discard if this
  2784. * changes: passwords aren't (usually) database-specific.
  2785. */
  2786. if (!dbname && reuse_previous)
  2787. {
  2788. initPQExpBuffer(&connstr);
  2789. appendPQExpBufferStr(&connstr, "dbname=");
  2790. appendConnStrVal(&connstr, PQdb(o_conn));
  2791. dbname = connstr.data;
  2792. /* has_connection_string=true would be a dead store */
  2793. }
  2794. else
  2795. connstr.data = NULL;
  2796. /*
  2797. * If the user asked to be prompted for a password, ask for one now. If
  2798. * not, use the password from the old connection, provided the username
  2799. * etc have not changed. Otherwise, try to connect without a password
  2800. * first, and then ask for a password if needed.
  2801. *
  2802. * XXX: this behavior leads to spurious connection attempts recorded in
  2803. * the postmaster's log. But libpq offers no API that would let us obtain
  2804. * a password and then continue with the first connection attempt.
  2805. */
  2806. if (pset.getPassword == TRI_YES)
  2807. {
  2808. /*
  2809. * If a connstring or URI is provided, we can't be sure we know which
  2810. * username will be used, since we haven't parsed that argument yet.
  2811. * Don't risk issuing a misleading prompt. As in startup.c, it does
  2812. * not seem worth working harder, since this getPassword option is
  2813. * normally only used in noninteractive cases.
  2814. */
  2815. password = prompt_for_password(has_connection_string ? NULL : user);
  2816. }
  2817. else if (o_conn && keep_password)
  2818. {
  2819. password = PQpass(o_conn);
  2820. if (password && *password)
  2821. password = pg_strdup(password);
  2822. else
  2823. password = NULL;
  2824. }
  2825. while (true)
  2826. {
  2827. #define PARAMS_ARRAY_SIZE 9
  2828. const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
  2829. const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
  2830. int paramnum = -1;
  2831. keywords[++paramnum] = "host";
  2832. values[paramnum] = host;
  2833. if (hostaddr && *hostaddr)
  2834. {
  2835. keywords[++paramnum] = "hostaddr";
  2836. values[paramnum] = hostaddr;
  2837. }
  2838. keywords[++paramnum] = "port";
  2839. values[paramnum] = port;
  2840. keywords[++paramnum] = "user";
  2841. values[paramnum] = user;
  2842. /*
  2843. * Position in the array matters when the dbname is a connection
  2844. * string, because settings in a connection string override earlier
  2845. * array entries only. Thus, user= in the connection string always
  2846. * takes effect, but client_encoding= often will not.
  2847. *
  2848. * If you change this code, also change the initial-connection code in
  2849. * main(). For no good reason, a connection string password= takes
  2850. * precedence in main() but not here.
  2851. */
  2852. keywords[++paramnum] = "dbname";
  2853. values[paramnum] = dbname;
  2854. keywords[++paramnum] = "password";
  2855. values[paramnum] = password;
  2856. keywords[++paramnum] = "fallback_application_name";
  2857. values[paramnum] = pset.progname;
  2858. keywords[++paramnum] = "client_encoding";
  2859. values[paramnum] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
  2860. /* add array terminator */
  2861. keywords[++paramnum] = NULL;
  2862. values[paramnum] = NULL;
  2863. n_conn = PQconnectdbParams(keywords, values, true);
  2864. pg_free(keywords);
  2865. pg_free(values);
  2866. /* We can immediately discard the password -- no longer needed */
  2867. if (password)
  2868. pg_free(password);
  2869. if (PQstatus(n_conn) == CONNECTION_OK)
  2870. break;
  2871. /*
  2872. * Connection attempt failed; either retry the connection attempt with
  2873. * a new password, or give up.
  2874. */
  2875. if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
  2876. {
  2877. /*
  2878. * Prompt for password using the username we actually connected
  2879. * with --- it might've come out of "dbname" rather than "user".
  2880. */
  2881. password = prompt_for_password(PQuser(n_conn));
  2882. PQfinish(n_conn);
  2883. continue;
  2884. }
  2885. /*
  2886. * Failed to connect to the database. In interactive mode, keep the
  2887. * previous connection to the DB; in scripting mode, close our
  2888. * previous connection as well.
  2889. */
  2890. if (pset.cur_cmd_interactive)
  2891. {
  2892. pg_log_info("%s", PQerrorMessage(n_conn));
  2893. /* pset.db is left unmodified */
  2894. if (o_conn)
  2895. pg_log_info("Previous connection kept");
  2896. }
  2897. else
  2898. {
  2899. pg_log_error("\\connect: %s", PQerrorMessage(n_conn));
  2900. if (o_conn)
  2901. {
  2902. /*
  2903. * Transition to having no connection. Keep this bit in sync
  2904. * with CheckConnection().
  2905. */
  2906. PQfinish(o_conn);
  2907. pset.db = NULL;
  2908. ResetCancelConn();
  2909. UnsyncVariables();
  2910. }
  2911. }
  2912. PQfinish(n_conn);
  2913. if (connstr.data)
  2914. termPQExpBuffer(&connstr);
  2915. return false;
  2916. }
  2917. if (connstr.data)
  2918. termPQExpBuffer(&connstr);
  2919. /*
  2920. * Replace the old connection with the new one, and update
  2921. * connection-dependent variables. Keep the resynchronization logic in
  2922. * sync with CheckConnection().
  2923. */
  2924. PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
  2925. pset.db = n_conn;
  2926. SyncVariables();
  2927. connection_warnings(false); /* Must be after SyncVariables */
  2928. /* Tell the user about the new connection */
  2929. if (!pset.quiet)
  2930. {
  2931. if (!o_conn ||
  2932. param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
  2933. param_is_newly_set(PQport(o_conn), PQport(pset.db)))
  2934. {
  2935. char *host = PQhost(pset.db);
  2936. char *hostaddr = PQhostaddr(pset.db);
  2937. /*
  2938. * If the host is an absolute path, the connection is via socket
  2939. * unless overridden by hostaddr
  2940. */
  2941. if (is_absolute_path(host))
  2942. {
  2943. if (hostaddr && *hostaddr)
  2944. printf(_("You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"),
  2945. PQdb(pset.db), PQuser(pset.db), hostaddr, PQport(pset.db));
  2946. else
  2947. printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
  2948. PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
  2949. }
  2950. else
  2951. {
  2952. if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0)
  2953. printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"),
  2954. PQdb(pset.db), PQuser(pset.db), host, hostaddr, PQport(pset.db));
  2955. else
  2956. printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
  2957. PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
  2958. }
  2959. }
  2960. else
  2961. printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
  2962. PQdb(pset.db), PQuser(pset.db));
  2963. }
  2964. if (o_conn)
  2965. PQfinish(o_conn);
  2966. return true;
  2967. }
  2968. void
  2969. connection_warnings(bool in_startup)
  2970. {
  2971. if (!pset.quiet && !pset.notty)
  2972. {
  2973. int client_ver = PG_VERSION_NUM;
  2974. char cverbuf[32];
  2975. char sverbuf[32];
  2976. if (pset.sversion != client_ver)
  2977. {
  2978. const char *server_version;
  2979. /* Try to get full text form, might include "devel" etc */
  2980. server_version = PQparameterStatus(pset.db, "server_version");
  2981. /* Otherwise fall back on pset.sversion */
  2982. if (!server_version)
  2983. {
  2984. formatPGVersionNumber(pset.sversion, true,
  2985. sverbuf, sizeof(sverbuf));
  2986. server_version = sverbuf;
  2987. }
  2988. printf(_("%s (%s, server %s)\n"),
  2989. pset.progname, PG_VERSION, server_version);
  2990. }
  2991. /* For version match, only print psql banner on startup. */
  2992. else if (in_startup)
  2993. printf("%s (%s)\n", pset.progname, PG_VERSION);
  2994. if (pset.sversion / 100 > client_ver / 100)
  2995. printf(_("WARNING: %s major version %s, server major version %s.\n"
  2996. " Some psql features might not work.\n"),
  2997. pset.progname,
  2998. formatPGVersionNumber(client_ver, false,
  2999. cverbuf, sizeof(cverbuf)),
  3000. formatPGVersionNumber(pset.sversion, false,
  3001. sverbuf, sizeof(sverbuf)));
  3002. #ifdef WIN32
  3003. if (in_startup)
  3004. checkWin32Codepage();
  3005. #endif
  3006. printSSLInfo();
  3007. printGSSInfo();
  3008. }
  3009. }
  3010. /*
  3011. * printSSLInfo
  3012. *
  3013. * Prints information about the current SSL connection, if SSL is in use
  3014. */
  3015. static void
  3016. printSSLInfo(void)
  3017. {
  3018. const char *protocol;
  3019. const char *cipher;
  3020. const char *bits;
  3021. const char *compression;
  3022. if (!PQsslInUse(pset.db))
  3023. return; /* no SSL */
  3024. protocol = PQsslAttribute(pset.db, "protocol");
  3025. cipher = PQsslAttribute(pset.db, "cipher");
  3026. bits = PQsslAttribute(pset.db, "key_bits");
  3027. compression = PQsslAttribute(pset.db, "compression");
  3028. printf(_("SSL connection (protocol: %s, cipher: %s, bits: %s, compression: %s)\n"),
  3029. protocol ? protocol : _("unknown"),
  3030. cipher ? cipher : _("unknown"),
  3031. bits ? bits : _("unknown"),
  3032. (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
  3033. }
  3034. /*
  3035. * printGSSInfo
  3036. *
  3037. * Prints information about the current GSSAPI connection, if GSSAPI encryption is in use
  3038. */
  3039. static void
  3040. printGSSInfo(void)
  3041. {
  3042. if (!PQgssEncInUse(pset.db))
  3043. return; /* no GSSAPI encryption in use */
  3044. printf(_("GSSAPI-encrypted connection\n"));
  3045. }
  3046. /*
  3047. * checkWin32Codepage
  3048. *
  3049. * Prints a warning when win32 console codepage differs from Windows codepage
  3050. */
  3051. #ifdef WIN32
  3052. static void
  3053. checkWin32Codepage(void)
  3054. {
  3055. unsigned int wincp,
  3056. concp;
  3057. wincp = GetACP();
  3058. concp = GetConsoleCP();
  3059. if (wincp != concp)
  3060. {
  3061. printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n"
  3062. " 8-bit characters might not work correctly. See psql reference\n"
  3063. " page \"Notes for Windows users\" for details.\n"),
  3064. concp, wincp);
  3065. }
  3066. }
  3067. #endif
  3068. /*
  3069. * SyncVariables
  3070. *
  3071. * Make psql's internal variables agree with connection state upon
  3072. * establishing a new connection.
  3073. */
  3074. void
  3075. SyncVariables(void)
  3076. {
  3077. char vbuf[32];
  3078. const char *server_version;
  3079. /* get stuff from connection */
  3080. pset.encoding = PQclientEncoding(pset.db);
  3081. pset.popt.topt.encoding = pset.encoding;
  3082. pset.sversion = PQserverVersion(pset.db);
  3083. SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
  3084. SetVariable(pset.vars, "USER", PQuser(pset.db));
  3085. SetVariable(pset.vars, "HOST", PQhost(pset.db));
  3086. SetVariable(pset.vars, "PORT", PQport(pset.db));
  3087. SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
  3088. /* this bit should match connection_warnings(): */
  3089. /* Try to get full text form of version, might include "devel" etc */
  3090. server_version = PQparameterStatus(pset.db, "server_version");
  3091. /* Otherwise fall back on pset.sversion */
  3092. if (!server_version)
  3093. {
  3094. formatPGVersionNumber(pset.sversion, true, vbuf, sizeof(vbuf));
  3095. server_version = vbuf;
  3096. }
  3097. SetVariable(pset.vars, "SERVER_VERSION_NAME", server_version);
  3098. snprintf(vbuf, sizeof(vbuf), "%d", pset.sversion);
  3099. SetVariable(pset.vars, "SERVER_VERSION_NUM", vbuf);
  3100. /* send stuff to it, too */
  3101. PQsetErrorVerbosity(pset.db, pset.verbosity);
  3102. PQsetErrorContextVisibility(pset.db, pset.show_context);
  3103. }
  3104. /*
  3105. * UnsyncVariables
  3106. *
  3107. * Clear variables that should be not be set when there is no connection.
  3108. */
  3109. void
  3110. UnsyncVariables(void)
  3111. {
  3112. SetVariable(pset.vars, "DBNAME", NULL);
  3113. SetVariable(pset.vars, "USER", NULL);
  3114. SetVariable(pset.vars, "HOST", NULL);
  3115. SetVariable(pset.vars, "PORT", NULL);
  3116. SetVariable(pset.vars, "ENCODING", NULL);
  3117. SetVariable(pset.vars, "SERVER_VERSION_NAME", NULL);
  3118. SetVariable(pset.vars, "SERVER_VERSION_NUM", NULL);
  3119. }
  3120. /*
  3121. * do_edit -- handler for \e
  3122. *
  3123. * If you do not specify a filename, the current query buffer will be copied
  3124. * into a temporary one.
  3125. */
  3126. static bool
  3127. editFile(const char *fname, int lineno)
  3128. {
  3129. const char *editorName;
  3130. const char *editor_lineno_arg = NULL;
  3131. char *sys;
  3132. int result;
  3133. Assert(fname != NULL);
  3134. /* Find an editor to use */
  3135. editorName = getenv("PSQL_EDITOR");
  3136. if (!editorName)
  3137. editorName = getenv("EDITOR");
  3138. if (!editorName)
  3139. editorName = getenv("VISUAL");
  3140. if (!editorName)
  3141. editorName = DEFAULT_EDITOR;
  3142. /* Get line number argument, if we need it. */
  3143. if (lineno > 0)
  3144. {
  3145. editor_lineno_arg = getenv("PSQL_EDITOR_LINENUMBER_ARG");
  3146. #ifdef DEFAULT_EDITOR_LINENUMBER_ARG
  3147. if (!editor_lineno_arg)
  3148. editor_lineno_arg = DEFAULT_EDITOR_LINENUMBER_ARG;
  3149. #endif
  3150. if (!editor_lineno_arg)
  3151. {
  3152. pg_log_error("environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number");
  3153. return false;
  3154. }
  3155. }
  3156. /*
  3157. * On Unix the EDITOR value should *not* be quoted, since it might include
  3158. * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
  3159. * if necessary. But this policy is not very workable on Windows, due to
  3160. * severe brain damage in their command shell plus the fact that standard
  3161. * program paths include spaces.
  3162. */
  3163. #ifndef WIN32
  3164. if (lineno > 0)
  3165. sys = psprintf("exec %s %s%d '%s'",
  3166. editorName, editor_lineno_arg, lineno, fname);
  3167. else
  3168. sys = psprintf("exec %s '%s'",
  3169. editorName, fname);
  3170. #else
  3171. if (lineno > 0)
  3172. sys = psprintf("\"%s\" %s%d \"%s\"",
  3173. editorName, editor_lineno_arg, lineno, fname);
  3174. else
  3175. sys = psprintf("\"%s\" \"%s\"",
  3176. editorName, fname);
  3177. #endif
  3178. result = system(sys);
  3179. if (result == -1)
  3180. pg_log_error("could not start editor \"%s\"", editorName);
  3181. else if (result == 127)
  3182. pg_log_error("could not start /bin/sh");
  3183. free(sys);
  3184. return result == 0;
  3185. }
  3186. /* call this one */
  3187. static bool
  3188. do_edit(const char *filename_arg, PQExpBuffer query_buf,
  3189. int lineno, bool *edited)
  3190. {
  3191. char fnametmp[MAXPGPATH];
  3192. FILE *stream = NULL;
  3193. const char *fname;
  3194. bool error = false;
  3195. int fd;
  3196. struct stat before,
  3197. after;
  3198. if (filename_arg)
  3199. fname = filename_arg;
  3200. else
  3201. {
  3202. /* make a temp file to edit */
  3203. #ifndef WIN32
  3204. const char *tmpdir = getenv("TMPDIR");
  3205. if (!tmpdir)
  3206. tmpdir = "/tmp";
  3207. #else
  3208. char tmpdir[MAXPGPATH];
  3209. int ret;
  3210. ret = GetTempPath(MAXPGPATH, tmpdir);
  3211. if (ret == 0 || ret > MAXPGPATH)
  3212. {
  3213. pg_log_error("could not locate temporary directory: %s",
  3214. !ret ? strerror(errno) : "");
  3215. return false;
  3216. }
  3217. /*
  3218. * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
  3219. * current directory to the supplied path unless we use only
  3220. * backslashes, so we do that.
  3221. */
  3222. #endif
  3223. #ifndef WIN32
  3224. snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
  3225. "/", (int) getpid());
  3226. #else
  3227. snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
  3228. "" /* trailing separator already present */ , (int) getpid());
  3229. #endif
  3230. fname = (const char *) fnametmp;
  3231. fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
  3232. if (fd != -1)
  3233. stream = fdopen(fd, "w");
  3234. if (fd == -1 || !stream)
  3235. {
  3236. pg_log_error("could not open temporary file \"%s\": %m", fname);
  3237. error = true;
  3238. }
  3239. else
  3240. {
  3241. unsigned int ql = query_buf->len;
  3242. /* force newline-termination of what we send to editor */
  3243. if (ql > 0 && query_buf->data[ql - 1] != '\n')
  3244. {
  3245. appendPQExpBufferChar(query_buf, '\n');
  3246. ql++;
  3247. }
  3248. if (fwrite(query_buf->data, 1, ql, stream) != ql)
  3249. {
  3250. pg_log_error("%s: %m", fname);
  3251. if (fclose(stream) != 0)
  3252. pg_log_error("%s: %m", fname);
  3253. if (remove(fname) != 0)
  3254. pg_log_error("%s: %m", fname);
  3255. error = true;
  3256. }
  3257. else if (fclose(stream) != 0)
  3258. {
  3259. pg_log_error("%s: %m", fname);
  3260. if (remove(fname) != 0)
  3261. pg_log_error("%s: %m", fname);
  3262. error = true;
  3263. }
  3264. }
  3265. }
  3266. if (!error && stat(fname, &before) != 0)
  3267. {
  3268. pg_log_error("%s: %m", fname);
  3269. error = true;
  3270. }
  3271. /* call editor */
  3272. if (!error)
  3273. error = !editFile(fname, lineno);
  3274. if (!error && stat(fname, &after) != 0)
  3275. {
  3276. pg_log_error("%s: %m", fname);
  3277. error = true;
  3278. }
  3279. if (!error && before.st_mtime != after.st_mtime)
  3280. {
  3281. stream = fopen(fname, PG_BINARY_R);
  3282. if (!stream)
  3283. {
  3284. pg_log_error("%s: %m", fname);
  3285. error = true;
  3286. }
  3287. else
  3288. {
  3289. /* read file back into query_buf */
  3290. char line[1024];
  3291. resetPQExpBuffer(query_buf);
  3292. while (fgets(line, sizeof(line), stream) != NULL)
  3293. appendPQExpBufferStr(query_buf, line);
  3294. if (ferror(stream))
  3295. {
  3296. pg_log_error("%s: %m", fname);
  3297. error = true;
  3298. }
  3299. else if (edited)
  3300. {
  3301. *edited = true;
  3302. }
  3303. fclose(stream);
  3304. }
  3305. }
  3306. /* remove temp file */
  3307. if (!filename_arg)
  3308. {
  3309. if (remove(fname) == -1)
  3310. {
  3311. pg_log_error("%s: %m", fname);
  3312. error = true;
  3313. }
  3314. }
  3315. return !error;
  3316. }
  3317. /*
  3318. * process_file
  3319. *
  3320. * Reads commands from filename and passes them to the main processing loop.
  3321. * Handler for \i and \ir, but can be used for other things as well. Returns
  3322. * MainLoop() error code.
  3323. *
  3324. * If use_relative_path is true and filename is not an absolute path, then open
  3325. * the file from where the currently processed file (if any) is located.
  3326. */
  3327. int
  3328. process_file(char *filename, bool use_relative_path)
  3329. {
  3330. FILE *fd;
  3331. int result;
  3332. char *oldfilename;
  3333. char relpath[MAXPGPATH];
  3334. if (!filename)
  3335. {
  3336. fd = stdin;
  3337. filename = NULL;
  3338. }
  3339. else if (strcmp(filename, "-") != 0)
  3340. {
  3341. canonicalize_path(filename);
  3342. /*
  3343. * If we were asked to resolve the pathname relative to the location
  3344. * of the currently executing script, and there is one, and this is a
  3345. * relative pathname, then prepend all but the last pathname component
  3346. * of the current script to this pathname.
  3347. */
  3348. if (use_relative_path && pset.inputfile &&
  3349. !is_absolute_path(filename) && !has_drive_prefix(filename))
  3350. {
  3351. strlcpy(relpath, pset.inputfile, sizeof(relpath));
  3352. get_parent_directory(relpath);
  3353. join_path_components(relpath, relpath, filename);
  3354. canonicalize_path(relpath);
  3355. filename = relpath;
  3356. }
  3357. fd = fopen(filename, PG_BINARY_R);
  3358. if (!fd)
  3359. {
  3360. pg_log_error("%s: %m", filename);
  3361. return EXIT_FAILURE;
  3362. }
  3363. }
  3364. else
  3365. {
  3366. fd = stdin;
  3367. filename = "<stdin>"; /* for future error messages */
  3368. }
  3369. oldfilename = pset.inputfile;
  3370. pset.inputfile = filename;
  3371. pg_logging_config(pset.inputfile ? 0 : PG_LOG_FLAG_TERSE);
  3372. result = MainLoop(fd);
  3373. if (fd != stdin)
  3374. fclose(fd);
  3375. pset.inputfile = oldfilename;
  3376. pg_logging_config(pset.inputfile ? 0 : PG_LOG_FLAG_TERSE);
  3377. return result;
  3378. }
  3379. static const char *
  3380. _align2string(enum printFormat in)
  3381. {
  3382. switch (in)
  3383. {
  3384. case PRINT_NOTHING:
  3385. return "nothing";
  3386. break;
  3387. case PRINT_ALIGNED:
  3388. return "aligned";
  3389. break;
  3390. case PRINT_ASCIIDOC:
  3391. return "asciidoc";
  3392. break;
  3393. case PRINT_CSV:
  3394. return "csv";
  3395. break;
  3396. case PRINT_HTML:
  3397. return "html";
  3398. break;
  3399. case PRINT_LATEX:
  3400. return "latex";
  3401. break;
  3402. case PRINT_LATEX_LONGTABLE:
  3403. return "latex-longtable";
  3404. break;
  3405. case PRINT_TROFF_MS:
  3406. return "troff-ms";
  3407. break;
  3408. case PRINT_UNALIGNED:
  3409. return "unaligned";
  3410. break;
  3411. case PRINT_WRAPPED:
  3412. return "wrapped";
  3413. break;
  3414. }
  3415. return "unknown";
  3416. }
  3417. /*
  3418. * Parse entered Unicode linestyle. If ok, update *linestyle and return
  3419. * true, else return false.
  3420. */
  3421. static bool
  3422. set_unicode_line_style(const char *value, size_t vallen,
  3423. unicode_linestyle *linestyle)
  3424. {
  3425. if (pg_strncasecmp("single", value, vallen) == 0)
  3426. *linestyle = UNICODE_LINESTYLE_SINGLE;
  3427. else if (pg_strncasecmp("double", value, vallen) == 0)
  3428. *linestyle = UNICODE_LINESTYLE_DOUBLE;
  3429. else
  3430. return false;
  3431. return true;
  3432. }
  3433. static const char *
  3434. _unicode_linestyle2string(int linestyle)
  3435. {
  3436. switch (linestyle)
  3437. {
  3438. case UNICODE_LINESTYLE_SINGLE:
  3439. return "single";
  3440. break;
  3441. case UNICODE_LINESTYLE_DOUBLE:
  3442. return "double";
  3443. break;
  3444. }
  3445. return "unknown";
  3446. }
  3447. /*
  3448. * do_pset
  3449. *
  3450. * Performs the assignment "param = value", where value could be NULL;
  3451. * for some params that has an effect such as inversion, for others
  3452. * it does nothing.
  3453. *
  3454. * Adjusts the state of the formatting options at *popt. (In practice that
  3455. * is always pset.popt, but maybe someday it could be different.)
  3456. *
  3457. * If successful and quiet is false, then invokes printPsetInfo() to report
  3458. * the change.
  3459. *
  3460. * Returns true if successful, else false (eg for invalid param or value).
  3461. */
  3462. bool
  3463. do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
  3464. {
  3465. size_t vallen = 0;
  3466. Assert(param != NULL);
  3467. if (value)
  3468. vallen = strlen(value);
  3469. /* set format */
  3470. if (strcmp(param, "format") == 0)
  3471. {
  3472. static const struct fmt
  3473. {
  3474. const char *name;
  3475. enum printFormat number;
  3476. } formats[] =
  3477. {
  3478. /* remember to update error message below when adding more */
  3479. {"aligned", PRINT_ALIGNED},
  3480. {"asciidoc", PRINT_ASCIIDOC},
  3481. {"csv", PRINT_CSV},
  3482. {"html", PRINT_HTML},
  3483. {"latex", PRINT_LATEX},
  3484. {"troff-ms", PRINT_TROFF_MS},
  3485. {"unaligned", PRINT_UNALIGNED},
  3486. {"wrapped", PRINT_WRAPPED}
  3487. };
  3488. if (!value)
  3489. ;
  3490. else
  3491. {
  3492. int match_pos = -1;
  3493. for (int i = 0; i < lengthof(formats); i++)
  3494. {
  3495. if (pg_strncasecmp(formats[i].name, value, vallen) == 0)
  3496. {
  3497. if (match_pos < 0)
  3498. match_pos = i;
  3499. else
  3500. {
  3501. pg_log_error("\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"",
  3502. value,
  3503. formats[match_pos].name, formats[i].name);
  3504. return false;
  3505. }
  3506. }
  3507. }
  3508. if (match_pos >= 0)
  3509. popt->topt.format = formats[match_pos].number;
  3510. else if (pg_strncasecmp("latex-longtable", value, vallen) == 0)
  3511. {
  3512. /*
  3513. * We must treat latex-longtable specially because latex is a
  3514. * prefix of it; if both were in the table above, we'd think
  3515. * "latex" is ambiguous.
  3516. */
  3517. popt->topt.format = PRINT_LATEX_LONGTABLE;
  3518. }
  3519. else
  3520. {
  3521. pg_log_error("\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped");
  3522. return false;
  3523. }
  3524. }
  3525. }
  3526. /* set table line style */
  3527. else if (strcmp(param, "linestyle") == 0)
  3528. {
  3529. if (!value)
  3530. ;
  3531. else if (pg_strncasecmp("ascii", value, vallen) == 0)
  3532. popt->topt.line_style = &pg_asciiformat;
  3533. else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
  3534. popt->topt.line_style = &pg_asciiformat_old;
  3535. else if (pg_strncasecmp("unicode", value, vallen) == 0)
  3536. popt->topt.line_style = &pg_utf8format;
  3537. else
  3538. {
  3539. pg_log_error("\\pset: allowed line styles are ascii, old-ascii, unicode");
  3540. return false;
  3541. }
  3542. }
  3543. /* set unicode border line style */
  3544. else if (strcmp(param, "unicode_border_linestyle") == 0)
  3545. {
  3546. if (!value)
  3547. ;
  3548. else if (set_unicode_line_style(value, vallen,
  3549. &popt->topt.unicode_border_linestyle))
  3550. refresh_utf8format(&(popt->topt));
  3551. else
  3552. {
  3553. pg_log_error("\\pset: allowed Unicode border line styles are single, double");
  3554. return false;
  3555. }
  3556. }
  3557. /* set unicode column line style */
  3558. else if (strcmp(param, "unicode_column_linestyle") == 0)
  3559. {
  3560. if (!value)
  3561. ;
  3562. else if (set_unicode_line_style(value, vallen,
  3563. &popt->topt.unicode_column_linestyle))
  3564. refresh_utf8format(&(popt->topt));
  3565. else
  3566. {
  3567. pg_log_error("\\pset: allowed Unicode column line styles are single, double");
  3568. return false;
  3569. }
  3570. }
  3571. /* set unicode header line style */
  3572. else if (strcmp(param, "unicode_header_linestyle") == 0)
  3573. {
  3574. if (!value)
  3575. ;
  3576. else if (set_unicode_line_style(value, vallen,
  3577. &popt->topt.unicode_header_linestyle))
  3578. refresh_utf8format(&(popt->topt));
  3579. else
  3580. {
  3581. pg_log_error("\\pset: allowed Unicode header line styles are single, double");
  3582. return false;
  3583. }
  3584. }
  3585. /* set border style/width */
  3586. else if (strcmp(param, "border") == 0)
  3587. {
  3588. if (value)
  3589. popt->topt.border = atoi(value);
  3590. }
  3591. /* set expanded/vertical mode */
  3592. else if (strcmp(param, "x") == 0 ||
  3593. strcmp(param, "expanded") == 0 ||
  3594. strcmp(param, "vertical") == 0)
  3595. {
  3596. if (value && pg_strcasecmp(value, "auto") == 0)
  3597. popt->topt.expanded = 2;
  3598. else if (value)
  3599. {
  3600. bool on_off;
  3601. if (ParseVariableBool(value, NULL, &on_off))
  3602. popt->topt.expanded = on_off ? 1 : 0;
  3603. else
  3604. {
  3605. PsqlVarEnumError(param, value, "on, off, auto");
  3606. return false;
  3607. }
  3608. }
  3609. else
  3610. popt->topt.expanded = !popt->topt.expanded;
  3611. }
  3612. /* field separator for CSV format */
  3613. else if (strcmp(param, "csv_fieldsep") == 0)
  3614. {
  3615. if (value)
  3616. {
  3617. /* CSV separator has to be a one-byte character */
  3618. if (strlen(value) != 1)
  3619. {
  3620. pg_log_error("\\pset: csv_fieldsep must be a single one-byte character");
  3621. return false;
  3622. }
  3623. if (value[0] == '"' || value[0] == '\n' || value[0] == '\r')
  3624. {
  3625. pg_log_error("\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return");
  3626. return false;
  3627. }
  3628. popt->topt.csvFieldSep[0] = value[0];
  3629. }
  3630. }
  3631. /* locale-aware numeric output */
  3632. else if (strcmp(param, "numericlocale") == 0)
  3633. {
  3634. if (value)
  3635. return ParseVariableBool(value, param, &popt->topt.numericLocale);
  3636. else
  3637. popt->topt.numericLocale = !popt->topt.numericLocale;
  3638. }
  3639. /* null display */
  3640. else if (strcmp(param, "null") == 0)
  3641. {
  3642. if (value)
  3643. {
  3644. free(popt->nullPrint);
  3645. popt->nullPrint = pg_strdup(value);
  3646. }
  3647. }
  3648. /* field separator for unaligned text */
  3649. else if (strcmp(param, "fieldsep") == 0)
  3650. {
  3651. if (value)
  3652. {
  3653. free(popt->topt.fieldSep.separator);
  3654. popt->topt.fieldSep.separator = pg_strdup(value);
  3655. popt->topt.fieldSep.separator_zero = false;
  3656. }
  3657. }
  3658. else if (strcmp(param, "fieldsep_zero") == 0)
  3659. {
  3660. free(popt->topt.fieldSep.separator);
  3661. popt->topt.fieldSep.separator = NULL;
  3662. popt->topt.fieldSep.separator_zero = true;
  3663. }
  3664. /* record separator for unaligned text */
  3665. else if (strcmp(param, "recordsep") == 0)
  3666. {
  3667. if (value)
  3668. {
  3669. free(popt->topt.recordSep.separator);
  3670. popt->topt.recordSep.separator = pg_strdup(value);
  3671. popt->topt.recordSep.separator_zero = false;
  3672. }
  3673. }
  3674. else if (strcmp(param, "recordsep_zero") == 0)
  3675. {
  3676. free(popt->topt.recordSep.separator);
  3677. popt->topt.recordSep.separator = NULL;
  3678. popt->topt.recordSep.separator_zero = true;
  3679. }
  3680. /* toggle between full and tuples-only format */
  3681. else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
  3682. {
  3683. if (value)
  3684. return ParseVariableBool(value, param, &popt->topt.tuples_only);
  3685. else
  3686. popt->topt.tuples_only = !popt->topt.tuples_only;
  3687. }
  3688. /* set title override */
  3689. else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
  3690. {
  3691. free(popt->title);
  3692. if (!value)
  3693. popt->title = NULL;
  3694. else
  3695. popt->title = pg_strdup(value);
  3696. }
  3697. /* set HTML table tag options */
  3698. else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
  3699. {
  3700. free(popt->topt.tableAttr);
  3701. if (!value)
  3702. popt->topt.tableAttr = NULL;
  3703. else
  3704. popt->topt.tableAttr = pg_strdup(value);
  3705. }
  3706. /* toggle use of pager */
  3707. else if (strcmp(param, "pager") == 0)
  3708. {
  3709. if (value && pg_strcasecmp(value, "always") == 0)
  3710. popt->topt.pager = 2;
  3711. else if (value)
  3712. {
  3713. bool on_off;
  3714. if (!ParseVariableBool(value, NULL, &on_off))
  3715. {
  3716. PsqlVarEnumError(param, value, "on, off, always");
  3717. return false;
  3718. }
  3719. popt->topt.pager = on_off ? 1 : 0;
  3720. }
  3721. else if (popt->topt.pager == 1)
  3722. popt->topt.pager = 0;
  3723. else
  3724. popt->topt.pager = 1;
  3725. }
  3726. /* set minimum lines for pager use */
  3727. else if (strcmp(param, "pager_min_lines") == 0)
  3728. {
  3729. if (value)
  3730. popt->topt.pager_min_lines = atoi(value);
  3731. }
  3732. /* disable "(x rows)" footer */
  3733. else if (strcmp(param, "footer") == 0)
  3734. {
  3735. if (value)
  3736. return ParseVariableBool(value, param, &popt->topt.default_footer);
  3737. else
  3738. popt->topt.default_footer = !popt->topt.default_footer;
  3739. }
  3740. /* set border style/width */
  3741. else if (strcmp(param, "columns") == 0)
  3742. {
  3743. if (value)
  3744. popt->topt.columns = atoi(value);
  3745. }
  3746. else
  3747. {
  3748. pg_log_error("\\pset: unknown option: %s", param);
  3749. return false;
  3750. }
  3751. if (!quiet)
  3752. printPsetInfo(param, &pset.popt);
  3753. return true;
  3754. }
  3755. /*
  3756. * printPsetInfo: print the state of the "param" formatting parameter in popt.
  3757. */
  3758. static bool
  3759. printPsetInfo(const char *param, printQueryOpt *popt)
  3760. {
  3761. Assert(param != NULL);
  3762. /* show border style/width */
  3763. if (strcmp(param, "border") == 0)
  3764. printf(_("Border style is %d.\n"), popt->topt.border);
  3765. /* show the target width for the wrapped format */
  3766. else if (strcmp(param, "columns") == 0)
  3767. {
  3768. if (!popt->topt.columns)
  3769. printf(_("Target width is unset.\n"));
  3770. else
  3771. printf(_("Target width is %d.\n"), popt->topt.columns);
  3772. }
  3773. /* show expanded/vertical mode */
  3774. else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
  3775. {
  3776. if (popt->topt.expanded == 1)
  3777. printf(_("Expanded display is on.\n"));
  3778. else if (popt->topt.expanded == 2)
  3779. printf(_("Expanded display is used automatically.\n"));
  3780. else
  3781. printf(_("Expanded display is off.\n"));
  3782. }
  3783. /* show field separator for CSV format */
  3784. else if (strcmp(param, "csv_fieldsep") == 0)
  3785. {
  3786. printf(_("Field separator for CSV is \"%s\".\n"),
  3787. popt->topt.csvFieldSep);
  3788. }
  3789. /* show field separator for unaligned text */
  3790. else if (strcmp(param, "fieldsep") == 0)
  3791. {
  3792. if (popt->topt.fieldSep.separator_zero)
  3793. printf(_("Field separator is zero byte.\n"));
  3794. else
  3795. printf(_("Field separator is \"%s\".\n"),
  3796. popt->topt.fieldSep.separator);
  3797. }
  3798. else if (strcmp(param, "fieldsep_zero") == 0)
  3799. {
  3800. printf(_("Field separator is zero byte.\n"));
  3801. }
  3802. /* show disable "(x rows)" footer */
  3803. else if (strcmp(param, "footer") == 0)
  3804. {
  3805. if (popt->topt.default_footer)
  3806. printf(_("Default footer is on.\n"));
  3807. else
  3808. printf(_("Default footer is off.\n"));
  3809. }
  3810. /* show format */
  3811. else if (strcmp(param, "format") == 0)
  3812. {
  3813. printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
  3814. }
  3815. /* show table line style */
  3816. else if (strcmp(param, "linestyle") == 0)
  3817. {
  3818. printf(_("Line style is %s.\n"),
  3819. get_line_style(&popt->topt)->name);
  3820. }
  3821. /* show null display */
  3822. else if (strcmp(param, "null") == 0)
  3823. {
  3824. printf(_("Null display is \"%s\".\n"),
  3825. popt->nullPrint ? popt->nullPrint : "");
  3826. }
  3827. /* show locale-aware numeric output */
  3828. else if (strcmp(param, "numericlocale") == 0)
  3829. {
  3830. if (popt->topt.numericLocale)
  3831. printf(_("Locale-adjusted numeric output is on.\n"));
  3832. else
  3833. printf(_("Locale-adjusted numeric output is off.\n"));
  3834. }
  3835. /* show toggle use of pager */
  3836. else if (strcmp(param, "pager") == 0)
  3837. {
  3838. if (popt->topt.pager == 1)
  3839. printf(_("Pager is used for long output.\n"));
  3840. else if (popt->topt.pager == 2)
  3841. printf(_("Pager is always used.\n"));
  3842. else
  3843. printf(_("Pager usage is off.\n"));
  3844. }
  3845. /* show minimum lines for pager use */
  3846. else if (strcmp(param, "pager_min_lines") == 0)
  3847. {
  3848. printf(ngettext("Pager won't be used for less than %d line.\n",
  3849. "Pager won't be used for less than %d lines.\n",
  3850. popt->topt.pager_min_lines),
  3851. popt->topt.pager_min_lines);
  3852. }
  3853. /* show record separator for unaligned text */
  3854. else if (strcmp(param, "recordsep") == 0)
  3855. {
  3856. if (popt->topt.recordSep.separator_zero)
  3857. printf(_("Record separator is zero byte.\n"));
  3858. else if (strcmp(popt->topt.recordSep.separator, "\n") == 0)
  3859. printf(_("Record separator is <newline>.\n"));
  3860. else
  3861. printf(_("Record separator is \"%s\".\n"),
  3862. popt->topt.recordSep.separator);
  3863. }
  3864. else if (strcmp(param, "recordsep_zero") == 0)
  3865. {
  3866. printf(_("Record separator is zero byte.\n"));
  3867. }
  3868. /* show HTML table tag options */
  3869. else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
  3870. {
  3871. if (popt->topt.tableAttr)
  3872. printf(_("Table attributes are \"%s\".\n"),
  3873. popt->topt.tableAttr);
  3874. else
  3875. printf(_("Table attributes unset.\n"));
  3876. }
  3877. /* show title override */
  3878. else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
  3879. {
  3880. if (popt->title)
  3881. printf(_("Title is \"%s\".\n"), popt->title);
  3882. else
  3883. printf(_("Title is unset.\n"));
  3884. }
  3885. /* show toggle between full and tuples-only format */
  3886. else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
  3887. {
  3888. if (popt->topt.tuples_only)
  3889. printf(_("Tuples only is on.\n"));
  3890. else
  3891. printf(_("Tuples only is off.\n"));
  3892. }
  3893. /* Unicode style formatting */
  3894. else if (strcmp(param, "unicode_border_linestyle") == 0)
  3895. {
  3896. printf(_("Unicode border line style is \"%s\".\n"),
  3897. _unicode_linestyle2string(popt->topt.unicode_border_linestyle));
  3898. }
  3899. else if (strcmp(param, "unicode_column_linestyle") == 0)
  3900. {
  3901. printf(_("Unicode column line style is \"%s\".\n"),
  3902. _unicode_linestyle2string(popt->topt.unicode_column_linestyle));
  3903. }
  3904. else if (strcmp(param, "unicode_header_linestyle") == 0)
  3905. {
  3906. printf(_("Unicode header line style is \"%s\".\n"),
  3907. _unicode_linestyle2string(popt->topt.unicode_header_linestyle));
  3908. }
  3909. else
  3910. {
  3911. pg_log_error("\\pset: unknown option: %s", param);
  3912. return false;
  3913. }
  3914. return true;
  3915. }
  3916. /*
  3917. * savePsetInfo: make a malloc'd copy of the data in *popt.
  3918. *
  3919. * Possibly this should be somewhere else, but it's a bit specific to psql.
  3920. */
  3921. printQueryOpt *
  3922. savePsetInfo(const printQueryOpt *popt)
  3923. {
  3924. printQueryOpt *save;
  3925. save = (printQueryOpt *) pg_malloc(sizeof(printQueryOpt));
  3926. /* Flat-copy all the scalar fields, then duplicate sub-structures. */
  3927. memcpy(save, popt, sizeof(printQueryOpt));
  3928. /* topt.line_style points to const data that need not be duplicated */
  3929. if (popt->topt.fieldSep.separator)
  3930. save->topt.fieldSep.separator = pg_strdup(popt->topt.fieldSep.separator);
  3931. if (popt->topt.recordSep.separator)
  3932. save->topt.recordSep.separator = pg_strdup(popt->topt.recordSep.separator);
  3933. if (popt->topt.tableAttr)
  3934. save->topt.tableAttr = pg_strdup(popt->topt.tableAttr);
  3935. if (popt->nullPrint)
  3936. save->nullPrint = pg_strdup(popt->nullPrint);
  3937. if (popt->title)
  3938. save->title = pg_strdup(popt->title);
  3939. /*
  3940. * footers and translate_columns are never set in psql's print settings,
  3941. * so we needn't write code to duplicate them.
  3942. */
  3943. Assert(popt->footers == NULL);
  3944. Assert(popt->translate_columns == NULL);
  3945. return save;
  3946. }
  3947. /*
  3948. * restorePsetInfo: restore *popt from the previously-saved copy *save,
  3949. * then free *save.
  3950. */
  3951. void
  3952. restorePsetInfo(printQueryOpt *popt, printQueryOpt *save)
  3953. {
  3954. /* Free all the old data we're about to overwrite the pointers to. */
  3955. /* topt.line_style points to const data that need not be duplicated */
  3956. if (popt->topt.fieldSep.separator)
  3957. free(popt->topt.fieldSep.separator);
  3958. if (popt->topt.recordSep.separator)
  3959. free(popt->topt.recordSep.separator);
  3960. if (popt->topt.tableAttr)
  3961. free(popt->topt.tableAttr);
  3962. if (popt->nullPrint)
  3963. free(popt->nullPrint);
  3964. if (popt->title)
  3965. free(popt->title);
  3966. /*
  3967. * footers and translate_columns are never set in psql's print settings,
  3968. * so we needn't write code to duplicate them.
  3969. */
  3970. Assert(popt->footers == NULL);
  3971. Assert(popt->translate_columns == NULL);
  3972. /* Now we may flat-copy all the fields, including pointers. */
  3973. memcpy(popt, save, sizeof(printQueryOpt));
  3974. /* Lastly, free "save" ... but its sub-structures now belong to popt. */
  3975. free(save);
  3976. }
  3977. static const char *
  3978. pset_bool_string(bool val)
  3979. {
  3980. return val ? "on" : "off";
  3981. }
  3982. static char *
  3983. pset_quoted_string(const char *str)
  3984. {
  3985. char *ret = pg_malloc(strlen(str) * 2 + 3);
  3986. char *r = ret;
  3987. *r++ = '\'';
  3988. for (; *str; str++)
  3989. {
  3990. if (*str == '\n')
  3991. {
  3992. *r++ = '\\';
  3993. *r++ = 'n';
  3994. }
  3995. else if (*str == '\'')
  3996. {
  3997. *r++ = '\\';
  3998. *r++ = '\'';
  3999. }
  4000. else
  4001. *r++ = *str;
  4002. }
  4003. *r++ = '\'';
  4004. *r = '\0';
  4005. return ret;
  4006. }
  4007. /*
  4008. * Return a malloc'ed string for the \pset value.
  4009. *
  4010. * Note that for some string parameters, print.c distinguishes between unset
  4011. * and empty string, but for others it doesn't. This function should produce
  4012. * output that produces the correct setting when fed back into \pset.
  4013. */
  4014. static char *
  4015. pset_value_string(const char *param, printQueryOpt *popt)
  4016. {
  4017. Assert(param != NULL);
  4018. if (strcmp(param, "border") == 0)
  4019. return psprintf("%d", popt->topt.border);
  4020. else if (strcmp(param, "columns") == 0)
  4021. return psprintf("%d", popt->topt.columns);
  4022. else if (strcmp(param, "csv_fieldsep") == 0)
  4023. return pset_quoted_string(popt->topt.csvFieldSep);
  4024. else if (strcmp(param, "expanded") == 0)
  4025. return pstrdup(popt->topt.expanded == 2
  4026. ? "auto"
  4027. : pset_bool_string(popt->topt.expanded));
  4028. else if (strcmp(param, "fieldsep") == 0)
  4029. return pset_quoted_string(popt->topt.fieldSep.separator
  4030. ? popt->topt.fieldSep.separator
  4031. : "");
  4032. else if (strcmp(param, "fieldsep_zero") == 0)
  4033. return pstrdup(pset_bool_string(popt->topt.fieldSep.separator_zero));
  4034. else if (strcmp(param, "footer") == 0)
  4035. return pstrdup(pset_bool_string(popt->topt.default_footer));
  4036. else if (strcmp(param, "format") == 0)
  4037. return psprintf("%s", _align2string(popt->topt.format));
  4038. else if (strcmp(param, "linestyle") == 0)
  4039. return psprintf("%s", get_line_style(&popt->topt)->name);
  4040. else if (strcmp(param, "null") == 0)
  4041. return pset_quoted_string(popt->nullPrint
  4042. ? popt->nullPrint
  4043. : "");
  4044. else if (strcmp(param, "numericlocale") == 0)
  4045. return pstrdup(pset_bool_string(popt->topt.numericLocale));
  4046. else if (strcmp(param, "pager") == 0)
  4047. return psprintf("%d", popt->topt.pager);
  4048. else if (strcmp(param, "pager_min_lines") == 0)
  4049. return psprintf("%d", popt->topt.pager_min_lines);
  4050. else if (strcmp(param, "recordsep") == 0)
  4051. return pset_quoted_string(popt->topt.recordSep.separator
  4052. ? popt->topt.recordSep.separator
  4053. : "");
  4054. else if (strcmp(param, "recordsep_zero") == 0)
  4055. return pstrdup(pset_bool_string(popt->topt.recordSep.separator_zero));
  4056. else if (strcmp(param, "tableattr") == 0)
  4057. return popt->topt.tableAttr ? pset_quoted_string(popt->topt.tableAttr) : pstrdup("");
  4058. else if (strcmp(param, "title") == 0)
  4059. return popt->title ? pset_quoted_string(popt->title) : pstrdup("");
  4060. else if (strcmp(param, "tuples_only") == 0)
  4061. return pstrdup(pset_bool_string(popt->topt.tuples_only));
  4062. else if (strcmp(param, "unicode_border_linestyle") == 0)
  4063. return pstrdup(_unicode_linestyle2string(popt->topt.unicode_border_linestyle));
  4064. else if (strcmp(param, "unicode_column_linestyle") == 0)
  4065. return pstrdup(_unicode_linestyle2string(popt->topt.unicode_column_linestyle));
  4066. else if (strcmp(param, "unicode_header_linestyle") == 0)
  4067. return pstrdup(_unicode_linestyle2string(popt->topt.unicode_header_linestyle));
  4068. else
  4069. return pstrdup("ERROR");
  4070. }
  4071. #ifndef WIN32
  4072. #define DEFAULT_SHELL "/bin/sh"
  4073. #else
  4074. /*
  4075. * CMD.EXE is in different places in different Win32 releases so we
  4076. * have to rely on the path to find it.
  4077. */
  4078. #define DEFAULT_SHELL "cmd.exe"
  4079. #endif
  4080. static bool
  4081. do_shell(const char *command)
  4082. {
  4083. int result;
  4084. if (!command)
  4085. {
  4086. char *sys;
  4087. const char *shellName;
  4088. shellName = getenv("SHELL");
  4089. #ifdef WIN32
  4090. if (shellName == NULL)
  4091. shellName = getenv("COMSPEC");
  4092. #endif
  4093. if (shellName == NULL)
  4094. shellName = DEFAULT_SHELL;
  4095. /* See EDITOR handling comment for an explanation */
  4096. #ifndef WIN32
  4097. sys = psprintf("exec %s", shellName);
  4098. #else
  4099. sys = psprintf("\"%s\"", shellName);
  4100. #endif
  4101. result = system(sys);
  4102. free(sys);
  4103. }
  4104. else
  4105. result = system(command);
  4106. if (result == 127 || result == -1)
  4107. {
  4108. pg_log_error("\\!: failed");
  4109. return false;
  4110. }
  4111. return true;
  4112. }
  4113. /*
  4114. * do_watch -- handler for \watch
  4115. *
  4116. * We break this out of exec_command to avoid having to plaster "volatile"
  4117. * onto a bunch of exec_command's variables to silence stupider compilers.
  4118. */
  4119. static bool
  4120. do_watch(PQExpBuffer query_buf, double sleep)
  4121. {
  4122. long sleep_ms = (long) (sleep * 1000);
  4123. printQueryOpt myopt = pset.popt;
  4124. const char *strftime_fmt;
  4125. const char *user_title;
  4126. char *title;
  4127. int title_len;
  4128. int res = 0;
  4129. if (!query_buf || query_buf->len <= 0)
  4130. {
  4131. pg_log_error("\\watch cannot be used with an empty query");
  4132. return false;
  4133. }
  4134. /*
  4135. * Choose format for timestamps. We might eventually make this a \pset
  4136. * option. In the meantime, using a variable for the format suppresses
  4137. * overly-anal-retentive gcc warnings about %c being Y2K sensitive.
  4138. */
  4139. strftime_fmt = "%c";
  4140. /*
  4141. * Set up rendering options, in particular, disable the pager, because
  4142. * nobody wants to be prompted while watching the output of 'watch'.
  4143. */
  4144. myopt.topt.pager = 0;
  4145. /*
  4146. * If there's a title in the user configuration, make sure we have room
  4147. * for it in the title buffer. Allow 128 bytes for the timestamp plus 128
  4148. * bytes for the rest.
  4149. */
  4150. user_title = myopt.title;
  4151. title_len = (user_title ? strlen(user_title) : 0) + 256;
  4152. title = pg_malloc(title_len);
  4153. for (;;)
  4154. {
  4155. time_t timer;
  4156. char timebuf[128];
  4157. long i;
  4158. /*
  4159. * Prepare title for output. Note that we intentionally include a
  4160. * newline at the end of the title; this is somewhat historical but it
  4161. * makes for reasonably nicely formatted output in simple cases.
  4162. */
  4163. timer = time(NULL);
  4164. strftime(timebuf, sizeof(timebuf), strftime_fmt, localtime(&timer));
  4165. if (user_title)
  4166. snprintf(title, title_len, _("%s\t%s (every %gs)\n"),
  4167. user_title, timebuf, sleep);
  4168. else
  4169. snprintf(title, title_len, _("%s (every %gs)\n"),
  4170. timebuf, sleep);
  4171. myopt.title = title;
  4172. /* Run the query and print out the results */
  4173. res = PSQLexecWatch(query_buf->data, &myopt);
  4174. /*
  4175. * PSQLexecWatch handles the case where we can no longer repeat the
  4176. * query, and returns 0 or -1.
  4177. */
  4178. if (res <= 0)
  4179. break;
  4180. /*
  4181. * Set up cancellation of 'watch' via SIGINT. We redo this each time
  4182. * through the loop since it's conceivable something inside
  4183. * PSQLexecWatch could change sigint_interrupt_jmp.
  4184. */
  4185. if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
  4186. break;
  4187. /*
  4188. * Enable 'watch' cancellations and wait a while before running the
  4189. * query again. Break the sleep into short intervals (at most 1s)
  4190. * since pg_usleep isn't interruptible on some platforms.
  4191. */
  4192. sigint_interrupt_enabled = true;
  4193. i = sleep_ms;
  4194. while (i > 0)
  4195. {
  4196. long s = Min(i, 1000L);
  4197. pg_usleep(s * 1000L);
  4198. if (cancel_pressed)
  4199. break;
  4200. i -= s;
  4201. }
  4202. sigint_interrupt_enabled = false;
  4203. }
  4204. pg_free(title);
  4205. return (res >= 0);
  4206. }
  4207. /*
  4208. * a little code borrowed from PSQLexec() to manage ECHO_HIDDEN output.
  4209. * returns true unless we have ECHO_HIDDEN_NOEXEC.
  4210. */
  4211. static bool
  4212. echo_hidden_command(const char *query)
  4213. {
  4214. if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
  4215. {
  4216. printf(_("********* QUERY **********\n"
  4217. "%s\n"
  4218. "**************************\n\n"), query);
  4219. fflush(stdout);
  4220. if (pset.logfile)
  4221. {
  4222. fprintf(pset.logfile,
  4223. _("********* QUERY **********\n"
  4224. "%s\n"
  4225. "**************************\n\n"), query);
  4226. fflush(pset.logfile);
  4227. }
  4228. if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
  4229. return false;
  4230. }
  4231. return true;
  4232. }
  4233. /*
  4234. * Look up the object identified by obj_type and desc. If successful,
  4235. * store its OID in *obj_oid and return true, else return false.
  4236. *
  4237. * Note that we'll fail if the object doesn't exist OR if there are multiple
  4238. * matching candidates OR if there's something syntactically wrong with the
  4239. * object description; unfortunately it can be hard to tell the difference.
  4240. */
  4241. static bool
  4242. lookup_object_oid(EditableObjectType obj_type, const char *desc,
  4243. Oid *obj_oid)
  4244. {
  4245. bool result = true;
  4246. PQExpBuffer query = createPQExpBuffer();
  4247. PGresult *res;
  4248. switch (obj_type)
  4249. {
  4250. case EditableFunction:
  4251. /*
  4252. * We have a function description, e.g. "x" or "x(int)". Issue a
  4253. * query to retrieve the function's OID using a cast to regproc or
  4254. * regprocedure (as appropriate).
  4255. */
  4256. appendPQExpBufferStr(query, "SELECT ");
  4257. appendStringLiteralConn(query, desc, pset.db);
  4258. appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
  4259. strchr(desc, '(') ? "regprocedure" : "regproc");
  4260. break;
  4261. case EditableView:
  4262. /*
  4263. * Convert view name (possibly schema-qualified) to OID. Note:
  4264. * this code doesn't check if the relation is actually a view.
  4265. * We'll detect that in get_create_object_cmd().
  4266. */
  4267. appendPQExpBufferStr(query, "SELECT ");
  4268. appendStringLiteralConn(query, desc, pset.db);
  4269. appendPQExpBufferStr(query, "::pg_catalog.regclass::pg_catalog.oid");
  4270. break;
  4271. }
  4272. if (!echo_hidden_command(query->data))
  4273. {
  4274. destroyPQExpBuffer(query);
  4275. return false;
  4276. }
  4277. res = PQexec(pset.db, query->data);
  4278. if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
  4279. *obj_oid = atooid(PQgetvalue(res, 0, 0));
  4280. else
  4281. {
  4282. minimal_error_message(res);
  4283. result = false;
  4284. }
  4285. PQclear(res);
  4286. destroyPQExpBuffer(query);
  4287. return result;
  4288. }
  4289. /*
  4290. * Construct a "CREATE OR REPLACE ..." command that describes the specified
  4291. * database object. If successful, the result is stored in buf.
  4292. */
  4293. static bool
  4294. get_create_object_cmd(EditableObjectType obj_type, Oid oid,
  4295. PQExpBuffer buf)
  4296. {
  4297. bool result = true;
  4298. PQExpBuffer query = createPQExpBuffer();
  4299. PGresult *res;
  4300. switch (obj_type)
  4301. {
  4302. case EditableFunction:
  4303. printfPQExpBuffer(query,
  4304. "SELECT pg_catalog.pg_get_functiondef(%u)",
  4305. oid);
  4306. break;
  4307. case EditableView:
  4308. /*
  4309. * pg_get_viewdef() just prints the query, so we must prepend
  4310. * CREATE for ourselves. We must fully qualify the view name to
  4311. * ensure the right view gets replaced. Also, check relation kind
  4312. * to be sure it's a view.
  4313. *
  4314. * Starting with 9.2, views may have reloptions (security_barrier)
  4315. * and from 9.4 onwards they may also have WITH [LOCAL|CASCADED]
  4316. * CHECK OPTION. These are not part of the view definition
  4317. * returned by pg_get_viewdef() and so need to be retrieved
  4318. * separately. Materialized views (introduced in 9.3) may have
  4319. * arbitrary storage parameter reloptions.
  4320. */
  4321. if (pset.sversion >= 90400)
  4322. {
  4323. printfPQExpBuffer(query,
  4324. "SELECT nspname, relname, relkind, "
  4325. "pg_catalog.pg_get_viewdef(c.oid, true), "
  4326. "pg_catalog.array_remove(pg_catalog.array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
  4327. "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
  4328. "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption "
  4329. "FROM pg_catalog.pg_class c "
  4330. "LEFT JOIN pg_catalog.pg_namespace n "
  4331. "ON c.relnamespace = n.oid WHERE c.oid = %u",
  4332. oid);
  4333. }
  4334. else if (pset.sversion >= 90200)
  4335. {
  4336. printfPQExpBuffer(query,
  4337. "SELECT nspname, relname, relkind, "
  4338. "pg_catalog.pg_get_viewdef(c.oid, true), "
  4339. "c.reloptions AS reloptions, "
  4340. "NULL AS checkoption "
  4341. "FROM pg_catalog.pg_class c "
  4342. "LEFT JOIN pg_catalog.pg_namespace n "
  4343. "ON c.relnamespace = n.oid WHERE c.oid = %u",
  4344. oid);
  4345. }
  4346. else
  4347. {
  4348. printfPQExpBuffer(query,
  4349. "SELECT nspname, relname, relkind, "
  4350. "pg_catalog.pg_get_viewdef(c.oid, true), "
  4351. "NULL AS reloptions, "
  4352. "NULL AS checkoption "
  4353. "FROM pg_catalog.pg_class c "
  4354. "LEFT JOIN pg_catalog.pg_namespace n "
  4355. "ON c.relnamespace = n.oid WHERE c.oid = %u",
  4356. oid);
  4357. }
  4358. break;
  4359. }
  4360. if (!echo_hidden_command(query->data))
  4361. {
  4362. destroyPQExpBuffer(query);
  4363. return false;
  4364. }
  4365. res = PQexec(pset.db, query->data);
  4366. if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
  4367. {
  4368. resetPQExpBuffer(buf);
  4369. switch (obj_type)
  4370. {
  4371. case EditableFunction:
  4372. appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
  4373. break;
  4374. case EditableView:
  4375. {
  4376. char *nspname = PQgetvalue(res, 0, 0);
  4377. char *relname = PQgetvalue(res, 0, 1);
  4378. char *relkind = PQgetvalue(res, 0, 2);
  4379. char *viewdef = PQgetvalue(res, 0, 3);
  4380. char *reloptions = PQgetvalue(res, 0, 4);
  4381. char *checkoption = PQgetvalue(res, 0, 5);
  4382. /*
  4383. * If the backend ever supports CREATE OR REPLACE
  4384. * MATERIALIZED VIEW, allow that here; but as of today it
  4385. * does not, so editing a matview definition in this way
  4386. * is impossible.
  4387. */
  4388. switch (relkind[0])
  4389. {
  4390. #ifdef NOT_USED
  4391. case RELKIND_MATVIEW:
  4392. appendPQExpBufferStr(buf, "CREATE OR REPLACE MATERIALIZED VIEW ");
  4393. break;
  4394. #endif
  4395. case RELKIND_VIEW:
  4396. appendPQExpBufferStr(buf, "CREATE OR REPLACE VIEW ");
  4397. break;
  4398. default:
  4399. pg_log_error("\"%s.%s\" is not a view",
  4400. nspname, relname);
  4401. result = false;
  4402. break;
  4403. }
  4404. appendPQExpBuffer(buf, "%s.", fmtId(nspname));
  4405. appendPQExpBufferStr(buf, fmtId(relname));
  4406. /* reloptions, if not an empty array "{}" */
  4407. if (reloptions != NULL && strlen(reloptions) > 2)
  4408. {
  4409. appendPQExpBufferStr(buf, "\n WITH (");
  4410. if (!appendReloptionsArray(buf, reloptions, "",
  4411. pset.encoding,
  4412. standard_strings()))
  4413. {
  4414. pg_log_error("could not parse reloptions array");
  4415. result = false;
  4416. }
  4417. appendPQExpBufferChar(buf, ')');
  4418. }
  4419. /* View definition from pg_get_viewdef (a SELECT query) */
  4420. appendPQExpBuffer(buf, " AS\n%s", viewdef);
  4421. /* Get rid of the semicolon that pg_get_viewdef appends */
  4422. if (buf->len > 0 && buf->data[buf->len - 1] == ';')
  4423. buf->data[--(buf->len)] = '\0';
  4424. /* WITH [LOCAL|CASCADED] CHECK OPTION */
  4425. if (checkoption && checkoption[0] != '\0')
  4426. appendPQExpBuffer(buf, "\n WITH %s CHECK OPTION",
  4427. checkoption);
  4428. }
  4429. break;
  4430. }
  4431. /* Make sure result ends with a newline */
  4432. if (buf->len > 0 && buf->data[buf->len - 1] != '\n')
  4433. appendPQExpBufferChar(buf, '\n');
  4434. }
  4435. else
  4436. {
  4437. minimal_error_message(res);
  4438. result = false;
  4439. }
  4440. PQclear(res);
  4441. destroyPQExpBuffer(query);
  4442. return result;
  4443. }
  4444. /*
  4445. * If the given argument of \ef or \ev ends with a line number, delete the line
  4446. * number from the argument string and return it as an integer. (We need
  4447. * this kluge because we're too lazy to parse \ef's function or \ev's view
  4448. * argument carefully --- we just slop it up in OT_WHOLE_LINE mode.)
  4449. *
  4450. * Returns -1 if no line number is present, 0 on error, or a positive value
  4451. * on success.
  4452. */
  4453. static int
  4454. strip_lineno_from_objdesc(char *obj)
  4455. {
  4456. char *c;
  4457. int lineno;
  4458. if (!obj || obj[0] == '\0')
  4459. return -1;
  4460. c = obj + strlen(obj) - 1;
  4461. /*
  4462. * This business of parsing backwards is dangerous as can be in a
  4463. * multibyte environment: there is no reason to believe that we are
  4464. * looking at the first byte of a character, nor are we necessarily
  4465. * working in a "safe" encoding. Fortunately the bitpatterns we are
  4466. * looking for are unlikely to occur as non-first bytes, but beware of
  4467. * trying to expand the set of cases that can be recognized. We must
  4468. * guard the <ctype.h> macros by using isascii() first, too.
  4469. */
  4470. /* skip trailing whitespace */
  4471. while (c > obj && isascii((unsigned char) *c) && isspace((unsigned char) *c))
  4472. c--;
  4473. /* must have a digit as last non-space char */
  4474. if (c == obj || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c))
  4475. return -1;
  4476. /* find start of digit string */
  4477. while (c > obj && isascii((unsigned char) *c) && isdigit((unsigned char) *c))
  4478. c--;
  4479. /* digits must be separated from object name by space or closing paren */
  4480. /* notice also that we are not allowing an empty object name ... */
  4481. if (c == obj || !isascii((unsigned char) *c) ||
  4482. !(isspace((unsigned char) *c) || *c == ')'))
  4483. return -1;
  4484. /* parse digit string */
  4485. c++;
  4486. lineno = atoi(c);
  4487. if (lineno < 1)
  4488. {
  4489. pg_log_error("invalid line number: %s", c);
  4490. return 0;
  4491. }
  4492. /* strip digit string from object name */
  4493. *c = '\0';
  4494. return lineno;
  4495. }
  4496. /*
  4497. * Count number of lines in the buffer.
  4498. * This is used to test if pager is needed or not.
  4499. */
  4500. static int
  4501. count_lines_in_buf(PQExpBuffer buf)
  4502. {
  4503. int lineno = 0;
  4504. const char *lines = buf->data;
  4505. while (*lines != '\0')
  4506. {
  4507. lineno++;
  4508. /* find start of next line */
  4509. lines = strchr(lines, '\n');
  4510. if (!lines)
  4511. break;
  4512. lines++;
  4513. }
  4514. return lineno;
  4515. }
  4516. /*
  4517. * Write text at *lines to output with line numbers.
  4518. *
  4519. * If header_keyword isn't NULL, then line 1 should be the first line beginning
  4520. * with header_keyword; lines before that are unnumbered.
  4521. *
  4522. * Caution: this scribbles on *lines.
  4523. */
  4524. static void
  4525. print_with_linenumbers(FILE *output, char *lines,
  4526. const char *header_keyword)
  4527. {
  4528. bool in_header = (header_keyword != NULL);
  4529. size_t header_sz = in_header ? strlen(header_keyword) : 0;
  4530. int lineno = 0;
  4531. while (*lines != '\0')
  4532. {
  4533. char *eol;
  4534. if (in_header && strncmp(lines, header_keyword, header_sz) == 0)
  4535. in_header = false;
  4536. /* increment lineno only for body's lines */
  4537. if (!in_header)
  4538. lineno++;
  4539. /* find and mark end of current line */
  4540. eol = strchr(lines, '\n');
  4541. if (eol != NULL)
  4542. *eol = '\0';
  4543. /* show current line as appropriate */
  4544. if (in_header)
  4545. fprintf(output, " %s\n", lines);
  4546. else
  4547. fprintf(output, "%-7d %s\n", lineno, lines);
  4548. /* advance to next line, if any */
  4549. if (eol == NULL)
  4550. break;
  4551. lines = ++eol;
  4552. }
  4553. }
  4554. /*
  4555. * Report just the primary error; this is to avoid cluttering the output
  4556. * with, for instance, a redisplay of the internally generated query
  4557. */
  4558. static void
  4559. minimal_error_message(PGresult *res)
  4560. {
  4561. PQExpBuffer msg;
  4562. const char *fld;
  4563. msg = createPQExpBuffer();
  4564. fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
  4565. if (fld)
  4566. printfPQExpBuffer(msg, "%s: ", fld);
  4567. else
  4568. printfPQExpBuffer(msg, "ERROR: ");
  4569. fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
  4570. if (fld)
  4571. appendPQExpBufferStr(msg, fld);
  4572. else
  4573. appendPQExpBufferStr(msg, "(not available)");
  4574. appendPQExpBufferChar(msg, '\n');
  4575. pg_log_error("%s", msg->data);
  4576. destroyPQExpBuffer(msg);
  4577. }