Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008 #include "postgres_fe.h"
00009 #include "mainloop.h"
00010
00011
00012 #include "command.h"
00013 #include "common.h"
00014 #include "input.h"
00015 #include "settings.h"
00016
00017 #include "mb/pg_wchar.h"
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 int
00028 MainLoop(FILE *source)
00029 {
00030 PsqlScanState scan_state;
00031 volatile PQExpBuffer query_buf;
00032 volatile PQExpBuffer previous_buf;
00033
00034
00035 PQExpBuffer history_buf;
00036
00037 char *line;
00038 int added_nl_pos;
00039 bool success;
00040 bool line_saved_in_history;
00041 volatile int successResult = EXIT_SUCCESS;
00042 volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN;
00043 volatile promptStatus_t prompt_status = PROMPT_READY;
00044 volatile int count_eof = 0;
00045 volatile bool die_on_error = false;
00046
00047
00048 FILE *prev_cmd_source;
00049 bool prev_cmd_interactive;
00050 uint64 prev_lineno;
00051
00052
00053 prev_cmd_source = pset.cur_cmd_source;
00054 prev_cmd_interactive = pset.cur_cmd_interactive;
00055 prev_lineno = pset.lineno;
00056
00057
00058 pset.cur_cmd_source = source;
00059 pset.cur_cmd_interactive = ((source == stdin) && !pset.notty);
00060 pset.lineno = 0;
00061
00062
00063 scan_state = psql_scan_create();
00064
00065 query_buf = createPQExpBuffer();
00066 previous_buf = createPQExpBuffer();
00067 history_buf = createPQExpBuffer();
00068 if (PQExpBufferBroken(query_buf) ||
00069 PQExpBufferBroken(previous_buf) ||
00070 PQExpBufferBroken(history_buf))
00071 {
00072 psql_error("out of memory\n");
00073 exit(EXIT_FAILURE);
00074 }
00075
00076
00077 while (successResult == EXIT_SUCCESS)
00078 {
00079
00080
00081
00082 if (cancel_pressed)
00083 {
00084 if (!pset.cur_cmd_interactive)
00085 {
00086
00087
00088
00089 successResult = EXIT_USER;
00090 break;
00091 }
00092
00093 cancel_pressed = false;
00094 }
00095
00096
00097
00098
00099
00100
00101 if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
00102 {
00103
00104
00105
00106 psql_scan_finish(scan_state);
00107 psql_scan_reset(scan_state);
00108 resetPQExpBuffer(query_buf);
00109 resetPQExpBuffer(history_buf);
00110 count_eof = 0;
00111 slashCmdStatus = PSQL_CMD_UNKNOWN;
00112 prompt_status = PROMPT_READY;
00113 cancel_pressed = false;
00114
00115 if (pset.cur_cmd_interactive)
00116 putc('\n', stdout);
00117 else
00118 {
00119 successResult = EXIT_USER;
00120 break;
00121 }
00122 }
00123
00124 fflush(stdout);
00125
00126
00127
00128
00129 if (pset.cur_cmd_interactive)
00130 {
00131
00132 if (query_buf->len == 0)
00133 prompt_status = PROMPT_READY;
00134 line = gets_interactive(get_prompt(prompt_status));
00135 }
00136 else
00137 {
00138 line = gets_fromFile(source);
00139 if (!line && ferror(source))
00140 successResult = EXIT_FAILURE;
00141 }
00142
00143
00144
00145
00146
00147
00148
00149 if (line == NULL)
00150 {
00151 if (pset.cur_cmd_interactive)
00152 {
00153
00154 count_eof++;
00155
00156 if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false))
00157 {
00158 if (!pset.quiet)
00159 printf(_("Use \"\\q\" to leave %s.\n"), pset.progname);
00160 continue;
00161 }
00162
00163 puts(pset.quiet ? "" : "\\q");
00164 }
00165 break;
00166 }
00167
00168 count_eof = 0;
00169
00170 pset.lineno++;
00171
00172
00173 if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
00174 memmove(line, line + 3, strlen(line + 3) + 1);
00175
00176
00177 if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
00178 {
00179 free(line);
00180 continue;
00181 }
00182
00183
00184 if (pset.cur_cmd_interactive && query_buf->len == 0 &&
00185 pg_strncasecmp(line, "help", 4) == 0 &&
00186 (line[4] == '\0' || line[4] == ';' || isspace((unsigned char) line[4])))
00187 {
00188 free(line);
00189 puts(_("You are using psql, the command-line interface to PostgreSQL."));
00190 printf(_("Type: \\copyright for distribution terms\n"
00191 " \\h for help with SQL commands\n"
00192 " \\? for help with psql commands\n"
00193 " \\g or terminate with semicolon to execute query\n"
00194 " \\q to quit\n"));
00195
00196 fflush(stdout);
00197 continue;
00198 }
00199
00200
00201 if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive)
00202 puts(line);
00203 fflush(stdout);
00204
00205
00206 if (query_buf->len > 0)
00207 {
00208 appendPQExpBufferChar(query_buf, '\n');
00209 added_nl_pos = query_buf->len;
00210 }
00211 else
00212 added_nl_pos = -1;
00213
00214
00215 die_on_error = pset.on_error_stop;
00216
00217
00218
00219
00220 psql_scan_setup(scan_state, line, strlen(line));
00221 success = true;
00222 line_saved_in_history = false;
00223
00224 while (success || !die_on_error)
00225 {
00226 PsqlScanResult scan_result;
00227 promptStatus_t prompt_tmp = prompt_status;
00228
00229 scan_result = psql_scan(scan_state, query_buf, &prompt_tmp);
00230 prompt_status = prompt_tmp;
00231
00232 if (PQExpBufferBroken(query_buf))
00233 {
00234 psql_error("out of memory\n");
00235 exit(EXIT_FAILURE);
00236 }
00237
00238
00239
00240
00241
00242 if (scan_result == PSCAN_SEMICOLON ||
00243 (scan_result == PSCAN_EOL && pset.singleline))
00244 {
00245
00246
00247
00248
00249 if (pset.cur_cmd_interactive && !line_saved_in_history)
00250 {
00251 pg_append_history(line, history_buf);
00252 pg_send_history(history_buf);
00253 line_saved_in_history = true;
00254 }
00255
00256
00257 success = SendQuery(query_buf->data);
00258 slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR;
00259
00260
00261 {
00262 PQExpBuffer swap_buf = previous_buf;
00263
00264 previous_buf = query_buf;
00265 query_buf = swap_buf;
00266 }
00267 resetPQExpBuffer(query_buf);
00268
00269 added_nl_pos = -1;
00270
00271 }
00272 else if (scan_result == PSCAN_BACKSLASH)
00273 {
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 if (query_buf->len == added_nl_pos)
00286 {
00287 query_buf->data[--query_buf->len] = '\0';
00288 pg_send_history(history_buf);
00289 }
00290 added_nl_pos = -1;
00291
00292
00293 if (pset.cur_cmd_interactive && !line_saved_in_history)
00294 {
00295 pg_append_history(line, history_buf);
00296 pg_send_history(history_buf);
00297 line_saved_in_history = true;
00298 }
00299
00300
00301 slashCmdStatus = HandleSlashCmds(scan_state,
00302 query_buf->len > 0 ?
00303 query_buf : previous_buf);
00304
00305 success = slashCmdStatus != PSQL_CMD_ERROR;
00306
00307 if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) &&
00308 query_buf->len == 0)
00309 {
00310
00311 appendPQExpBufferStr(query_buf, previous_buf->data);
00312 }
00313
00314 if (slashCmdStatus == PSQL_CMD_SEND)
00315 {
00316 success = SendQuery(query_buf->data);
00317
00318
00319 {
00320 PQExpBuffer swap_buf = previous_buf;
00321
00322 previous_buf = query_buf;
00323 query_buf = swap_buf;
00324 }
00325 resetPQExpBuffer(query_buf);
00326
00327
00328 psql_scan_reset(scan_state);
00329 }
00330 else if (slashCmdStatus == PSQL_CMD_NEWEDIT)
00331 {
00332
00333 psql_scan_finish(scan_state);
00334 free(line);
00335 line = pg_strdup(query_buf->data);
00336 resetPQExpBuffer(query_buf);
00337
00338 psql_scan_reset(scan_state);
00339 psql_scan_setup(scan_state, line, strlen(line));
00340 line_saved_in_history = false;
00341 prompt_status = PROMPT_READY;
00342 }
00343 else if (slashCmdStatus == PSQL_CMD_TERMINATE)
00344 break;
00345 }
00346
00347
00348 if (scan_result == PSCAN_INCOMPLETE ||
00349 scan_result == PSCAN_EOL)
00350 break;
00351 }
00352
00353
00354 if (pset.cur_cmd_interactive && !line_saved_in_history)
00355 pg_append_history(line, history_buf);
00356
00357 psql_scan_finish(scan_state);
00358 free(line);
00359
00360 if (slashCmdStatus == PSQL_CMD_TERMINATE)
00361 {
00362 successResult = EXIT_SUCCESS;
00363 break;
00364 }
00365
00366 if (!pset.cur_cmd_interactive)
00367 {
00368 if (!success && die_on_error)
00369 successResult = EXIT_USER;
00370
00371 else if (!pset.db)
00372 successResult = EXIT_BADCONN;
00373 }
00374 }
00375
00376
00377
00378
00379 if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
00380 successResult == EXIT_SUCCESS)
00381 {
00382
00383 if (pset.cur_cmd_interactive)
00384 pg_send_history(history_buf);
00385
00386
00387 success = SendQuery(query_buf->data);
00388
00389 if (!success && die_on_error)
00390 successResult = EXIT_USER;
00391 else if (pset.db == NULL)
00392 successResult = EXIT_BADCONN;
00393 }
00394
00395
00396
00397
00398
00399
00400
00401
00402 sigint_interrupt_enabled = false;
00403
00404 destroyPQExpBuffer(query_buf);
00405 destroyPQExpBuffer(previous_buf);
00406 destroyPQExpBuffer(history_buf);
00407
00408 psql_scan_destroy(scan_state);
00409
00410 pset.cur_cmd_source = prev_cmd_source;
00411 pset.cur_cmd_interactive = prev_cmd_interactive;
00412 pset.lineno = prev_lineno;
00413
00414 return successResult;
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425 #include "psqlscan.c"