示例#1
0
/*
 * PrintQueryResults: print out query results as required
 *
 * Note: Utility function for use by SendQuery() only.
 *
 * Returns true if the query executed successfully, false otherwise.
 */
static bool
PrintQueryResults(PGresult *results)
{
	bool		success = false;

	if (!results)
		return false;

	switch (PQresultStatus(results))
	{
		case PGRES_TUPLES_OK:
			success = PrintQueryTuples(results);
			break;

		case PGRES_COMMAND_OK:
			{
				char		buf[10];

				success = true;
				sprintf(buf, "%u", (unsigned int) PQoidValue(results));
				if (!QUIET())
				{
					if (pset.popt.topt.format == PRINT_HTML)
					{
						fputs("<p>", pset.queryFout);
						html_escaped_print(PQcmdStatus(results),
										   pset.queryFout);
						fputs("</p>\n", pset.queryFout);
					}
					else
						fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
				}
				SetVariable(pset.vars, "LASTOID", buf);
				break;
			}

		case PGRES_EMPTY_QUERY:
			success = true;
			break;

		case PGRES_COPY_OUT:
		case PGRES_COPY_IN:
			/* nothing to do here */
			success = true;
			break;

		default:
			break;
	}

	fflush(pset.queryFout);

	return success;
}
示例#2
0
/*
 * call-seq:
 *    res.cmd_status() -> String
 *
 * Returns the status string of the last query command.
 */
static VALUE
pgresult_cmd_status(VALUE self)
{
	VALUE ret = rb_tainted_str_new2(PQcmdStatus(pgresult_get(self)));
	ASSOCIATE_INDEX(ret, self);
	return ret;
}
示例#3
0
void dlgDirectDbg::OnTargetComplete( wxCommandEvent &event )
{
	// Extract the result set handle from the event and log the status info

	PGresult    *result = (PGresult *)event.GetClientData();

	wxLogInfo( wxT( "OnTargetComplete() called\n" ));
	wxLogInfo( wxT( "%s\n" ), wxString(PQresStatus( PQresultStatus( result )), wxConvUTF8).c_str());

	// If the query failed, write the error message to the status line, otherwise, copy the result set into the grid
	if(( PQresultStatus( result ) == PGRES_NONFATAL_ERROR ) || ( PQresultStatus( result ) == PGRES_FATAL_ERROR ))
	{
		wxString    message( PQresultErrorMessage( result ), wxConvUTF8 );

		message.Replace( wxT( "\n" ), wxT( " " ));

		m_parent->getStatusBar()->SetStatusText( message, 1 );
		char *state = PQresultErrorField(result, PG_DIAG_SQLSTATE);

		// Don't bother telling the user that he aborted - he already knows!
		// Depending on the stage, m_conn might not be set all! so check for
		// that first
		if (m_conn)
		{
			if (state != NULL && strcmp(state, "57014"))
				wxLogError( wxT( "%s\n" ), wxString(PQerrorMessage(m_conn->getConnection()), wxConvUTF8).c_str());
			else
				wxLogInfo( wxT( "%s\n" ), wxString(PQerrorMessage(m_conn->getConnection()), wxConvUTF8).c_str());
		}
	}
	else
	{
		wxString message( PQcmdStatus( result ), wxConvUTF8 );

		message.Replace( wxT( "\r" ), wxT( "" ));
		message.Replace( wxT( "\n" ), wxT( " " ));

		m_parent->getStatusBar()->SetStatusText( message, 1 );

		// If this result set has any columns, add a result grid to the code window so
		// we can show the results to the user

		if( m_codeWindow && PQnfields( result ))
		{
			m_codeWindow->OnResultSet( result );
		}
	}

	if (m_codeWindow)
	{
		m_codeWindow->m_targetComplete = true;
		m_codeWindow->disableTools( );
	}

	// Do not show if aborted
	if ( m_codeWindow && m_codeWindow->m_targetAborted )
		return;

	this->Show( true );
}
示例#4
0
文件: common.c 项目: PJMODOS/postgres
/*
 * PrintQueryResults: print out (or store) query results as required
 *
 * Note: Utility function for use by SendQuery() only.
 *
 * Returns true if the query executed successfully, false otherwise.
 */
static bool
PrintQueryResults(PGresult *results)
{
	bool		success;
	const char *cmdstatus;

	if (!results)
		return false;

	switch (PQresultStatus(results))
	{
		case PGRES_TUPLES_OK:
			/* store or print the data ... */
			if (pset.gset_prefix)
				success = StoreQueryTuple(results);
			else
				success = PrintQueryTuples(results);
			/* if it's INSERT/UPDATE/DELETE RETURNING, also print status */
			cmdstatus = PQcmdStatus(results);
			if (strncmp(cmdstatus, "INSERT", 6) == 0 ||
				strncmp(cmdstatus, "UPDATE", 6) == 0 ||
				strncmp(cmdstatus, "DELETE", 6) == 0)
				PrintQueryStatus(results);
			break;

		case PGRES_COMMAND_OK:
			PrintQueryStatus(results);
			success = true;
			break;

		case PGRES_EMPTY_QUERY:
			success = true;
			break;

		case PGRES_COPY_OUT:
		case PGRES_COPY_IN:
			/* nothing to do here */
			success = true;
			break;

		case PGRES_BAD_RESPONSE:
		case PGRES_NONFATAL_ERROR:
		case PGRES_FATAL_ERROR:
			success = false;
			break;

		default:
			success = false;
			psql_error("unexpected PQresultStatus: %d\n",
					   PQresultStatus(results));
			break;
	}

	fflush(pset.queryFout);

	return success;
}
示例#5
0
文件: common.c 项目: GisKook/Gis
/*
 * PrintQueryStatus: report command status as required
 *
 * Note: Utility function for use by PrintQueryResults() only.
 */
