SQLRETURN SQL_API RsPrepare::RS_SQLPrepare()

in src/odbc/rsodbc/rsprepare.cpp [458:629]


SQLRETURN  SQL_API RsPrepare::RS_SQLPrepare(SQLHSTMT phstmt,
                                    SQLCHAR* pCmd,
                                    SQLINTEGER cbLen,
                                    int iInternal,
                                    int iSQLPrepareW,
                                    int iReprepareForMultiInsert,
									int iLockRequired)
{
    SQLRETURN rc = SQL_SUCCESS;
    RS_STMT_INFO *pStmt = (RS_STMT_INFO *)phstmt;
    char *pszCmd;
    char *pszMultiInsertCmd = NULL;
    char *pszUserInsertCmd = NULL;
    char *pLastBatchMultiInsertCmd = NULL;
	RS_CONN_INFO *pConn = NULL;
	int iApiLocked = FALSE;

    if(!VALID_HSTMT(phstmt))
    {
        rc = SQL_INVALID_HANDLE;
        goto error;
    }

    // Is thread running?
    if(pStmt->pExecThread)
    {
        int iPrepare = pStmt->pExecThread->iPrepare;

        rc = checkExecutingThread(pStmt);
        if(rc != SQL_STILL_EXECUTING)
        {
            waitAndFreeExecThread(pStmt, FALSE);
            if(iPrepare)
                return rc;
            else
            {
                // Follow through for next prepare.
            }
        }
        else
            return rc;
    }

	pConn = pStmt->phdbc;

	if(iLockRequired && pConn && (pConn->pConnectProps->iStreamingCursorRows > 0))
	{
		iApiLocked = TRUE;
		beginApiMutex(NULL, pConn);
	}

    // Clear error list
    pStmt->pErrorList = clearErrorList(pStmt->pErrorList);

    // Check for COPY command in current execution
    rc = checkForCopyExecution(pStmt);
    if(rc == SQL_ERROR)
        goto error;

    if(pCmd == NULL)
    {
        rc = SQL_ERROR;
        addError(&pStmt->pErrorList,"HY009", "Invalid use of null pointer", 0, NULL);
        goto error; 
    }

    // Save the flag before clean-up
    if(iSQLPrepareW)
    {
        pszUserInsertCmd = pStmt->pszUserInsertCmd;
        pStmt->pszUserInsertCmd = NULL;
    }

	if(libpqDoesAnyOtherStreamingCursorOpen(pStmt, TRUE))
	{
		// Error
        rc = SQL_ERROR;
        addError(&pStmt->pErrorList,"HY000", "Invalid streaming cursor state", 0, NULL);
        goto error; 
	}

    // Release/reset previously executed stmt info
    makeItReadyForNewQueryExecution(pStmt, FALSE, iReprepareForMultiInsert, !iSQLPrepareW);

    // Restore the flag after clean-up
    if(iSQLPrepareW)
    {
        pStmt->pszUserInsertCmd = pszUserInsertCmd;
        pszUserInsertCmd = NULL;
    }

    // Set implicit cursor name
    if(pStmt->szCursorName[0] == '\0')
        snprintf(pStmt->szCursorName,sizeof(pStmt->szCursorName),"%s%p",IMPLICIT_CURSOR_NAME_PREFIX, phstmt);

    if(!iInternal)
    {
        // Release previously allocated buf, if any
        releasePaStrBuf(pStmt->pCmdBuf);
        setParamMarkerCount(pStmt,0);

        // Look for INSERT command with array binding, which can convert into Multi INSERT
        pszMultiInsertCmd = parseForMultiInsertCommand(
            pStmt, (char *)pCmd, cbLen, &pLastBatchMultiInsertCmd);

        if(!pszMultiInsertCmd)
        {
            pszCmd = (char *)checkReplaceParamMarkerAndODBCEscapeClause(pStmt,(char *)pCmd, cbLen, pStmt->pCmdBuf, TRUE);

            // Look for COPY command
            parseForCopyCommand(pStmt, pszCmd, SQL_NTS);

            if(!(pStmt->pCopyCmd))
            {
                // Look for UNLOAD command
                parseForUnloadCommand(pStmt, pszCmd, SQL_NTS);
            }
        }
        else
        {
            pszCmd = (char *)checkReplaceParamMarkerAndODBCEscapeClause(pStmt,(char *)pszMultiInsertCmd, SQL_NTS, pStmt->pCmdBuf, TRUE);
            pszMultiInsertCmd = (char *)rs_free(pszMultiInsertCmd);

            if(pLastBatchMultiInsertCmd)
            {
                rc = createLastBatchMultiInsertCmd(pStmt, pLastBatchMultiInsertCmd);
                pLastBatchMultiInsertCmd = NULL;
                if(rc == SQL_ERROR)
                    goto error;

            }
        }
    }
    else
    {
        pszCmd = pStmt->pCmdBuf->pBuf;

        // Is it called from SQLPrepareW?
        if(iSQLPrepareW)
        {
            if(!(pStmt->iMultiInsert))
            {
                // Look for COPY command
                parseForCopyCommand(pStmt, pszCmd, SQL_NTS);

                if(!(pStmt->pCopyCmd))
                {
                    // Look for UNLOAD command
                    parseForUnloadCommand(pStmt, pszCmd, SQL_NTS);
                }
            }
        }
    }

    rc = libpqPrepare(pStmt, pszCmd);

    if(rc == SQL_ERROR)
        goto error;

    pStmt->iStatus = RS_PREPARE_STMT;

error:

    pszMultiInsertCmd = (char *)rs_free(pszMultiInsertCmd);

	if(pConn && (pConn->pConnectProps->iStreamingCursorRows > 0) && iApiLocked)
	{
		endApiMutex(NULL, pConn);
	}

    return rc;
}