MainLoop.c (2)函数SendQuery 和 HandleSlashCmds

来源:互联网 发布:淘宝发布图片规则 编辑:程序博客网 时间:2024/05/22 12:09

函数SendQuery 用来执行命令,并输出结果

/* execute query */
success = SendQuery(query_buf->data);


函数SendQuery定义如下:

/* * SendQuery: send the query string to the backend * (and print out results) * * Note: This is the "front door" way to send a query. That is, use it to * send queries actually entered by the user. These queries will be subject to * single step mode. * To send "back door" queries (generated by slash commands, etc.) in a * controlled way, use PSQLexec(). * * Returns true if the query executed successfully, false otherwise. */boolSendQuery(const char *query){PGresult   *results;PGTransactionStatusType transaction_status;doubleelapsed_msec = 0;boolOK,on_error_rollback_savepoint = false;static bool on_error_rollback_warning = false;if (!pset.db){psql_error("You are currently not connected to a database.\n");return false;}if (pset.singlestep){charbuf[3];printf(_("***(Single step mode: verify command)*******************************************\n" "%s\n" "***(press return to proceed or enter x and return to cancel)********************\n"),   query);fflush(stdout);if (fgets(buf, sizeof(buf), stdin) != NULL)if (buf[0] == 'x')return false;}else if (pset.echo == PSQL_ECHO_QUERIES){puts(query);fflush(stdout);}if (pset.logfile){fprintf(pset.logfile,_("********* QUERY **********\n"  "%s\n"  "**************************\n\n"), query);fflush(pset.logfile);}SetCancelConn();transaction_status = PQtransactionStatus(pset.db);if (transaction_status == PQTRANS_IDLE &&!pset.autocommit &&!command_no_begin(query)){results = PQexec(pset.db, "BEGIN");if (PQresultStatus(results) != PGRES_COMMAND_OK){psql_error("%s", PQerrorMessage(pset.db));PQclear(results);ResetCancelConn();return false;}PQclear(results);transaction_status = PQtransactionStatus(pset.db);}if (transaction_status == PQTRANS_INTRANS &&pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF &&(pset.cur_cmd_interactive || pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON)){if (on_error_rollback_warning == false && pset.sversion < 80000){fprintf(stderr, _("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n"),pset.sversion / 10000, (pset.sversion / 100) % 100);on_error_rollback_warning = true;}else{results = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint");if (PQresultStatus(results) != PGRES_COMMAND_OK){psql_error("%s", PQerrorMessage(pset.db));PQclear(results);ResetCancelConn();return false;}PQclear(results);on_error_rollback_savepoint = true;}}if (pset.fetch_count <= 0 || !is_select_command(query)){/* Default fetch-it-all-and-print mode */instr_timebefore,after;if (pset.timing)INSTR_TIME_SET_CURRENT(before);results = PQexec(pset.db, query);/* these operations are included in the timing result: */ResetCancelConn();OK = (AcceptResult(results) && ProcessCopyResult(results));if (pset.timing){INSTR_TIME_SET_CURRENT(after);INSTR_TIME_SUBTRACT(after, before);elapsed_msec = INSTR_TIME_GET_MILLISEC(after);}/* but printing results isn't: */if (OK)OK = PrintQueryResults(results);}else{/* Fetch-in-segments mode */OK = ExecQueryUsingCursor(query, &elapsed_msec);ResetCancelConn();results = NULL;/* PQclear(NULL) does nothing */}/* If we made a temporary savepoint, possibly release/rollback */if (on_error_rollback_savepoint){const char *svptcmd;transaction_status = PQtransactionStatus(pset.db);if (transaction_status == PQTRANS_INERROR){/* We always rollback on an error */svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";}else if (transaction_status != PQTRANS_INTRANS){/* If they are no longer in a transaction, then do nothing */svptcmd = NULL;}else{/* * Do nothing if they are messing with savepoints themselves: If * the user did RELEASE or ROLLBACK, our savepoint is gone. If * they issued a SAVEPOINT, releasing ours would remove theirs. */if (results &&(strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 || strcmp(PQcmdStatus(results), "RELEASE") == 0 || strcmp(PQcmdStatus(results), "ROLLBACK") == 0))svptcmd = NULL;elsesvptcmd = "RELEASE pg_psql_temporary_savepoint";}if (svptcmd){PGresult   *svptres;svptres = PQexec(pset.db, svptcmd);if (PQresultStatus(svptres) != PGRES_COMMAND_OK){psql_error("%s", PQerrorMessage(pset.db));PQclear(svptres);PQclear(results);ResetCancelConn();return false;}PQclear(svptres);}}PQclear(results);/* Possible microtiming output */if (OK && pset.timing)printf(_("Time: %.3f ms\n"), elapsed_msec);/* check for events that may occur during query execution */if (pset.encoding != PQclientEncoding(pset.db) &&PQclientEncoding(pset.db) >= 0){/* track effects of SET CLIENT_ENCODING */pset.encoding = PQclientEncoding(pset.db);pset.popt.topt.encoding = pset.encoding;SetVariable(pset.vars, "ENCODING",pg_encoding_to_char(pset.encoding));}PrintNotifications();return OK;}


当对应backslash命令时,执行的函数为:

/* execute backslash command */
slashCmdStatus = HandleSlashCmds(scan_state,query_buf->len > 0 ?query_buf : previous_buf);

/*---------- * HandleSlashCmds: * * Handles all the different commands that start with '\'. * Ordinarily called by MainLoop(). * * scan_state is a lexer working state that is set to continue scanning * just after the '\'.  The lexer is advanced past the command and all * arguments on return. * * 'query_buf' contains the query-so-far, which may be modified by * execution of the backslash command (for example, \r clears it). * query_buf can be NULL if there is no query so far. * * Returns a status code indicating what action is desired, see command.h. *---------- */backslashResultHandleSlashCmds(PsqlScanState scan_state,PQExpBuffer query_buf){backslashResult status = PSQL_CMD_SKIP_LINE;char   *cmd;char   *arg;psql_assert(scan_state);/* Parse off the command name */cmd = psql_scan_slash_command(scan_state);/* And try to execute it */status = exec_command(cmd, scan_state, query_buf);if (status == PSQL_CMD_UNKNOWN){if (pset.cur_cmd_interactive)fprintf(stderr, _("Invalid command \\%s. Try \\? for help.\n"), cmd);elsepsql_error("invalid command \\%s\n", cmd);status = PSQL_CMD_ERROR;}if (status != PSQL_CMD_ERROR){/* eat any remaining arguments after a valid command *//* note we suppress evaluation of backticks here */while ((arg = psql_scan_slash_option(scan_state, OT_VERBATIM, NULL, false))){psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);free(arg);}}else{/* silently throw away rest of line after an erroneous command */while ((arg = psql_scan_slash_option(scan_state, OT_WHOLE_LINE, NULL, false)))free(arg);}/* if there is a trailing \\, swallow it */psql_scan_slash_command_end(scan_state);free(cmd);/* some commands write to queryFout, so make sure output is sent */fflush(pset.queryFout);return status;}




0 0
原创粉丝点击