static void
PrintQueryStatus(PGresult *results)
{
	char		buf[16];

	if (!pset.quiet)
	{
		if (pset.popt.topt.format == PRINT_HTML)
		{
			fputs("<p>", pset.queryFout);
			html_escaped_print(PQcmdStatus(results), pset.queryFout);
			fputs("</p>\n", pset.queryFout);
		}
		else
			fprintf(pset.queryFout, "%s\n", PQcmdStatus(results));
	}

	if (pset.logfile)
		fprintf(pset.logfile, "%s\n", PQcmdStatus(results));

	snprintf(buf, sizeof(buf), "%u", (unsigned int) PQoidValue(results));
	SetVariable(pset.vars, "LASTOID", buf);
}
示例#6
0
文件: common.c 项目: GisKook/Gis
/*
 * PrintQueryResults: print out query results as required
 *
 * Note: Utility function for use by SendQuery() only.
 *
 * Returns true if the query executed successfully, false otherwise.
 */
static bool
PrintQueryResults(PGresult *results)
{
	bool		success = false;
	const char *cmdstatus;

	if (!results)
		return false;

	switch (PQresultStatus(results))
	{
		case PGRES_TUPLES_OK:
			/* print the data ... */
			success = PrintQueryTuples(results);
			/* if it's INSERT/UPDATE/DELETE RETURNING, also print status */
			cmdstatus = PQcmdStatus(results);
			if (strncmp(cmdstatus, "INSERT", 6) == 0 ||
				strncmp(cmdstatus, "UPDATE", 6) == 0 ||
				strncmp(cmdstatus, "DELETE", 6) == 0)
				PrintQueryStatus(results);
			break;

		case PGRES_COMMAND_OK:
			PrintQueryStatus(results);
			success = true;
			break;

		case PGRES_EMPTY_QUERY:
			success = true;
			break;

		case PGRES_COPY_OUT:
		case PGRES_COPY_IN:
			/* nothing to do here */
			success = true;
			break;

		default:
			break;
	}

	fflush(pset.queryFout);

	return success;
}
示例#7
0
 std::string answer() const { return PQcmdStatus(res); }
示例#8
0
/*
 * Display a CdbDispatchResult in the log for debugging.
 * Call only from main thread, during or after cdbdisp_checkDispatchResults.
 */
void
cdbdisp_debugDispatchResult(CdbDispatchResult * dispatchResult)
{
	int	ires;
	int	nres;

	Assert (dispatchResult != NULL);

	/*
	 * PGresult messages
	 */
	nres = cdbdisp_numPGresult(dispatchResult);
	for (ires = 0; ires < nres; ++ires)
	{
		PGresult *pgresult = cdbdisp_getPGresult(dispatchResult, ires);
		ExecStatusType resultStatus = PQresultStatus(pgresult);
		char *whoami = PQresultErrorField(pgresult, PG_DIAG_GP_PROCESS_TAG);

		if (!whoami)
			whoami = "no process id";

		if (resultStatus == PGRES_COMMAND_OK ||
			resultStatus == PGRES_TUPLES_OK ||
			resultStatus == PGRES_COPY_IN ||
			resultStatus == PGRES_COPY_OUT ||
			resultStatus == PGRES_EMPTY_QUERY)
		{
			char *cmdStatus = PQcmdStatus(pgresult);

			elog(LOG, "DispatchResult from %s: ok %s (%s)",
				 dispatchResult->segdbDesc->whoami,
				 cmdStatus ? cmdStatus : "(no cmdStatus)", whoami);
		}
		else
		{
			char *sqlstate = PQresultErrorField(pgresult, PG_DIAG_SQLSTATE);
			char *pri = PQresultErrorField(pgresult, PG_DIAG_MESSAGE_PRIMARY);
			char *dtl = PQresultErrorField(pgresult, PG_DIAG_MESSAGE_DETAIL);
			char *sourceFile = PQresultErrorField(pgresult, PG_DIAG_SOURCE_FILE);
			char *sourceLine = PQresultErrorField(pgresult, PG_DIAG_SOURCE_LINE);
			int	lenpri = (pri == NULL) ? 0 : strlen(pri);

			if (!sqlstate)
				sqlstate = "no SQLSTATE";

			while (lenpri > 0 && pri[lenpri - 1] <= ' ' && pri[lenpri - 1] > '\0')
				lenpri--;

			ereport(LOG,
					(errmsg("DispatchResult from %s: error (%s) %s %.*s (%s)",
							dispatchResult->segdbDesc->whoami,
							sqlstate,
							PQresStatus(resultStatus),
							lenpri,
							pri ? pri : "", whoami),
					 errdetail("(%s:%s) %s",
							 sourceFile ? sourceFile : "unknown file",
							 sourceLine ? sourceLine : "unknown line",
							 dtl ? dtl : "")));
		}
	}

	/*
	 * Error found on our side of the libpq interface?
	 */
	if (dispatchResult->error_message &&
		dispatchResult->error_message->len > 0)
	{
		char esqlstate[6];
		errcode_to_sqlstate(dispatchResult->errcode, esqlstate);
		elog(LOG, "DispatchResult from %s: connect error (%s) %s",
			 dispatchResult->segdbDesc->whoami,
			 esqlstate, dispatchResult->error_message->data);
	}

	/*
	 * Should have either an error code or an ok result.
	 */
	if (dispatchResult->errcode == 0 && dispatchResult->okindex < 0)
	{
		elog(LOG, "DispatchResult from %s: No ending status.",
			 dispatchResult->segdbDesc->whoami);
	}
}
示例#9
0
/*************************************************************
 *Returns the status of the command status of last query.
 *************************************************************/
char *
dbi_cmd_status(DBI_result *result_id)
{
  return(PQcmdStatus(result_id));
}
示例#10
0
文件: common.c 项目: GisKook/Gis
/*
 * 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.
 */
