PageRenderTime 63ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/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

Large files files are truncated, but you can click here to view the full file

  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 =

Large files files are truncated, but you can click here to view the full file