diff --git a/source/pdo_sqlsrv/pdo_stmt.cpp b/source/pdo_sqlsrv/pdo_stmt.cpp index 78828a02..7fac6259 100644 --- a/source/pdo_sqlsrv/pdo_stmt.cpp +++ b/source/pdo_sqlsrv/pdo_stmt.cpp @@ -1067,6 +1067,30 @@ int pdo_sqlsrv_stmt_next_rowset( _Inout_ pdo_stmt_t *stmt TSRMLS_DC ) SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_next_rowset: driver_data object was null" ); + // + CHECK_CUSTOM_ERROR( stmt->past_next_result_end, stmt, SQLSRV_ERROR_NEXT_RESULT_PAST_END ) { + throw core::CoreException(); + } + + // Make sure that we haven't gone past the end of the result set, then make sure that + // the result set is not null. Null means SQLNumResultCols returns 0 and SQLRowCount + // is not > 0. Normally the latter error is handled in core_sqlsrv_fetch(), but if the + // user calls nextRowset() before fetch() the error is never shown so we handle it here. + // In that case, however, core_sqlsrv_has_any_result would return false if we are at + // the end of a non-null result set, so we check for that error first to make sure the + // user gets the correct error message. + CHECK_CUSTOM_ERROR( stmt->past_next_result_end, driver_stmt, SQLSRV_ERROR_NEXT_RESULT_PAST_END ) { + throw core::CoreException(); + } + + bool has_result = core_sqlsrv_has_any_result( driver_stmt ); + + if(!driver_stmt->fetch_called){ + CHECK_CUSTOM_ERROR( !has_result, driver_stmt, SQLSRV_ERROR_NO_FIELDS ) { + throw core::CoreException(); + } + } + core_sqlsrv_next_result( static_cast( stmt->driver_data ) TSRMLS_CC ); // clear the current meta data since the new result will generate new meta data diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index fdfcf809..29255029 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -1058,18 +1058,6 @@ void core_sqlsrv_next_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC, _In_ bool fin throw core::CoreException(); } - // Make sure that the result set is not null. Null means SQLNumResultCols returns 0 - // and SQLRowCount is not > 0. Normally this error is handled in core_sqlsrv_fetch(), - // but if the user calls nextRowset() before fetch() the error is never shown - // so we handle it here. - bool has_result = core_sqlsrv_has_any_result( stmt ); - - if(!stmt->fetch_called){ - CHECK_CUSTOM_ERROR( !has_result, stmt, SQLSRV_ERROR_NO_FIELDS ) { - throw core::CoreException(); - } - } - close_active_stream( stmt TSRMLS_CC ); //Clear column sql types and sql display sizes. diff --git a/source/sqlsrv/stmt.cpp b/source/sqlsrv/stmt.cpp index a548bfc6..4404bf41 100644 --- a/source/sqlsrv/stmt.cpp +++ b/source/sqlsrv/stmt.cpp @@ -561,6 +561,25 @@ PHP_FUNCTION( sqlsrv_next_result ) try { + // Make sure that we haven't gone past the end of the result set, then make sure that + // the result set is not null. Null means SQLNumResultCols returns 0 and SQLRowCount + // is not > 0. Normally the latter error is handled in core_sqlsrv_fetch(), but if the + // user calls sqlsrv_next_result() before fetch() the error is never shown so we handle it here. + // In that case, however, core_sqlsrv_has_any_result would return false if we are at + // the end of a non-null result set, so we check for that error first to make sure the + // user gets the correct error message. + CHECK_CUSTOM_ERROR( stmt->past_next_result_end, stmt, SQLSRV_ERROR_NEXT_RESULT_PAST_END ) { + throw core::CoreException(); + } + + bool has_result = core_sqlsrv_has_any_result( driver_stmt ); + + if(!driver_stmt->fetch_called){ + CHECK_CUSTOM_ERROR( !has_result, driver_stmt, SQLSRV_ERROR_NO_FIELDS ) { + throw core::CoreException(); + } + } + core_sqlsrv_next_result( stmt TSRMLS_CC, true ); if( stmt->past_next_result_end ) {