From 7256685a4c817563639371083e7028aaa5b0207e Mon Sep 17 00:00:00 2001 From: v-kaywon Date: Mon, 27 Mar 2017 17:49:01 -0700 Subject: [PATCH] workaround for unixODBC bug returning error when pdo::exec query with empty result set --- source/shared/core_sqlsrv.h | 11 ++++ ...o_336_pho_exec_empty_result_set_error.phpt | 53 +++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 test/pdo_sqlsrv/pdo_336_pho_exec_empty_result_set_error.phpt diff --git a/source/shared/core_sqlsrv.h b/source/shared/core_sqlsrv.h index 55c0678b..7a46ca70 100644 --- a/source/shared/core_sqlsrv.h +++ b/source/shared/core_sqlsrv.h @@ -2040,6 +2040,17 @@ namespace core { SQLRETURN r; SQLSMALLINT num_cols; r = ::SQLNumResultCols( stmt->handle(), &num_cols ); + + // Workaround for a bug in unixODBC: after SQLExecDirect for an empty result set, + // r = ::SQLNumResultCols( stmt->handle(), &num_cols ); + // returns r=-1 (SQL_ERROR) and error HY010 (Function sequence error) + // but it should have succeeded with r=0 (SQL_SUCCESS) and no error + // instead of throwing an exception, return 0 if the r=-1, stament has been executed, and has a HY010 error + // (HY010 error should not return if stmt->execute is true) +#ifndef _WIN32 + if ( r == -1 && stmt->execute && strcmp( reinterpret_cast( stmt->last_error()->sqlstate ), "HY010" ) == 0 ) + return 0; +#endif // !_WIN32 CHECK_SQL_ERROR_OR_WARNING( r, stmt ) { throw CoreException(); diff --git a/test/pdo_sqlsrv/pdo_336_pho_exec_empty_result_set_error.phpt b/test/pdo_sqlsrv/pdo_336_pho_exec_empty_result_set_error.phpt new file mode 100644 index 00000000..f9b2017d --- /dev/null +++ b/test/pdo_sqlsrv/pdo_336_pho_exec_empty_result_set_error.phpt @@ -0,0 +1,53 @@ +--TEST-- +GitHub issue #336 - PDO::exec should not return an error with query returning SQL_NO_DATA +--DESCRIPTION-- +Verifies GitHub issue 336 is fixed, PDO::exec on query returning SQL_NO_DATA will not give an error +--SKIPIF-- +--FILE-- +setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); + +$sql = "DELETE FROM foo_table WHERE id = 42"; +$sqlWithParameter = "DELETE FROM foo_table WHERE id = :id"; +$sqlParameter = 42; + +$Statement = $conn->exec("IF OBJECT_ID('foo_table', 'U') IS NOT NULL DROP TABLE foo_table"); +$Statement = $conn->exec("CREATE TABLE foo_table (id BIGINT PRIMARY KEY NOT NULL IDENTITY, intField INT NOT NULL)"); +$Statement = $conn->exec("INSERT INTO foo_table (intField) VALUES(3)"); + +//test prepare, not args +$stmt = $conn->prepare($sql); +$stmt->execute(); +if ($conn->errorCode() == 00000) + echo "prepare OK\n"; + +//test prepare, with args +$stmt = $conn->prepare($sqlWithParameter); +$stmt->execute(array(':id' => $sqlParameter)); +if ($conn->errorCode() == 00000) + echo "prepare with args OK\n"; + +//test direct exec +$stmt = $conn->exec($sql); +if ($conn->errorCode() == 00000) + echo "direct exec OK\n"; + +$Statement = $conn->exec("IF OBJECT_ID('foo_table', 'U') IS NOT NULL DROP TABLE foo_table"); + +$stmt = NULL; +$Statement = NULL; +$conn = NULL; + +?> +--EXPECT-- +prepare OK +prepare with args OK +direct exec OK \ No newline at end of file