| /*------------------------------------------------------------------------- |
| * |
| * cdbdispatchresult.h |
| * routines for processing dispatch results. |
| * |
| * Portions Copyright (c) 2005-2008, Greenplum inc |
| * Portions Copyright (c) 2012-Present VMware, Inc. or its affiliates. |
| * |
| * |
| * IDENTIFICATION |
| * src/include/cdb/cdbdispatchresult.h |
| * |
| *------------------------------------------------------------------------- |
| */ |
| #ifndef CDBDISPATCHRESULT_H |
| #define CDBDISPATCHRESULT_H |
| |
| #include "cdb/cdbdisp.h" |
| #include "commands/tablecmds.h" |
| #include "utils/hsearch.h" |
| |
| struct pg_result; /* PGresult ... #include "libpq-fe.h" */ |
| struct SegmentDatabaseDescriptor; /* #include "cdb/cdbconn.h" */ |
| struct StringInfoData; /* #include "lib/stringinfo.h" */ |
| struct PQExpBufferData; /* #include "libpq-int.h" */ |
| struct pgNotify; /* PGnotify ... #include "libpq-fe.h" */ |
| |
| typedef struct CdbPgResults |
| { |
| struct pg_result **pg_results; |
| int numResults; |
| int numDispatches; /* the number of dispatched QE, from CdbDispatchResults.resultCount */ |
| }CdbPgResults; |
| |
| /* |
| * CdbDispatchResults_SliceInfo: |
| * An entry in a CdbDispatchResults object's slice map. |
| * Used to find the CdbDispatchResult objects for a gang |
| * of QEs given their slice index. |
| */ |
| typedef struct CdbDispatchResults_SliceInfo |
| { |
| int resultBegin; |
| int resultEnd; |
| } CdbDispatchResults_SliceInfo; |
| |
| /* |
| * CdbDispatchResult: |
| * Struct for holding the result information |
| * for a command dispatched by CdbCommandDispatch to |
| * a single segdb. |
| */ |
| typedef struct CdbDispatchResult |
| { |
| /* |
| * libpq connection to QE process; |
| * * reset to NULL after end of thread |
| */ |
| struct SegmentDatabaseDescriptor *segdbDesc; |
| |
| /* owner of this CdbDispatchResult */ |
| struct CdbDispatchResults *meleeResults; |
| |
| /* |
| * index of this entry within |
| * results->resultArray |
| */ |
| int meleeIndex; |
| |
| /* |
| * ERRCODE_xxx (sqlstate encoded as |
| * an int) of first error, or 0. |
| */ |
| int errcode; |
| |
| /* |
| * index of last entry in resultbuf |
| * with resultStatus == PGRES_TUPLES_OK |
| * or PGRES_COMMAND_OK (command ended |
| * successfully); or -1. |
| * Pass to cdbconn_getResult(). |
| */ |
| int okindex; |
| |
| /* |
| * array of ptr to PGresult |
| */ |
| struct PQExpBufferData *resultbuf; |
| |
| /* string of messages; or NULL */ |
| struct PQExpBufferData *error_message; |
| |
| /* true => PQsendCommand done */ |
| bool hasDispatched; |
| |
| /* true => busy in dispatch thread */ |
| bool stillRunning; |
| |
| /* |
| * true => received specified acknowledge message from libpq. |
| * Should set to false before receive new message |
| */ |
| bool receivedAckMsg; |
| |
| /* type of signal sent */ |
| DispatchWaitMode sentSignal; |
| |
| /* |
| * true => got any of these errors: |
| * ERRCODE_GP_OPERATION_CANCELED |
| * ERRCODE_QUERY_CANCELED |
| */ |
| bool wasCanceled; |
| |
| /* num rows rejected in SREH mode */ |
| int numrowsrejected; |
| |
| /* num rows completed in COPY FROM */ |
| int numrowscompleted; |
| |
| /* |
| * queue for acknowledge NOTIFY messages, get freed for |
| * each cdbdisp_waitDispatchAckMessage call |
| */ |
| struct pgNotify *ackPGNotifies; |
| } CdbDispatchResult; |
| |
| /* |
| * CdbDispatchResults: |
| * A collection of CdbDispatchResult objects to hold and summarize |
| * the results of dispatching a command or plan to one or more Gangs. |
| */ |
| typedef struct CdbDispatchResults |
| { |
| /* |
| * Array of CdbDispatchResult objects, one per QE |
| */ |
| CdbDispatchResult *resultArray; |
| |
| /* |
| * num of assigned slots (num of QEs) |
| * 0 <= resultCount <= resultCapacity |
| */ |
| int resultCount; |
| |
| /* size of resultArray (total #slots) */ |
| int resultCapacity; |
| |
| /* |
| * index of the resultArray entry for |
| * the QE that was first to report an |
| * error; or -1 if no error. |
| */ |
| volatile int iFirstError; |
| |
| /* |
| * ERRCODE_xxx (sqlstate encoded as |
| * an int) of the first error, or 0. |
| */ |
| volatile int errcode; |
| |
| /* true => stop remaining QEs on err */ |
| bool cancelOnError; |
| |
| /* |
| * Map: sliceIndex => resultArray index |
| */ |
| CdbDispatchResults_SliceInfo *sliceMap; |
| |
| /* num of slots in sliceMap */ |
| int sliceCapacity; |
| } CdbDispatchResults; |
| |
| |
| /* |
| * Create a CdbDispatchResult object, appending it to the |
| * resultArray of a given CdbDispatchResults object. |
| */ |
| CdbDispatchResult * |
| cdbdisp_makeResult(struct CdbDispatchResults *meleeResults, |
| struct SegmentDatabaseDescriptor *segdbDesc, |
| int sliceIndex); |
| |
| /* |
| * Destroy a CdbDispatchResult object. |
| */ |
| void |
| cdbdisp_termResult(CdbDispatchResult *dispatchResult); |
| |
| /* |
| * Reset a CdbDispatchResult object for possible reuse. |
| */ |
| void |
| cdbdisp_resetResult(CdbDispatchResult *dispatchResult); |
| |
| /* |
| * Take note of an error. |
| * 'errcode' is the ERRCODE_xxx value for setting the client's SQLSTATE. |
| * NB: This can be called from a dispatcher thread, so it must not use |
| * palloc/pfree or elog/ereport because they are not thread safe. |
| */ |
| void |
| cdbdisp_seterrcode(int errcode, /* ERRCODE_xxx or 0 */ |
| int resultIndex, /* -1 if no PGresult */ |
| CdbDispatchResult *dispatchResult); |
| |
| /* |
| * Format a message, printf-style, and append to the error_message buffer. |
| * Also write it to stderr if logging is enabled for messages of the |
| * given severity level 'elevel' (for example, DEBUG1; or 0 to suppress). |
| * 'errcode' is the ERRCODE_xxx value for setting the client's SQLSTATE. |
| * NB: This can be called from a dispatcher thread, so it must not use |
| * palloc/pfree or elog/ereport because they are not thread safe. |
| */ |
| void |
| cdbdisp_appendMessageNonThread(CdbDispatchResult *dispatchResult, |
| int errcode, |
| const char *fmt, |
| ...) |
| pg_attribute_printf(3, 4); |
| |
| |
| /* |
| * Store a PGresult object ptr in the result buffer. |
| * NB: Caller must not PQclear() the PGresult object. |
| */ |
| void |
| cdbdisp_appendResult(CdbDispatchResult *dispatchResult, |
| struct pg_result *res); |
| |
| /* |
| * Return the i'th PGresult object ptr (if i >= 0), or |
| * the n+i'th one (if i < 0), or NULL (if i out of bounds). |
| * NB: Caller must not PQclear() the PGresult object. |
| */ |
| struct pg_result * |
| cdbdisp_getPGresult(CdbDispatchResult *dispatchResult, int i); |
| |
| /* |
| * Return the number of PGresult objects in the result buffer. |
| */ |
| int |
| cdbdisp_numPGresult(CdbDispatchResult *dispatchResult); |
| |
| /* |
| * Display a CdbDispatchResult in the log for debugging. |
| * Call only from main thread, during or after cdbdisp_checkDispatchResults. |
| */ |
| void |
| cdbdisp_debugDispatchResult(CdbDispatchResult *dispatchResult); |
| |
| /* |
| * Construct an ErrorData from the dispatch results. |
| */ |
| ErrorData * |
| cdbdisp_dumpDispatchResult(CdbDispatchResult *dispatchResult); |
| |
| /* |
| * Format a CdbDispatchResults object. |
| * Appends error messages to caller's StringInfo buffer. |
| * Returns ERRCODE_xxx if some error was found, or 0 if no errors. |
| * Before calling this function, you must call CdbCheckDispatchResult(). |
| */ |
| void |
| cdbdisp_dumpDispatchResults(struct CdbDispatchResults *gangResults, |
| ErrorData **qeError); |
| |
| extern ErrorData *cdbdisp_get_PQerror(struct pg_result *pgresult); |
| |
| /* |
| * Return sum of the cmdTuples values from CdbDispatchResult |
| * entries that have a successful PGresult. If sliceIndex >= 0, |
| * uses only the entries belonging to the specified slice. |
| */ |
| int64 |
| cdbdisp_sumCmdTuples(CdbDispatchResults *results, int sliceIndex); |
| |
| /* |
| * If several tuples were eliminated/rejected from the result because of |
| * bad data formatting (this is currenly only possible in external tables |
| * with single row error handling) - sum up the total rows rejected from |
| * all QE's and notify the client. |
| */ |
| void |
| cdbdisp_sumRejectedRows(CdbDispatchResults *results); |
| |
| /* |
| * Return ptr to first resultArray entry for a given sliceIndex. |
| */ |
| CdbDispatchResult * |
| cdbdisp_resultBegin(CdbDispatchResults *results, int sliceIndex); |
| |
| /* |
| * Return ptr to last+1 resultArray entry for a given sliceIndex. |
| */ |
| CdbDispatchResult * |
| cdbdisp_resultEnd(CdbDispatchResults *results, int sliceIndex); |
| |
| void |
| cdbdisp_returnResults(CdbDispatchResults *primaryResults, CdbPgResults *cdb_pgresults); |
| |
| /* |
| * used in the interconnect on the dispatcher to avoid error-cleanup deadlocks. |
| */ |
| bool |
| cdbdisp_checkResultsErrcode(struct CdbDispatchResults *meeleResults); |
| |
| /* |
| * cdbdisp_makeDispatchResults: |
| * Will be freed in function cdbdisp_destroyDispatcherState by deleting the |
| * memory context. |
| */ |
| void |
| cdbdisp_makeDispatchResults(struct CdbDispatcherState *ds, |
| int sliceCapacity, |
| bool cancelOnError); |
| |
| void |
| cdbdisp_clearCdbPgResults(CdbPgResults* cdb_pgresults); |
| typedef void (*ProcessDispatchResult_hook_type) (CdbDispatcherState*); |
| extern PGDLLIMPORT ProcessDispatchResult_hook_type ProcessDispatchResult_hook; |
| |
| #endif /* CDBDISPATCHRESULT_H */ |