bool
SendQuery(const char *query)
{
	PGresult   *results;
	PGTransactionStatusType transaction_status;
	double		elapsed_msec = 0;
	bool		OK,
				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)
	{
		char		buf[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_time	before,
					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;
			else
				svptcmd = "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;
}
示例#11
0
/*
 *  fetch_prompt_rule
 * 
 *  Return the set of parameters to be used to turn the form_name, fieldname
 *  pair into an input prompt.
 *
 *  The result will contain both locally allocated and PGresult data.
 *  It must be freed with free_prompt_rule.
 */
struct prompt_rule* fetch_prompt_rule(struct handler_args* h, 
    char* form_name, char* fieldname){

    double start = gettime();
    bool log_errors = false;

    char* paramValues[] = {form_name, fieldname, NULL};

    PGresult* rs = PQexecPrepared(h->session->conn, "fetch_rule", 2,
        (const char* const*) &paramValues, NULL, NULL, 0);

    if ((PQresultStatus(rs) == PGRES_TUPLES_OK) && (PQntuples(rs) == 1)) {
   
        struct prompt_rule* rule = calloc(1,sizeof(struct prompt_rule));

        rule->form_name = get_value(rs, 0, "form_name");
        rule->fieldname =  get_value(rs, 0, "fieldname");
        rule->prompt_type = get_value(rs, 0, "prompt_type");
        rule->el_class = get_value(rs, 0, "el_class");

        rule->readonly =  get_bool(rs, 0, "readonly");

        rule->publish_pgtype = get_bool(rs, 0, "publish_pgtype");
       
        rule->rows = strtol( get_value(rs, 0, "rows"), NULL, 10);
        rule->cols = strtol( get_value(rs, 0, "cols"), NULL, 10);
        rule->size = strtol( get_value(rs, 0, "size"), NULL, 10);
        rule->maxlength = strtol(get_value(rs, 0, "maxlength"), NULL, 10);
        rule->tabindex = strtol(get_value(rs, 0, "tabindex"), NULL, 10);
        rule->regex_pattern = get_value(rs, 0, "regex_pattern");
        if (rule->regex_pattern != NULL){
            const char* error = NULL;
            int erroffset = 0;
            rule->comp_regex = pcre_compile( rule->regex_pattern, 
                PCRE_JAVASCRIPT_COMPAT|PCRE_UTF8,
                &error, &erroffset, NULL);

            if (rule->comp_regex == NULL){
                fprintf(h->log, "%f %d %s:%d "
                    "regex compile failed form %s field %s offset %d: %s\n",
                    gettime(), h->request_id, __func__, __LINE__,
                    form_name, fieldname, erroffset, error);
            }
        }

        rule->expand_percent_n = get_bool(rs, 0, "expand_percent_n");

        // The default value for rule->options is a pointer to a 
        // pg result set.  Whether rule->options is overwritten or not, 
        // the pg string will be freed by free_prompt_rule.
        // In a few cases, the options need to be generated dynamically.
        // Select pkey and enum are examples. In such a case, the 
        // string which needs to be independently freed is referenced
        // in free_options.
        rule->options = get_value(rs, 0, "options");
        rule->free_options = NULL;

        rule->src = get_value(rs, 0, "src");
        rule->onblur = get_value(rs, 0, "onblur");
        rule->onchange = get_value(rs, 0, "onchange");
        rule->onclick = get_value(rs, 0, "onclick");
        rule->ondblclick = get_value(rs, 0, "ondblclick");
        rule->onfocus = get_value(rs, 0, "onfocus");
        rule->onkeypress = get_value(rs, 0, "onkeypress");
        rule->onkeyup = get_value(rs, 0, "onkeyup");
        rule->onkeydown = get_value(rs, 0, "onkeydown");
        rule->onmousedown = get_value(rs, 0, "onmousedown");
        rule->onmouseup = get_value(rs, 0, "onmouseup");
        rule->onmouseout = get_value(rs, 0, "onmouseout");
        rule->onmouseover = get_value(rs, 0, "onmouseover");
        rule->onselect = get_value(rs, 0, "onselect");
 
        rule->result = rs;

        fprintf(h->log, "%f %d %s:%d fetch_prompt_rule (%s,%s) in %f\n",
                gettime(), h->request_id, __func__, __LINE__,
                form_name, fieldname, gettime() - start);

        return rule;
    }else{
        if (log_errors){
            fprintf(h->log, "%f %d %s:%d fetch_prompt_rules"
                "resStatus:%s cmdStatus:%s ErrorMessage:%s\n", 
                gettime(), h->request_id, __func__, __LINE__,
                PQresStatus(PQresultStatus(rs)),
                PQcmdStatus(rs),
                PQresultErrorMessage(rs));
        }
        //ZZZZZZZZZZZZZZZZZZZZZ
        return default_prompt_rule(h, form_name, fieldname);
    }    
}
示例#12
0
/*
 * 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.
 */
bool
SendQuery(const char *query)
{
	PGresult   *results;
	PGTransactionStatusType transaction_status;
	double		elapsed_msec = 0;
	bool		OK = false;
	int			i;
	bool		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");
		goto sendquery_cleanup;
	}

	if (pset.singlestep)
	{
		char		buf[3];

		fflush(stderr);
		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')
				goto sendquery_cleanup;
		if (cancel_pressed)
			goto sendquery_cleanup;
	}
	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));
			ClearOrSaveResult(results);
			ResetCancelConn();
			goto sendquery_cleanup;
		}
		ClearOrSaveResult(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)
		{
			char		sverbuf[32];

			psql_error("The server (version %s) does not support savepoints for ON_ERROR_ROLLBACK.\n",
					   formatPGVersionNumber(pset.sversion, false,
											 sverbuf, sizeof(sverbuf)));
			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));
				ClearOrSaveResult(results);
				ResetCancelConn();
				goto sendquery_cleanup;
			}
			ClearOrSaveResult(results);
			on_error_rollback_savepoint = true;
		}
	}

	if (pset.fetch_count <= 0 || pset.gexec_flag ||
		pset.crosstab_flag || !is_select_command(query))
	{
		/* Default fetch-it-all-and-print mode */
		instr_time	before,
					after;

		if (pset.timing)
			INSTR_TIME_SET_CURRENT(before);

		results = PQexec(pset.db, query);

		/* these operations are included in the timing result: */
		ResetCancelConn();
		OK = ProcessResult(&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 && results)
			OK = PrintQueryResults(results);
	}
	else
	{
		/* Fetch-in-segments mode */
		OK = ExecQueryUsingCursor(query, &elapsed_msec);
		ResetCancelConn();
		results = NULL;			/* PQclear(NULL) does nothing */
	}

	if (!OK && pset.echo == PSQL_ECHO_ERRORS)
		psql_error("STATEMENT:  %s\n", query);

	/* If we made a temporary savepoint, possibly release/rollback */
	if (on_error_rollback_savepoint)
	{
		const char *svptcmd = NULL;

		transaction_status = PQtransactionStatus(pset.db);

		switch (transaction_status)
		{
			case PQTRANS_INERROR:
				/* We always rollback on an error */
				svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint";
				break;

			case PQTRANS_IDLE:
				/* If they are no longer in a transaction, then do nothing */
				break;

			case PQTRANS_INTRANS:

				/*
				 * 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;
				else
					svptcmd = "RELEASE pg_psql_temporary_savepoint";
				break;

			case PQTRANS_ACTIVE:
			case PQTRANS_UNKNOWN:
			default:
				OK = false;
				/* PQTRANS_UNKNOWN is expected given a broken connection. */
				if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp())
					psql_error("unexpected transaction status (%d)\n",
							   transaction_status);
				break;
		}

		if (svptcmd)
		{
			PGresult   *svptres;

			svptres = PQexec(pset.db, svptcmd);
			if (PQresultStatus(svptres) != PGRES_COMMAND_OK)
			{
				psql_error("%s", PQerrorMessage(pset.db));
				ClearOrSaveResult(svptres);
				OK = false;

				PQclear(results);
				ResetCancelConn();
				goto sendquery_cleanup;
			}
			PQclear(svptres);
		}
	}

	ClearOrSaveResult(results);

	/* Possible microtiming output */
	if (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();

	/* perform cleanup that should occur after any attempted query */

sendquery_cleanup:

	/* reset \g's output-to-filename trigger */
	if (pset.gfname)
	{
		free(pset.gfname);
		pset.gfname = NULL;
	}

	/* reset \gset trigger */
	if (pset.gset_prefix)
	{
		free(pset.gset_prefix);
		pset.gset_prefix = NULL;
	}

	/* reset \gexec trigger */
	pset.gexec_flag = false;

	/* reset \crosstabview trigger */
	pset.crosstab_flag = false;
	for (i = 0; i < lengthof(pset.ctv_args); i++)
	{
		pg_free(pset.ctv_args[i]);
		pset.ctv_args[i] = NULL;
	}

	return OK;
}
示例#13
0
static void
thread_DispatchWaitSingle(DispatchCommandParms * pParms)
{
	SegmentDatabaseDescriptor *segdbDesc;
	CdbDispatchResult *dispatchResult;
	char *msg = NULL;

	/*
	 * Assert() cannot be used in threads
	 */
	if (pParms->db_count != 1)
		write_log("Bug... thread_dispatchWaitSingle called with db_count %d",
				  pParms->db_count);

	dispatchResult = pParms->dispatchResultPtrArray[0];
	segdbDesc = dispatchResult->segdbDesc;

	if (PQstatus(segdbDesc->conn) == CONNECTION_BAD)
	{
		msg = PQerrorMessage(segdbDesc->conn);

		/*
		 * Save error info for later.
		 */
		cdbdisp_appendMessage(dispatchResult, DEBUG1,
							  ERRCODE_GP_INTERCONNECTION_ERROR,
							  "Lost connection to %s.  %s",
							  segdbDesc->whoami, msg ? msg : "");

		/*
		 * Free the PGconn object.
		 */
		PQfinish(segdbDesc->conn);
		segdbDesc->conn = NULL;
		dispatchResult->stillRunning = false;
	}
	else
	{
		PQsetnonblocking(segdbDesc->conn, FALSE);

		for (;;)
		{
			PGresult *pRes;
			ExecStatusType resultStatus;
			int	resultIndex = cdbdisp_numPGresult(dispatchResult);

			if (DEBUG4 >= log_min_messages)
				write_log("PQgetResult, resultIndex = %d", resultIndex);
			/*
			 * Get one message.
			 */
			pRes = PQgetResult(segdbDesc->conn);

			CollectQEWriterTransactionInformation(segdbDesc, dispatchResult);

			/*
			 * Command is complete when PGgetResult() returns NULL. It is critical
			 * that for any connection that had an asynchronous command sent thru
			 * it, we call PQgetResult until it returns NULL. Otherwise, the next
			 * time a command is sent to that connection, it will return an error
			 * that there's a command pending.
			 */
			if (!pRes)
			{
				if (DEBUG4 >= log_min_messages)
				{
					/*
					 * Don't use elog, it's not thread-safe
					 */
					write_log("%s -> idle", segdbDesc->whoami);
				}
				break;
			}

			/*
			 * Attach the PGresult object to the CdbDispatchResult object.
			 */
			cdbdisp_appendResult(dispatchResult, pRes);

			/*
			 * Did a command complete successfully?
			 */
			resultStatus = PQresultStatus(pRes);
			if (resultStatus == PGRES_COMMAND_OK ||
				resultStatus == PGRES_TUPLES_OK ||
				resultStatus == PGRES_COPY_IN ||
				resultStatus == PGRES_COPY_OUT)
			{
				/*
				 * Save the index of the last successful PGresult. Can be given to
				 * cdbdisp_getPGresult() to get tuple count, etc.
				 */
				dispatchResult->okindex = resultIndex;

				if (DEBUG3 >= log_min_messages)
				{
					/*
					 * Don't use elog, it's not thread-safe
					 */
					char *cmdStatus = PQcmdStatus(pRes);

					write_log("%s -> ok %s",
							  segdbDesc->whoami,
							  cmdStatus ? cmdStatus : "(no cmdStatus)");
				}

				if (resultStatus == PGRES_COPY_IN ||
					resultStatus == PGRES_COPY_OUT)
					return;
			}

			/*
			 * Note QE error.  Cancel the whole statement if requested.
			 */
			else
			{
				char *sqlstate = PQresultErrorField(pRes, PG_DIAG_SQLSTATE);
				int	errcode = 0;

				msg = PQresultErrorMessage(pRes);

				if (DEBUG2 >= log_min_messages)
				{
					/*
					 * Don't use elog, it's not thread-safe
					 */
					write_log("%s -> %s %s  %s",
							  segdbDesc->whoami,
							  PQresStatus(resultStatus),
							  sqlstate ? sqlstate : "(no SQLSTATE)",
							  msg ? msg : "");
				}

				/*
				 * Convert SQLSTATE to an error code (ERRCODE_xxx). Use a generic
				 * nonzero error code if no SQLSTATE.
				 */
				if (sqlstate && strlen(sqlstate) == 5)
					errcode = sqlstate_to_errcode(sqlstate);

				/*
				 * Save first error code and the index of its PGresult buffer
				 * entry.
				 */
				cdbdisp_seterrcode(errcode, resultIndex, dispatchResult);
			}
		}


		if (DEBUG4 >= log_min_messages)
			write_log("processResultsSingle says we are finished with :  %s",
					  segdbDesc->whoami);
		dispatchResult->stillRunning = false;
		if (DEBUG1 >= log_min_messages)
		{
			char msec_str[32];

			switch (check_log_duration(msec_str, false))
			{
				case 1:
				case 2:
					write_log
						("duration to dispatch result received from thread (seg %d): %s ms",
						 dispatchResult->segdbDesc->segindex, msec_str);
					break;
			}
		}
		if (PQisBusy(dispatchResult->segdbDesc->conn))
			write_log
				("We thought we were done, because finished==true, but libpq says we are still busy");
	}
}
示例#14
0
static bool
processResults(CdbDispatchResult * dispatchResult)
{
	SegmentDatabaseDescriptor *segdbDesc = dispatchResult->segdbDesc;
	char *msg;
	int	rc;

	/*
	 * PQisBusy() has side-effects
	 */
	if (DEBUG5 >= log_min_messages)
	{
		write_log("processResults.  isBusy = %d", PQisBusy(segdbDesc->conn));

		if (PQstatus(segdbDesc->conn) == CONNECTION_BAD)
			goto connection_error;
	}

	/*
	 * Receive input from QE.
	 */
	rc = PQconsumeInput(segdbDesc->conn);

	/*
	 * If PQconsumeInput fails, we're hosed. 
	 */
	if (rc == 0)
	{							/* handle PQconsumeInput error */
		goto connection_error;
	}

	/*
	 * PQisBusy() has side-effects
	 */
	if (DEBUG4 >= log_min_messages && PQisBusy(segdbDesc->conn))
		write_log("PQisBusy");

	/*
	 * If we have received one or more complete messages, process them.
	 */
	while (!PQisBusy(segdbDesc->conn))
	{
		/* loop to call PQgetResult; won't block */
		PGresult *pRes;
		ExecStatusType resultStatus;
		int	resultIndex;

		/*
		 * PQisBusy() does some error handling, which can
		 * cause the connection to die -- we can't just continue on as
		 * if the connection is happy without checking first.
		 * 
		 * For example, cdbdisp_numPGresult() will return a completely
		 * bogus value!
		 */
		if (PQstatus(segdbDesc->conn) == CONNECTION_BAD
			|| segdbDesc->conn->sock == -1)
		{
			goto connection_error;
		}

		resultIndex = cdbdisp_numPGresult(dispatchResult);

		if (DEBUG4 >= log_min_messages)
			write_log("PQgetResult");
		/*
		 * Get one message.
		 */
		pRes = PQgetResult(segdbDesc->conn);

		CollectQEWriterTransactionInformation(segdbDesc, dispatchResult);

		/*
		 * Command is complete when PGgetResult() returns NULL. It is critical
		 * that for any connection that had an asynchronous command sent thru
		 * it, we call PQgetResult until it returns NULL. Otherwise, the next
		 * time a command is sent to that connection, it will return an error
		 * that there's a command pending.
		 */
		if (!pRes)
		{
			if (DEBUG4 >= log_min_messages)
			{
				/*
				 * Don't use elog, it's not thread-safe
				 */
				write_log("%s -> idle", segdbDesc->whoami);
			}
			/* this is normal end of command */
			return true;
		} /* end of results */


		/*
		 * Attach the PGresult object to the CdbDispatchResult object.
		 */
		cdbdisp_appendResult(dispatchResult, pRes);

		/*
		 * Did a command complete successfully?
		 */
		resultStatus = PQresultStatus(pRes);
		if (resultStatus == PGRES_COMMAND_OK ||
			resultStatus == PGRES_TUPLES_OK ||
			resultStatus == PGRES_COPY_IN || resultStatus == PGRES_COPY_OUT)
		{

			/*
			 * Save the index of the last successful PGresult. Can be given to
			 * cdbdisp_getPGresult() to get tuple count, etc.
			 */
			dispatchResult->okindex = resultIndex;

			if (DEBUG3 >= log_min_messages)
			{
				/*
				 * Don't use elog, it's not thread-safe
				 */
				char	   *cmdStatus = PQcmdStatus(pRes);

				write_log("%s -> ok %s",
						  segdbDesc->whoami,
						  cmdStatus ? cmdStatus : "(no cmdStatus)");
			}

			/*
			 * SREH - get number of rows rejected from QE if any
			 */
			if (pRes->numRejected > 0)
				dispatchResult->numrowsrejected += pRes->numRejected;

			if (resultStatus == PGRES_COPY_IN ||
				resultStatus == PGRES_COPY_OUT)
				return true;
		}

		/*
		 * Note QE error. Cancel the whole statement if requested.
		 */
		else
		{
			/* QE reported an error */
			char	   *sqlstate = PQresultErrorField(pRes, PG_DIAG_SQLSTATE);
			int			errcode = 0;

			msg = PQresultErrorMessage(pRes);

			if (DEBUG2 >= log_min_messages)
			{
				/*
				 * Don't use elog, it's not thread-safe
				 */
				write_log("%s -> %s %s  %s",
						  segdbDesc->whoami,
						  PQresStatus(resultStatus),
						  sqlstate ? sqlstate : "(no SQLSTATE)",
						  msg ? msg : "");
			}

			/*
			 * Convert SQLSTATE to an error code (ERRCODE_xxx). Use a generic
			 * nonzero error code if no SQLSTATE.
			 */
			if (sqlstate && strlen(sqlstate) == 5)
				errcode = sqlstate_to_errcode(sqlstate);

			/*
			 * Save first error code and the index of its PGresult buffer
			 * entry.
			 */
			cdbdisp_seterrcode(errcode, resultIndex, dispatchResult);
		}
	}

	return false; /* we must keep on monitoring this socket */

connection_error:
	msg = PQerrorMessage(segdbDesc->conn);

	if (msg)
		write_log("Dispatcher encountered connection error on %s: %s",
				  segdbDesc->whoami, msg);

	/*
	 * Save error info for later.
	 */
	cdbdisp_appendMessage(dispatchResult, LOG,
						  ERRCODE_GP_INTERCONNECTION_ERROR,
						  "Error on receive from %s: %s",
						  segdbDesc->whoami, msg ? msg : "unknown error");

	/*
	 * Can't recover, so drop the connection. 
	 */
	PQfinish(segdbDesc->conn);
	segdbDesc->conn = NULL;
	dispatchResult->stillRunning = false;

	return true; /* connection is gone! */
}
示例#15
0
/* Complex checking of the query status */
    int
