zend_long pdo_sqlsrv_dbh_do()

in source/pdo_sqlsrv/pdo_dbh.cpp [886:968]


zend_long pdo_sqlsrv_dbh_do( _Inout_ pdo_dbh_t *dbh, _In_reads_bytes_(sql_len) const char *sql, _In_ size_t sql_len )
#else
zend_long pdo_sqlsrv_dbh_do(_Inout_ pdo_dbh_t *dbh, _In_ const zend_string *sql)
#endif
{
    PDO_RESET_DBH_ERROR;
    PDO_VALIDATE_CONN;
    PDO_LOG_DBH_ENTRY;

    pdo_sqlsrv_dbh* driver_dbh = static_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );

    sqlsrv_malloc_auto_ptr<sqlsrv_stmt> driver_stmt;
    SQLLEN rows = 0;

    // verify that the data type sizes are the same.  If we ever upgrade to 64 bit we don't want the wrong
    // thing to happen here.
    SQLSRV_STATIC_ASSERT( sizeof( rows ) == sizeof( SQLLEN ));

    try {
 
        SQLSRV_ASSERT( sql != NULL, "NULL or empty SQL string passed." );
        SQLSRV_ASSERT( driver_dbh != NULL, "pdo_sqlsrv_dbh_do: driver_data object was NULL.");

        // temp PDO statement used for error handling if something happens
        pdo_stmt_t temp_stmt;
        temp_stmt.dbh = dbh;
        // allocate a full driver statement to take advantage of the error handling
        driver_stmt = core_sqlsrv_create_stmt( driver_dbh, core::allocate_stmt<pdo_sqlsrv_stmt>, NULL /*options_ht*/, 
                          NULL /*valid_stmt_opts*/, pdo_sqlsrv_handle_stmt_error, &temp_stmt );
        driver_stmt->set_func( __FUNCTION__ );

#if PHP_VERSION_ID < 80100
        SQLRETURN execReturn = core_sqlsrv_execute(driver_stmt, sql, static_cast<int>(sql_len));
#else
        SQLRETURN execReturn = core_sqlsrv_execute(driver_stmt, ZSTR_VAL(sql), ZSTR_LEN(sql));
#endif
        // since the user can give us a compound statement, we return the row count for the last set, and since the row count
        // isn't guaranteed to be valid until all the results have been fetched, we fetch them all first.

        if ( execReturn != SQL_NO_DATA && core_sqlsrv_has_any_result( driver_stmt )) {

            SQLRETURN r = SQL_SUCCESS;

            do {

                rows = core::SQLRowCount( driver_stmt );

                r = core::SQLMoreResults( driver_stmt );

            } while ( r != SQL_NO_DATA );
        }

        // returning -1 forces PDO to return false, which signals an error occurred.  SQLRowCount returns -1 for a number of cases
        // naturally, so we override that here with no rows returned.
        if( rows == -1 ) {
            rows = 0;
        }
    }
    catch( core::CoreException& ) {

        // copy any errors on the statement to the connection so that the user sees them, since the statement is released
        // before this method returns
        strcpy_s( dbh->error_code, sizeof( dbh->error_code ),
                  reinterpret_cast<const char*>( driver_stmt->last_error()->sqlstate ));
        driver_dbh->set_last_error( driver_stmt->last_error() );
        
        if( driver_stmt ) {
            driver_stmt->~sqlsrv_stmt();
        }
        
        return -1;
    }
    catch( ... ) {

        DIE( "pdo_sqlsrv_dbh_do: Unknown exception caught." );
    }

    if( driver_stmt ) {
        driver_stmt->~sqlsrv_stmt();
    }

    return rows;
}