SQLRETURN libpqPrepareOnThreadWithoutStoringResults()

in src/odbc/rsodbc/rslibpq.c [2689:2815]


SQLRETURN libpqPrepareOnThreadWithoutStoringResults(RS_STMT_INFO *pStmt, char *pszCmd)
{
    SQLRETURN rc = SQL_SUCCESS;
    RS_CONN_INFO *pConn = pStmt->phdbc;

    if(pszCmd)
    {
        PGresult *pgResult = NULL;
        ExecStatusType pqRc = PGRES_COMMAND_OK;
        int asyncEnable = isAsyncEnable(pStmt);
        int sendStatus = 1;

        if(asyncEnable)
        {
            sendStatus = pqSendPrepareAndDescribe(pConn->pgConn, pStmt->szCursorName, pszCmd, 0, NULL);

            if(sendStatus)
            {
                pgResult = PQgetResult(pConn->pgConn);
                pqRc = PQresultStatus(pgResult);
            }
            else
                pqRc = PGRES_FATAL_ERROR;
        }
        else
        {
            pgResult = pqPrepare(pConn->pgConn, pStmt->szCursorName, pszCmd, 0, NULL);
            pqRc = PQresultStatus(pgResult);
        }

        // Multi prepare loop
        do
        {
            if(!(pqRc == PGRES_COMMAND_OK
                    || pqRc == PGRES_TUPLES_OK
                    || pqRc == PGRES_COPY_IN
                    || pqRc == PGRES_COPY_OUT))
            {
                char *pError = libpqErrorMsg(pConn);

                // Even one result in error, we are retuning error.
                rc = SQL_ERROR;

                if(pError && *pError != '\0')
                    addError(&pStmt->pErrorList,"HY000", pError, 0, pConn);

                // Clear this result because we are not storing it
                PQclear(pgResult);
                pgResult = NULL;
            }
            else
            {
                PGresult *pgResultDescParam = PQgetResult(pConn->pgConn);

                if(pgResultDescParam == NULL)
                {
                    // 'Z' must be followed to 't' during above PQgetResult
                    // So read from resultForDescParam

                    pgResultDescParam = pqgetResultForDescribeParam(pConn->pgConn);
                }

                PQclear(pgResultDescParam);
                pgResultDescParam = NULL;

                if(pqRc == PGRES_TUPLES_OK)
                {
                    // SELECT kind of operation returning rows description

                    pgResult = PQgetResult(pConn->pgConn);
                    PQclear(pgResult);
                    pgResult = NULL;
                } // SELECT

            } // Success

            if (pqRc == PGRES_COPY_IN ||
                pqRc == PGRES_COPY_OUT ||
                pqRc == PGRES_COPY_BOTH ||
                (pConn && pConn->pgConn && PQstatus(pConn->pgConn) == CONNECTION_BAD)
                )
            {
                // No need to loop any more.
                break;
            }

            // Loop for next result
            if(asyncEnable)
            {
                // If command not send, no need to check for next result.
                if(!sendStatus)
                    break;
            }

            PQclear(pgResult);
            pgResult = NULL;

            // Get next result description
            pgResult = PQgetResult(pConn->pgConn);
            if(!pgResult)
            {
                // 'Z' must be followed to 'T' during above PQgetResult
                // So read from resultForDescRowPrep and release it.
                PGresult *pgResultDescRowPrep = pqgetResultForDescribeRowPrep(pConn->pgConn);

                PQclear(pgResultDescRowPrep);
                pgResultDescRowPrep = NULL;

                break;
            }

            // Get result status
            pqRc = PQresultStatus(pgResult);

        }while(TRUE); // Results  loop
    }
    else
    {
        rc = SQL_ERROR;
        addError(&pStmt->pErrorList,"HY000", "Invalid command buffer", 0, NULL);
        goto error;
    }

error:

    return rc;
}