Beispiel #1
0
/*
 * sum tuple counts that were added into a partitioned AO table
 */
HTAB *
cdbdisp_sumAoPartTupCount(PartitionNode *parts, CdbDispatchResults *results)
{
	int	i;
	HTAB *ht = NULL;

	if (!parts)
		return NULL;

	for (i = 0; i < results->resultCount; ++i)
	{
		CdbDispatchResult *dispatchResult = &results->resultArray[i];
		int	nres = cdbdisp_numPGresult(dispatchResult);
		int	ires;

		for (ires = 0; ires < nres; ++ires)
		{
			PGresult *pgresult = cdbdisp_getPGresult(dispatchResult, ires);

			ht = PQprocessAoTupCounts(parts, ht, (void *) pgresult->aotupcounts,
									 pgresult->naotupcounts);
		}
	}

	return ht;
}
Beispiel #2
0
void
cdbdisp_returnResults(CdbDispatchResults * primaryResults, CdbPgResults* cdb_pgresults)
{
	CdbDispatchResult *dispatchResult;
	int	nslots;
	int	nresults = 0;
	int	i;

	if (!primaryResults || !cdb_pgresults)
		return;

	/*
	 * Allocate result set ptr array. The caller must PQclear() each PGresult
	 * and free() the array.
	 */
	nslots = 0;

	for (i = 0; i < primaryResults->resultCount; ++i)
		nslots += cdbdisp_numPGresult(&primaryResults->resultArray[i]);


	cdb_pgresults->pg_results = (struct pg_result **)calloc(nslots, sizeof(struct pg_result*));

	if (!cdb_pgresults->pg_results)
		ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY),
						errmsg
						("cdbdisp_returnResults failed: out of memory")));

	/*
	 * Collect results from primary gang.
	 */
	for (i = 0; i < primaryResults->resultCount; ++i)
	{
		dispatchResult = &primaryResults->resultArray[i];

		/*
		 * Take ownership of this QE's PGresult object(s).
		 */
		nresults += cdbdisp_snatchPGresults(dispatchResult,
											cdb_pgresults->pg_results + nresults,
											nslots - nresults);
	}

	Assert(nresults == nslots);

	/* tell the caller how many sets we're returning. */
	cdb_pgresults->numResults = nresults;

}
Beispiel #3
0
/*
 * Format a CdbDispatchResult into a StringInfo buffer provided by caller.
 * It reports at most one error.
 */
void
cdbdisp_dumpDispatchResult(CdbDispatchResult *dispatchResult,
						   struct StringInfoData *buf)
{
	int ires;
	int nres;

	if (!dispatchResult || !buf)
		return;

	/*
	 * Format 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);

		/*
		 * QE success
		 */
		if (resultStatus == PGRES_COMMAND_OK ||
			resultStatus == PGRES_TUPLES_OK ||
			resultStatus == PGRES_COPY_IN ||
			resultStatus == PGRES_COPY_OUT ||
			resultStatus == PGRES_EMPTY_QUERY)
			continue;

		/*
		 * QE error or libpq error
		 */
		char *pri = PQresultErrorField(pgresult, PG_DIAG_MESSAGE_PRIMARY);
		char *dtl = PQresultErrorField(pgresult, PG_DIAG_MESSAGE_DETAIL);
		char *ctx = PQresultErrorField(pgresult, PG_DIAG_CONTEXT);

		oneTrailingNewline(buf);
		if (pri)
		{
			appendStringInfoString(buf, pri);
		}
		else
		{
			elog(LOG, "No primary message?");
			appendStringInfoString(buf, PQresultErrorMessage(pgresult));
		}

		if (whoami)
		{
			noTrailingNewline(buf);
			appendStringInfo(buf, "  (%s)", whoami);
		}

		if (dtl)
		{
			oneTrailingNewline(buf);
			appendStringInfo(buf, "%s", dtl);
		}

		if (ctx)
		{
			oneTrailingNewline(buf);
			appendStringInfo(buf, "%s", ctx);
		}

		noTrailingNewline(buf);
		return;
	}

	/*
	 * Error found on our side of the libpq interface?
	 */
	if (dispatchResult->error_message &&
		dispatchResult->error_message->len > 0)
	{
		oneTrailingNewline(buf);
		appendStringInfoString(buf, dispatchResult->error_message->data);
		noTrailingNewline(buf);
	}
}
Beispiel #4
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);
	}
}
Beispiel #5
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");
	}
}
Beispiel #6
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! */
}
Beispiel #7
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 */
}