pgsql_query_checkstatus(PGresult *res)
{

    int status;
    int nFields;
    long long nTuples;

    /* 
       For successful queries, there are two options: either the query returns 
       results or not.  If it does not return data, but successfully completed, 
       then the status will be set to 
       PGRES_COMMAND_OK.  
       If success and returns tuples, then it will be set to 
       PGRES_TUPLES_OK 
       */


    status = PQresultStatus(res);

    if (PQresultStatus(res) == PGRES_COMMAND_OK)
    {
        /* Success but no results */
        IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, PQcmdStatus(res));
        return(MYPG_NO_RESULT);
    }

    if (PQresultStatus(res) != PGRES_TUPLES_OK)
    {
        IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, 
                PQresultErrorMessage(res));

        switch (status)
        {
            /* No results */
            case PGRES_COPY_IN:        return(MYPG_NO_RESULT);
            case PGRES_COPY_OUT:       return(MYPG_NO_RESULT);
            case PGRES_BAD_RESPONSE:   return(MYPG_NO_RESULT);
            case PGRES_NONFATAL_ERROR: return(MYPG_NO_RESULT);
                                       /* An error */
            case PGRES_FATAL_ERROR:    return(MYPG_FATAL_ERROR);
            default: break;
        } 
    }

    /* How many fields and rows did we return? */
    nFields = PQnfields(res);
    nTuples = PQntuples(res);

    /* Result is empty, either an error or this query returns no data */
    if (nTuples == 0) 
    {
        if (nFields == 0)
        {
            /* Query returns no data. Try to print a message to clarify */
            IDL_Message(IDL_M_NAMED_GENERIC, IDL_MSG_INFO, PQcmdStatus(res));
            return(MYPG_NO_RESULT);
        }
        else
            /* Probably nothing matched the query */
            return(MYPG_NO_RESULT);

    }

    return(MYPG_SUCCESS);

}
示例#16
0
static int aPGSQL_query(struct cw_channel *chan, void *data) {


    char *s1,*s2,*s3,*s4;
    char s[100] = "";
    char *querystring;
    char *var;
    int l;
    int res,nres;
    PGconn *karoto;
    PGresult *PGSQLres;
    int id,id1;
    char *stringp=NULL;


    res=0;
    l=strlen(data)+2;
    s1=malloc(l);
    s2=malloc(l);
    strncpy(s1, data, l - 1);
    stringp=s1;
    strsep(&stringp," "); /* eat the first token, we already know it :P  */
    s3=strsep(&stringp," ");
    while (1) {	/* ugly trick to make branches with break; */
        var=s3;
        s4=strsep(&stringp," ");
        id=atoi(s4);
        querystring=strsep(&stringp,"\n");
        if ((karoto=find_identifier(id,CW_PGSQL_ID_CONNID))==NULL) {
            cw_log(LOG_WARNING,"Invalid connection identifier %d passed in aPGSQL_query\n",id);
            res=-1;
            break;
        }
        PGSQLres=PQexec(karoto,querystring);
        if (PGSQLres==NULL) {
            cw_log(LOG_WARNING,"aPGSQL_query: Connection Error (connection identifier = %d, error message : %s)\n",id,PQerrorMessage(karoto));
            res=-1;
            break;
        }
        if (PQresultStatus(PGSQLres) == PGRES_BAD_RESPONSE ||
                PQresultStatus(PGSQLres) == PGRES_NONFATAL_ERROR ||
                PQresultStatus(PGSQLres) == PGRES_FATAL_ERROR) {
            cw_log(LOG_WARNING,"aPGSQL_query: Query Error (connection identifier : %d, error message : %s)\n",id,PQcmdStatus(PGSQLres));
            res=-1;
            break;
        }
        nres=PQnfields(PGSQLres);
        id1=add_identifier(CW_PGSQL_ID_RESID,PGSQLres);
        snprintf(s, sizeof(s), "%d", id1);
        pbx_builtin_setvar_helper(chan,var,s);
        break;
    }

    free(s1);
    free(s2);

    return(res);
}
ngx_int_t
ngx_postgres_process_response(ngx_http_request_t *r, PGresult *res)
{
    ngx_postgres_loc_conf_t      *pglcf;
    ngx_postgres_ctx_t           *pgctx;
    ngx_postgres_rewrite_conf_t  *pgrcf;
    ngx_postgres_variable_t      *pgvar;
    ngx_str_t                    *store;
    char                         *affected;
    size_t                        affected_len;
    ngx_uint_t                    i;
    ngx_int_t                     rc;

    dd("entering");

    pglcf = ngx_http_get_module_loc_conf(r, ngx_postgres_module);
    pgctx = ngx_http_get_module_ctx(r, ngx_postgres_module);

    /* set $postgres_columns */
    pgctx->var_cols = PQnfields(res);

    /* set $postgres_rows */
    pgctx->var_rows = PQntuples(res);

    /* set $postgres_affected */
    if (ngx_strncmp(PQcmdStatus(res), "SELECT", sizeof("SELECT") - 1)) {
        affected = PQcmdTuples(res);
        affected_len = ngx_strlen(affected);
        if (affected_len) {
            pgctx->var_affected = ngx_atoi((u_char *) affected, affected_len);
        }
    }

    if (pglcf->rewrites) {
        /* process rewrites */
        pgrcf = pglcf->rewrites->elts;
        for (i = 0; i < pglcf->rewrites->nelts; i++) {
            rc = pgrcf[i].handler(r, &pgrcf[i]);
            if (rc != NGX_DECLINED) {
                if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
                    dd("returning NGX_DONE, status %d", (int) rc);
                    pgctx->status = rc;
                    return NGX_DONE;
                }

                pgctx->status = rc;
                break;
            }
        }
    }

    if (pglcf->variables) {
        /* set custom variables */
        pgvar = pglcf->variables->elts;
        store = pgctx->variables->elts;

        for (i = 0; i < pglcf->variables->nelts; i++) {
            store[i] = ngx_postgres_variable_set_custom(r, res, &pgvar[i]);
            if ((store[i].len == 0) && (pgvar[i].value.required)) {
                dd("returning NGX_DONE, status NGX_HTTP_INTERNAL_SERVER_ERROR");
                pgctx->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
                return NGX_DONE;
            }
        }
    }

    if (pglcf->output_handler) {
        /* generate output */
        dd("returning");
        return pglcf->output_handler(r, res);
    }

    dd("returning NGX_DONE");
    return NGX_DONE;
}
示例#18
0
文件: common.c 项目: PJMODOS/postgres
/*
 * PSQLexecWatch
 *
 * This function is used for \watch command to send the query to
 * the server and print out the results.
 *
 * Returns 1 if the query executed successfully, 0 if it cannot be repeated,
 * e.g., because of the interrupt, -1 on error.
 */
