/* *Mainprocessingloopforreadinglinesofinput *andsendingthemtothebackend. * *Thisloopisre-entrant.Maybecalledby\icommand *whichreadsinputfromafile.
*/ int
MainLoop(FILE *source)
{
PsqlScanState scan_state; /* lexer working state */
ConditionalStack cond_stack; /* \if status stack */ volatile PQExpBuffer query_buf; /* buffer for query being accumulated */ volatile PQExpBuffer previous_buf; /* if there isn't anything in the new *bufferyet,usethisonefor\e,
* etc. */
PQExpBuffer history_buf; /* earlier lines of a multi-line command, not
* yet saved to readline history */ char *line; /* current line of input */ int added_nl_pos; bool success; bool line_saved_in_history; volatileint successResult = EXIT_SUCCESS; volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN; volatile promptStatus_t prompt_status = PROMPT_READY; volatilebool need_redisplay = false; volatileint count_eof = 0; volatilebool die_on_error = false;
FILE *prev_cmd_source; bool prev_cmd_interactive;
uint64 prev_lineno;
/* Save the prior command source */
prev_cmd_source = pset.cur_cmd_source;
prev_cmd_interactive = pset.cur_cmd_interactive;
prev_lineno = pset.lineno; /* pset.stmt_lineno does not need to be saved and restored */
/* Create working state */
scan_state = psql_scan_create(&psqlscan_callbacks);
cond_stack = conditional_stack_create();
psql_scan_set_passthrough(scan_state, cond_stack);
query_buf = createPQExpBuffer();
previous_buf = createPQExpBuffer();
history_buf = createPQExpBuffer(); if (PQExpBufferBroken(query_buf) ||
PQExpBufferBroken(previous_buf) ||
PQExpBufferBroken(history_buf))
pg_fatal("out of memory");
/* main loop to get queries and execute them */ while (successResult == EXIT_SUCCESS)
{ /* *CleanupafterapreviousControl-C
*/ if (cancel_pressed)
{ if (!pset.cur_cmd_interactive)
{ /* *YougethereifyoustoppedascriptwithCtrl-C.
*/
successResult = EXIT_USER; break;
}
cancel_pressed = false;
}
/* *Establishlongjmpdestinationforexitingfromwait-for-input.We *mustre-dothiseachtimethroughtheloopforsafety,sincethe *jmpbufmightgetchangedduringcommandexecution.
*/ if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
{ /* got here with longjmp */
/* *getanotherline
*/ if (pset.cur_cmd_interactive)
{ /* May need to reset prompt, eg after \r command */ if (query_buf->len == 0)
prompt_status = PROMPT_READY; /* If query buffer came from \e, redisplay it with a prompt */ if (need_redisplay)
{ if (query_buf->len > 0)
{
fputs(get_prompt(PROMPT_READY, cond_stack), stdout);
fputs(query_buf->data, stdout);
fflush(stdout);
}
need_redisplay = false;
} /* Now we can fetch a line */
line = gets_interactive(get_prompt(prompt_status, cond_stack),
query_buf);
} else
{
line = gets_fromFile(source); if (!line && ferror(source))
successResult = EXIT_FAILURE;
}
/* No more input. Time to quit, or \i done */ if (line == NULL)
{ if (pset.cur_cmd_interactive)
{ /* This tries to mimic bash's IGNOREEOF feature. */
count_eof++;
if (count_eof < pset.ignoreeof)
{ if (!pset.quiet)
printf(_("Use \"\\q\" to leave %s.\n"), pset.progname); continue;
}
puts(pset.quiet ? "" : "\\q");
} break;
}
count_eof = 0;
pset.lineno++;
/* ignore UTF-8 Unicode byte-order mark */ if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0)
memmove(line, line + 3, strlen(line + 3) + 1);
/* Detect attempts to run custom-format dumps as SQL scripts */ if (pset.lineno == 1 && !pset.cur_cmd_interactive &&
strncmp(line, "PGDMP", 5) == 0)
{
free(line);
puts(_("The input is a PostgreSQL custom-format dump.\n" "Use the pg_restore command-line client to restore this dump to a database.\n"));
fflush(stdout);
successResult = EXIT_FAILURE; break;
}
/* no further processing of empty lines, unless within a literal */ if (line[0] == '\0' && !psql_scan_in_quote(scan_state))
{
free(line); continue;
}
/* *Ifwefoundacommandword,checkwhethertherestoftheline *containsonlywhitespaceplusmaybeonesemicolon.Ifnot, *ignorethecommandwordafterall.Thesecommandsareonlyfor *compatibilitywithotherSQLclientsandarenotdocumented.
*/ if (rest_of_line != NULL)
{ /* *Ignoreunlessrestoflineiswhitespace,plusmaybeone *semicolon
*/ while (isspace((unsignedchar) *rest_of_line))
++rest_of_line; if (*rest_of_line == ';')
++rest_of_line; while (isspace((unsignedchar) *rest_of_line))
++rest_of_line; if (*rest_of_line != '\0')
{
found_help = false;
found_exit_or_quit = false;
}
}
/* *"help"isonlyacommandwhenthequerybufferisempty,butwe *emitaone-linemessageevenwhenitisn'ttohelpconfused *users.Thetextisstilladdedtothequerybufferinthat *case.
*/ if (found_help)
{ if (query_buf->len != 0) #ifndef WIN32
puts(_("Use \\? for help or press control-C to clear the input buffer.")); #else
puts(_("Use \\? for help.")); #endif else
{
puts(_("You are using psql, the command-line interface to PostgreSQL."));
printf(_("Type: \\copyright for distribution terms\n" " \\h for help with SQL commands\n" " \\? for help with psql commands\n" " \\g or terminate with semicolon to execute query\n" " \\q to quit\n"));
free(line);
fflush(stdout); continue;
}
}
/* *"quit"and"exit"areonlycommandswhenthequerybufferis *empty,butweemitaone-linemessageevenwhenitisn'tto *helpconfusedusers.Thetextisstilladdedtothequery *bufferinthatcase.
*/ if (found_exit_or_quit)
{ if (query_buf->len != 0)
{ if (prompt_status == PROMPT_READY ||
prompt_status == PROMPT_CONTINUE ||
prompt_status == PROMPT_PAREN)
puts(_("Use \\q to quit.")); else #ifndef WIN32
puts(_("Use control-D to quit.")); #else
puts(_("Use control-C to quit.")); #endif
} else
{ /* exit app */
free(line);
fflush(stdout);
successResult = EXIT_SUCCESS; break;
}
}
added_nl_pos = -1; /* we need not do psql_scan_reset() here */
} else
{ /* if interactive, warn about non-executed query */ if (pset.cur_cmd_interactive)
pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block"); /* fake an OK result for purposes of loop checks */
success = true;
slashCmdStatus = PSQL_CMD_SEND;
pset.stmt_lineno = 1; /* note that query_buf doesn't change state */
}
} elseif (scan_result == PSCAN_BACKSLASH)
{ /* handle backslash command */
/* save backslash command in history */ if (pset.cur_cmd_interactive && !line_saved_in_history)
{
pg_append_history(line, history_buf);
pg_send_history(history_buf);
line_saved_in_history = true;
}
/* flush any paren nesting info after forced send */
psql_scan_reset(scan_state);
} elseif (slashCmdStatus == PSQL_CMD_NEWEDIT)
{ /* should not see this in inactive branch */
Assert(conditional_active(cond_stack)); /* ensure what came back from editing ends in a newline */ if (query_buf->len > 0 &&
query_buf->data[query_buf->len - 1] != '\n')
appendPQExpBufferChar(query_buf, '\n'); /* rescan query_buf as new input */
psql_scan_finish(scan_state);
free(line);
line = pg_strdup(query_buf->data);
resetPQExpBuffer(query_buf); /* reset parsing state since we are rescanning whole line */
psql_scan_reset(scan_state);
psql_scan_setup(scan_state, line, strlen(line),
pset.encoding, standard_strings());
line_saved_in_history = false;
prompt_status = PROMPT_READY; /* we'll want to redisplay after parsing what we have */
need_redisplay = true;
} elseif (slashCmdStatus == PSQL_CMD_TERMINATE) break;
}
/* fall out of loop if lexer reached EOL */ if (scan_result == PSCAN_INCOMPLETE ||
scan_result == PSCAN_EOL) break;
}
/* *Addlinetopendinghistoryifwedidn'tdosoalready.Then,if *thequerybufferisstillempty,flushoutanyunsenthistory *entry.Thismeansthatemptylines(containingonlywhitespaceand *perhapsadash-dashcomment)thatprecedeaquerywillberecorded *asseparatehistoryentries,notaspartofthatquery.
*/ if (pset.cur_cmd_interactive)
{ if (!line_saved_in_history)
pg_append_history(line, history_buf); if (query_buf->len == 0)
pg_send_history(history_buf);
}
psql_scan_finish(scan_state);
free(line);
if (slashCmdStatus == PSQL_CMD_TERMINATE)
{
successResult = EXIT_SUCCESS; break;
}
if (!pset.cur_cmd_interactive)
{ if (!success && die_on_error)
successResult = EXIT_USER; /* Have we lost the db connection? */ elseif (!pset.db)
successResult = EXIT_BADCONN;
}
} /* while !endoffile/session */
/* *Ifwehaveanon-semicolon-terminatedqueryattheendoffile,we *processitunlesstheinputsourceisinteractive---inthatcaseit *seemsbettertogoaheadandquit.Alsoskipifthisisanerrorexit.
*/ if (query_buf->len > 0 && !pset.cur_cmd_interactive &&
successResult == EXIT_SUCCESS)
{ /* save query in history */ /* currently unneeded since we don't use this block if interactive */ #ifdef NOT_USED if (pset.cur_cmd_interactive)
pg_send_history(history_buf); #endif
/* execute query unless we're in an inactive \if branch */ if (conditional_active(cond_stack))
{
success = SendQuery(query_buf->data);
} else
{ if (pset.cur_cmd_interactive)
pg_log_error("query ignored; use \\endif or Ctrl-C to exit current \\if block");
success = true;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Bemerkung:
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.