diff --git a/source/pdo_sqlsrv/pdo_stmt.cpp b/source/pdo_sqlsrv/pdo_stmt.cpp index 33932d7e..906f73fd 100644 --- a/source/pdo_sqlsrv/pdo_stmt.cpp +++ b/source/pdo_sqlsrv/pdo_stmt.cpp @@ -593,12 +593,27 @@ int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt TSRMLS_DC ) if ( execReturn == SQL_NO_DATA ) { stmt->column_count = 0; stmt->row_count = 0; + driver_stmt->column_count = 0; + driver_stmt->row_count = 0; + driver_stmt->columns_rows_obtained = true; } else { + if (driver_stmt->columns_rows_obtained == false) + { stmt->column_count = core::SQLNumResultCols( driver_stmt TSRMLS_CC ); // return the row count regardless if there are any rows or not stmt->row_count = core::SQLRowCount( driver_stmt TSRMLS_CC ); + + driver_stmt->column_count = stmt->column_count; + driver_stmt->row_count = stmt->row_count; + driver_stmt->columns_rows_obtained = true; + } + else + { + stmt->column_count = driver_stmt->column_count; + stmt->row_count = driver_stmt->row_count; + } } // workaround for a bug in the PDO driver manager. It is fairly simple to crash the PDO driver manager with @@ -1146,6 +1161,10 @@ int pdo_sqlsrv_stmt_next_rowset( _Inout_ pdo_stmt_t *stmt TSRMLS_DC ) // return the row count regardless if there are any rows or not stmt->row_count = core::SQLRowCount( driver_stmt TSRMLS_CC ); + + driver_stmt->column_count = stmt->column_count; + driver_stmt->row_count = stmt->row_count; + driver_stmt->columns_rows_obtained = true; } catch( core::CoreException& ) { diff --git a/source/shared/core_sqlsrv.h b/source/shared/core_sqlsrv.h index d4ffdda5..2102636f 100644 --- a/source/shared/core_sqlsrv.h +++ b/source/shared/core_sqlsrv.h @@ -1438,8 +1438,10 @@ struct sqlsrv_stmt : public sqlsrv_context { bool has_rows; // Has_rows is set if there are actual rows in the row set bool fetch_called; // Used by core_sqlsrv_get_field to return an informative error if fetch not yet called int last_field_index; // last field retrieved by core_sqlsrv_get_field - bool past_next_result_end; // core_sqlsrv_next_result sets this to true when the statement goes beyond the - // last results + bool past_next_result_end; // core_sqlsrv_next_result sets this to true when the statement goes beyond the last results + bool columns_rows_obtained; // Whether or not SQLNumResultCols and SQLRowCount have been called for the active result set + int column_count; // Number of columns in the current result set obtained from SQLNumResultCols + int row_count; // Number of rows in the current result set obtained from SQLRowCount unsigned long query_timeout; // maximum allowed statement execution time zend_long buffered_query_limit; // maximum allowed memory for a buffered query (measured in KB) bool date_as_string; // false by default but the user can set this to true to retrieve datetime values as strings diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index 9cac96a5..352d2ff0 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -140,6 +140,9 @@ sqlsrv_stmt::sqlsrv_stmt( _In_ sqlsrv_conn* c, _In_ SQLHANDLE handle, _In_ error fetch_called( false ), last_field_index( -1 ), past_next_result_end( false ), + columns_rows_obtained( false ), + column_count( 0 ), + row_count( 0 ), query_timeout( QUERY_TIMEOUT_INVALID ), date_as_string(false), format_decimals(false), // no formatting needed @@ -225,6 +228,9 @@ void sqlsrv_stmt::new_result_set( TSRMLS_D ) this->past_next_result_end = false; this->past_fetch_end = false; this->last_field_index = -1; + this->columns_rows_obtained = false; + this->column_count = 0; + this->row_count = 0; // delete any current results if( current_results ) { @@ -821,7 +827,13 @@ bool core_sqlsrv_fetch( _Inout_ sqlsrv_stmt* stmt, _In_ SQLSMALLINT fetch_orient } // First time only if ( !stmt->fetch_called ) { - SQLSMALLINT has_fields = core::SQLNumResultCols( stmt TSRMLS_CC ); + SQLSMALLINT has_fields; + if (stmt->columns_rows_obtained) { + has_fields = stmt->column_count; + } else { + has_fields = core::SQLNumResultCols( stmt TSRMLS_CC ); + } + CHECK_CUSTOM_ERROR( has_fields == 0, stmt, SQLSRV_ERROR_NO_FIELDS ) { throw core::CoreException(); } @@ -1066,10 +1078,23 @@ void core_sqlsrv_get_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i bool core_sqlsrv_has_any_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC ) { - // Use SQLNumResultCols to determine if we have rows or not. - SQLSMALLINT num_cols = core::SQLNumResultCols( stmt TSRMLS_CC ); - // use SQLRowCount to determine if there is a rows status waiting - SQLLEN rows_affected = core::SQLRowCount( stmt TSRMLS_CC ); + SQLSMALLINT num_cols, rows_affected; + if (stmt->columns_rows_obtained) + { + num_cols = stmt->column_count; + rows_affected = stmt->row_count; + } + else + { + // Use SQLNumResultCols to determine if we have rows or not + num_cols = core::SQLNumResultCols( stmt TSRMLS_CC ); + stmt->column_count = num_cols; + // Use SQLRowCount to determine if there is a rows status waiting + rows_affected = core::SQLRowCount( stmt TSRMLS_CC ); + stmt->row_count = rows_affected; + stmt->columns_rows_obtained = true; + } + return (num_cols != 0) || (rows_affected > 0); } diff --git a/source/sqlsrv/stmt.cpp b/source/sqlsrv/stmt.cpp index 9d60de25..bdd1d2f8 100644 --- a/source/sqlsrv/stmt.cpp +++ b/source/sqlsrv/stmt.cpp @@ -1791,7 +1791,11 @@ SQLSMALLINT get_resultset_meta_data(_Inout_ sqlsrv_stmt * stmt) if (num_cols == 0) { getMetaData = true; + if (stmt->columns_rows_obtained == false) { num_cols = core::SQLNumResultCols(stmt TSRMLS_CC); + } else { + num_cols = stmt->column_count; + } } try {