int
PSQLexecWatch(const char *query, const printQueryOpt *opt)
{
	PGresult   *res;
	double	elapsed_msec = 0;
	instr_time	before;
	instr_time	after;

	if (!pset.db)
	{
		psql_error("You are currently not connected to a database.\n");
		return 0;
	}

	SetCancelConn();

	if (pset.timing)
		INSTR_TIME_SET_CURRENT(before);

	res = PQexec(pset.db, query);

	ResetCancelConn();

	if (!AcceptResult(res))
	{
		PQclear(res);
		return 0;
	}

	if (pset.timing)
	{
		INSTR_TIME_SET_CURRENT(after);
		INSTR_TIME_SUBTRACT(after, before);
		elapsed_msec = INSTR_TIME_GET_MILLISEC(after);
	}

	/*
	 * If SIGINT is sent while the query is processing, the interrupt
	 * will be consumed.  The user's intention, though, is to cancel
	 * the entire watch process, so detect a sent cancellation request and
	 * exit in this case.
	 */
	if (cancel_pressed)
	{
		PQclear(res);
		return 0;
	}

	switch (PQresultStatus(res))
	{
		case PGRES_TUPLES_OK:
			printQuery(res, opt, pset.queryFout, pset.logfile);
			break;

		case PGRES_COMMAND_OK:
			fprintf(pset.queryFout, "%s\n%s\n\n", opt->title, PQcmdStatus(res));
			break;

		case PGRES_EMPTY_QUERY:
			psql_error(_("\\watch cannot be used with an empty query\n"));
			PQclear(res);
			return -1;

		case PGRES_COPY_OUT:
		case PGRES_COPY_IN:
		case PGRES_COPY_BOTH:
			psql_error(_("\\watch cannot be used with COPY\n"));
			PQclear(res);
			return -1;

		default:
			psql_error(_("unexpected result status for \\watch\n"));
			PQclear(res);
			return -1;
	}

	PQclear(res);

	fflush(pset.queryFout);

	/* Possible microtiming output */
	if (pset.timing)
		printf(_("Time: %.3f ms\n"), elapsed_msec);

	return 1;
}
示例#19
0
static void
pgsql_cursor_statement_detect (GSQLCursor *cursor) {
	GSQL_TRACE_FUNC;
	
	gchar *stmt_char;
	gchar *affect = NULL;
	GSQLEPGSQLCursor  *e_cursor = NULL;
	
	e_cursor = cursor->spec;
	e_cursor->count = 0;
	cursor->stmt_affected_rows = 0;
	
	affect = PQcmdTuples(e_cursor->result);
	
	stmt_char = PQcmdStatus (e_cursor->result);
	GSQL_DEBUG("STMT [%s]", stmt_char);
	
	switch (0) {
		case 0:
			if (g_str_has_prefix (stmt_char, "SELECT")) {
				GSQL_DEBUG ("'select' statement");
				cursor->stmt_type = GSQL_CURSOR_STMT_SELECT;
				e_cursor->count = PQntuples(e_cursor->result);
				break;
			}
      
			if (g_str_has_prefix (stmt_char, "INSERT")) {
				GSQL_DEBUG ("'insert' statement");
				cursor->stmt_type = GSQL_CURSOR_STMT_INSERT;
				cursor->stmt_affected_rows = strtoull (affect,
								       NULL,
								       10);
				break;
			}
			
			if (g_str_has_prefix (stmt_char, "UPDATE")) {
				GSQL_DEBUG ("'update' statement");
				cursor->stmt_type = GSQL_CURSOR_STMT_UPDATE;
				cursor->stmt_affected_rows = strtoull (affect, 
								       NULL,
								       10);
				break;
			}
      
			if (g_str_has_prefix (stmt_char, "DELETE")) {
				GSQL_DEBUG ("'delete' statement");
				cursor->stmt_type = GSQL_CURSOR_STMT_DELETE;
				cursor->stmt_affected_rows = strtoull (affect,
								       NULL,
								       10);
				break;
			}
				
			if (g_str_has_prefix (stmt_char, "CREATE")) {
				GSQL_DEBUG ("'create' statement");
				cursor->stmt_type = GSQL_CURSOR_STMT_CREATE;
				break;
			}
			
			if (g_str_has_prefix (stmt_char, "DROP")) {
				GSQL_DEBUG ("'drop' statement");
				cursor->stmt_type = GSQL_CURSOR_STMT_DROP;
				break;
			}
      
			if (g_str_has_prefix (stmt_char, "ALTER")) {
				GSQL_DEBUG ("'alter' statement");
				cursor->stmt_type = GSQL_CURSOR_STMT_ALTER;
				break;
			}
			
		default:
			GSQL_DEBUG ("default 'exec' statement");
			cursor->stmt_type = GSQL_CURSOR_STMT_EXEC;
	}
}
示例#20
0
/*
 * Receive and process input from one QE.
 *
 * Return true if all input are consumed or the connection went wrong.
 * Return false if there'er still more data expected.
 */
static bool
processResults(CdbDispatchResult * dispatchResult)
{
	SegmentDatabaseDescriptor *segdbDesc = dispatchResult->segdbDesc;
	char *msg;

	/*
	 * Receive input from QE.
	 */
	if (PQconsumeInput(segdbDesc->conn) == 0)
	{
		msg = PQerrorMessage(segdbDesc->conn);
		cdbdisp_appendMessageNonThread(dispatchResult, LOG,
							  "Error on receive from %s: %s",
							  segdbDesc->whoami, msg ? msg : "unknown error");
		return true;
	}

	/*
	 * If we have received one or more complete messages, process them.
	 */
	while (!PQisBusy(segdbDesc->conn))
	{
		/* loop to call PQgetResult; won't block */
		PGresult *pRes;
		ExecStatusType resultStatus;
		int	resultIndex;

		/*
		 * PQisBusy() does some error handling, which can
		 * cause the connection to die -- we can't just continue on as
		 * if the connection is happy without checking first.
		 *
		 * For example, cdbdisp_numPGresult() will return a completely
		 * bogus value!
		 */
		if (cdbconn_isBadConnection(segdbDesc))
		{
			msg = PQerrorMessage(segdbDesc->conn);
			cdbdisp_appendMessageNonThread(dispatchResult, LOG,
								  "Connection lost when receiving from %s: %s",
								  segdbDesc->whoami, msg ? msg : "unknown error");
			return true;
		}

		/*
		 * Get one message.
		 */
		ELOG_DISPATCHER_DEBUG("PQgetResult");
		pRes = PQgetResult(segdbDesc->conn);

		/*
		 * Command is complete when PGgetResult() returns NULL. It is critical
		 * that for any connection that had an asynchronous command sent thru
		 * it, we call PQgetResult until it returns NULL. Otherwise, the next
		 * time a command is sent to that connection, it will return an error
		 * that there's a command pending.
		 */
		if (!pRes)
		{
			ELOG_DISPATCHER_DEBUG("%s -> idle", segdbDesc->whoami);
			/* this is normal end of command */
			return true;
		}

		/*
		 * Attach the PGresult object to the CdbDispatchResult object.
		 */
		resultIndex = cdbdisp_numPGresult(dispatchResult);
		cdbdisp_appendResult(dispatchResult, pRes);

		/*
		 * Did a command complete successfully?
		 */
		resultStatus = PQresultStatus(pRes);
		if (resultStatus == PGRES_COMMAND_OK ||
			resultStatus == PGRES_TUPLES_OK ||
			resultStatus == PGRES_COPY_IN ||
			resultStatus == PGRES_COPY_OUT ||
			resultStatus == PGRES_EMPTY_QUERY)
		{
			ELOG_DISPATCHER_DEBUG("%s -> ok %s",
								 segdbDesc->whoami,
								 PQcmdStatus(pRes) ? PQcmdStatus(pRes) : "(no cmdStatus)");

			if (resultStatus == PGRES_EMPTY_QUERY)
				ELOG_DISPATCHER_DEBUG("QE received empty query.");

			/*
			 * Save the index of the last successful PGresult. Can be given to
			 * cdbdisp_getPGresult() to get tuple count, etc.
			 */
			dispatchResult->okindex = resultIndex;

			/*
			 * SREH - get number of rows rejected from QE if any
			 */
			if (pRes->numRejected > 0)
				dispatchResult->numrowsrejected += pRes->numRejected;

			if (resultStatus == PGRES_COPY_IN ||
				resultStatus == PGRES_COPY_OUT)
				return true;
		}
		/*
		 * Note QE error. Cancel the whole statement if requested.
		 */
		else
		{
			/* QE reported an error */
			char	   *sqlstate = PQresultErrorField(pRes, PG_DIAG_SQLSTATE);
			int			errcode = 0;

			msg = PQresultErrorMessage(pRes);

			ELOG_DISPATCHER_DEBUG("%s -> %s %s  %s",
								 segdbDesc->whoami,
								 PQresStatus(resultStatus),
								 sqlstate ? sqlstate : "(no SQLSTATE)",
								 msg);

			/*
			 * Convert SQLSTATE to an error code (ERRCODE_xxx). Use a generic
			 * nonzero error code if no SQLSTATE.
			 */
			if (sqlstate && strlen(sqlstate) == 5)
				errcode = sqlstate_to_errcode(sqlstate);

			/*
			 * Save first error code and the index of its PGresult buffer
			 * entry.
			 */
			cdbdisp_seterrcode(errcode, resultIndex, dispatchResult);
		}
	}

	return false; /* we must keep on monitoring this socket */
}