Set logger for driver API (#1107)

This commit is contained in:
Jenny Tam 2020-03-25 09:53:18 -07:00 committed by GitHub
parent fb335c0b0d
commit 7214e8d553
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 434 additions and 123 deletions

View file

@ -105,7 +105,7 @@ jobs:
docker pull mcr.microsoft.com/mssql/server:2017-latest
docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=$(pwd)' -p 1433:1433 -h $(host) --name=$(host) -d mcr.microsoft.com/mssql/server:2017-latest
docker ps -a
sleep 5
sleep 10
docker exec -t $(host) /opt/mssql-tools/bin/sqlcmd -S $(server) -U $(uid) -P $(pwd) -Q 'select @@Version'
displayName: 'Run SQL Server for Linux'

View file

@ -489,26 +489,13 @@ struct pdo_dbh_methods pdo_sqlsrv_dbh_methods = {
// log a function entry point
#ifndef _WIN32
#define PDO_LOG_DBH_ENTRY \
{ \
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( dbh->driver_data ); \
driver_dbh->set_func( __FUNCTION__ ); \
int length = strlen( __FUNCTION__ ) + strlen( ": entering" ); \
char func[length+1]; \
memset(func, '\0', length+1); \
strcpy_s( func, sizeof( __FUNCTION__ ), __FUNCTION__ ); \
strcat_s( func, length+1, ": entering" ); \
LOG( SEV_NOTICE, func ); \
if (driver_dbh != NULL) driver_dbh->set_func(__FUNCTION__); \
core_sqlsrv_register_severity_checker(pdo_severity_check); \
LOG(SEV_NOTICE, "%1!s!: entering", __FUNCTION__); \
}
#else
#define PDO_LOG_DBH_ENTRY \
{ \
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( dbh->driver_data ); \
driver_dbh->set_func( __FUNCTION__ ); \
LOG( SEV_NOTICE, __FUNCTION__ ## ": entering" ); \
}
#endif
// constructor for the internal object for connections
pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( _In_ SQLHANDLE h, _In_ error_callback e, _In_ void* driver TSRMLS_DC ) :
@ -547,7 +534,7 @@ pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( _In_ SQLHANDLE h, _In_ error_callback e, _In_ vo
// 0 for failure, 1 for success.
int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_options TSRMLS_DC)
{
LOG( SEV_NOTICE, "pdo_sqlsrv_db_handle_factory: entering" );
PDO_LOG_DBH_ENTRY;
hash_auto_ptr pdo_conn_options_ht;
pdo_error_mode prev_err_mode = dbh->error_mode;

View file

@ -128,11 +128,11 @@ PHP_MINIT_FUNCTION(pdo_sqlsrv)
ZEND_TSRMLS_CACHE_UPDATE();
#endif
core_sqlsrv_register_logger( pdo_sqlsrv_log );
core_sqlsrv_register_severity_checker(pdo_severity_check);
REGISTER_INI_ENTRIES();
LOG( SEV_NOTICE, "pdo_sqlsrv: entering minit" );
PDO_LOG_NOTICE("pdo_sqlsrv: entering minit");
// initialize list of pdo errors
g_pdo_errors_ht = reinterpret_cast<HashTable*>( pemalloc( sizeof( HashTable ), 1 ));
@ -200,7 +200,7 @@ PHP_MSHUTDOWN_FUNCTION(pdo_sqlsrv)
}
catch( ... ) {
LOG( SEV_NOTICE, "Unknown exception caught in PHP_MSHUTDOWN_FUNCTION(pdo_sqlsrv)" );
PDO_LOG_NOTICE("Unknown exception caught in PHP_MSHUTDOWN_FUNCTION(pdo_sqlsrv)");
return FAILURE;
}
@ -225,18 +225,18 @@ PHP_RINIT_FUNCTION(pdo_sqlsrv)
int set_locale = PDO_SQLSRV_G(set_locale_info);
if (set_locale == 2) {
setlocale(LC_ALL, "");
LOG(SEV_NOTICE, "pdo_sqlsrv: setlocale LC_ALL");
PDO_LOG_NOTICE("pdo_sqlsrv: setlocale LC_ALL");
}
else if (set_locale == 1) {
setlocale(LC_CTYPE, "");
LOG(SEV_NOTICE, "pdo_sqlsrv: setlocale LC_CTYPE");
PDO_LOG_NOTICE("pdo_sqlsrv: setlocale LC_CTYPE");
}
else {
LOG(SEV_NOTICE, "pdo_sqlsrv: setlocale NONE");
PDO_LOG_NOTICE("pdo_sqlsrv: setlocale NONE");
}
#endif
LOG( SEV_NOTICE, "pdo_sqlsrv: entering rinit" );
PDO_LOG_NOTICE("pdo_sqlsrv: entering rinit");
return SUCCESS;
}
@ -250,7 +250,7 @@ PHP_RSHUTDOWN_FUNCTION(pdo_sqlsrv)
SQLSRV_UNUSED( module_number );
SQLSRV_UNUSED( type );
LOG( SEV_NOTICE, "pdo_sqlsrv: entering rshutdown" );
PDO_LOG_NOTICE("pdo_sqlsrv: entering rshutdown");
return SUCCESS;
}

View file

@ -351,26 +351,13 @@ void stmt_option_fetch_datetime:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_op
}
// log a function entry point
#ifndef _WIN32
#define PDO_LOG_STMT_ENTRY \
{ \
pdo_sqlsrv_stmt* driver_stmt = reinterpret_cast<pdo_sqlsrv_stmt*>( stmt->driver_data ); \
driver_stmt->set_func( __FUNCTION__ ); \
int length = strlen( __FUNCTION__ ) + strlen( ": entering" ); \
char func[length+1]; \
memset(func, '\0', length+1); \
strcpy_s( func, sizeof( __FUNCTION__ ), __FUNCTION__ ); \
strcat_s( func, length+1, ": entering" ); \
LOG( SEV_NOTICE, func ); \
if (driver_stmt != NULL) driver_stmt->set_func( __FUNCTION__ ); \
core_sqlsrv_register_severity_checker(pdo_severity_check); \
LOG(SEV_NOTICE, "%1!s!: entering", __FUNCTION__); \
}
#else
#define PDO_LOG_STMT_ENTRY \
{ \
pdo_sqlsrv_stmt* driver_stmt = reinterpret_cast<pdo_sqlsrv_stmt*>( stmt->driver_data ); \
driver_stmt->set_func( __FUNCTION__ ); \
LOG( SEV_NOTICE, __FUNCTION__ ## ": entering" ); \
}
#endif
// PDO SQLSRV statement destructor
pdo_sqlsrv_stmt::~pdo_sqlsrv_stmt( void )

View file

@ -39,13 +39,6 @@ const int MAX_DIGITS = 11; // +-2 billion = 10 digits + 1 for the sign if negati
// the warning message is not the error message alone; it must take WARNING_TEMPLATE above into consideration without the formats
const int WARNING_MIN_LENGTH = static_cast<const int>( strlen( WARNING_TEMPLATE ) - strlen( "%1!s!%2!d!%3!s!" ));
// buffer used to hold a formatted log message prior to actually logging it.
const int LOG_MSG_SIZE = 2048;
char log_msg[LOG_MSG_SIZE] = {'\0'};
// internal error that says that FormatMessage failed
SQLCHAR INTERNAL_FORMAT_ERROR[] = "An internal error occurred. FormatMessage failed writing an error message.";
// Returns a sqlsrv_error for a given error code.
sqlsrv_error_const* get_error_message( _In_opt_ unsigned int sqlsrv_error_code);
@ -623,22 +616,10 @@ void pdo_sqlsrv_retrieve_context_error( _In_ sqlsrv_error const* last_error, _Ou
}
}
// Formats the error message and writes to the php error log.
void pdo_sqlsrv_log( _In_opt_ unsigned int severity TSRMLS_DC, _In_opt_ const char* msg, _In_opt_ va_list* print_args )
// check the global variable of pdo_sqlsrv severity whether the message qualifies to be logged with the LOG macro
bool pdo_severity_check(_In_ unsigned int severity TSRMLS_DC)
{
if( (severity & PDO_SQLSRV_G( log_severity )) == 0 ) {
return;
}
DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, msg, 0, 0, log_msg, LOG_MSG_SIZE, print_args );
// if an error occurs for FormatMessage, we just output an internal error occurred.
if( rc == 0 ) {
SQLSRV_STATIC_ASSERT( sizeof( INTERNAL_FORMAT_ERROR ) < sizeof( log_msg ));
std::copy( INTERNAL_FORMAT_ERROR, INTERNAL_FORMAT_ERROR + sizeof( INTERNAL_FORMAT_ERROR ), log_msg );
}
php_log_err( log_msg TSRMLS_CC );
return ((severity & PDO_SQLSRV_G(pdo_log_severity)));
}
namespace {

View file

@ -29,7 +29,7 @@
// request level variables
ZEND_BEGIN_MODULE_GLOBALS(pdo_sqlsrv)
unsigned int log_severity;
unsigned int pdo_log_severity;
zend_long client_buffer_max_size;
#ifndef _WIN32

View file

@ -60,7 +60,7 @@ extern HMODULE g_sqlsrv_hmodule;
#endif
PHP_INI_BEGIN()
STD_PHP_INI_ENTRY( INI_PREFIX INI_PDO_SQLSRV_LOG , "0", PHP_INI_ALL, OnUpdateLong, log_severity,
STD_PHP_INI_ENTRY( INI_PREFIX INI_PDO_SQLSRV_LOG , "0", PHP_INI_ALL, OnUpdateLong, pdo_log_severity,
zend_pdo_sqlsrv_globals, pdo_sqlsrv_globals )
STD_PHP_INI_ENTRY( INI_PREFIX INI_PDO_SQLSRV_CLIENT_BUFFER_MAX_SIZE , INI_BUFFERED_QUERY_LIMIT_DEFAULT, PHP_INI_ALL, OnUpdateLong,
client_buffer_max_size, zend_pdo_sqlsrv_globals, pdo_sqlsrv_globals )
@ -326,6 +326,10 @@ inline void pdo_reset_dbh_error( _Inout_ pdo_dbh_t* dbh TSRMLS_DC )
}
}
#define PDO_LOG_NOTICE(message) \
core_sqlsrv_register_severity_checker(pdo_severity_check); \
LOG(SEV_NOTICE, message);
#define PDO_RESET_DBH_ERROR pdo_reset_dbh_error( dbh TSRMLS_CC );
inline void pdo_reset_stmt_error( _Inout_ pdo_stmt_t* stmt )
@ -417,8 +421,8 @@ namespace pdo {
} // namespace pdo
// logger for pdo_sqlsrv called by the core layer when it wants to log something with the LOG macro
void pdo_sqlsrv_log( _In_opt_ unsigned int severity TSRMLS_DC, _In_opt_ const char* msg, _In_opt_ va_list* print_args );
// check the global variable of pdo_sqlsrv severity whether the message qualifies to be logged with the LOG macro
bool pdo_severity_check(_In_ unsigned int severity TSRMLS_DC);
#endif /* PHP_PDO_SQLSRV_INT_H */

View file

@ -287,14 +287,12 @@ struct sqlsrv_static_assert<true> { _In_ static const int value = 1; };
// Logging
//*********************************************************************************************************************************
// log_callback
// a driver specific callback for logging messages
// a driver specific callback for checking if the messages are qualified to be logged:
// severity - severity of the message: notice, warning, or error
// msg - the message to log in a FormatMessage style formatting
// print_args - args to the message
typedef void (*log_callback)( _In_ unsigned int severity TSRMLS_DC, _In_ const char* msg, _In_opt_ va_list* print_args );
typedef bool (*severity_callback)(_In_ unsigned int severity TSRMLS_DC);
// each driver must register a log callback. This should be the first thing a driver does.
void core_sqlsrv_register_logger( _In_ log_callback );
// each driver must register a severity checker callback for logging to work according to the INI settings
void core_sqlsrv_register_severity_checker(_In_ severity_callback driver_checker);
// a simple wrapper around a PHP error logging function.
void write_to_log( _In_ unsigned int severity TSRMLS_DC, _In_ const char* msg, ... );

View file

@ -23,10 +23,16 @@
namespace {
severity_callback g_driver_severity;
// *** internal constants ***
log_callback g_driver_log;
// buffer used to hold a formatted log message prior to actually logging it.
const int LOG_MSG_SIZE = 2048;
// internal error that says that FormatMessage failed
SQLCHAR INTERNAL_FORMAT_ERROR[] = "An internal error occurred. FormatMessage failed writing an error message.";
// buffer used to hold a formatted log message prior to actually logging it.
char last_err_msg[2048] = {'\0'}; // 2k to hold the error messages
@ -35,6 +41,25 @@ unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encodin
_In_ unsigned int mbcs_len,
_Out_writes_(utf16_len) __transfer( mbcs_in_string ) SQLWCHAR* utf16_out_string,
_In_ unsigned int utf16_len, bool use_strict_conversion = false );
// invoked by write_to_log() when the message severity qualifies to be logged
// msg - the message to log in a FormatMessage style formatting
// print_args - args to the message
void log_activity(_In_opt_ const char* msg, _In_opt_ va_list* print_args)
{
char log_msg[LOG_MSG_SIZE] = { '\0' };
DWORD rc = FormatMessage(FORMAT_MESSAGE_FROM_STRING, msg, 0, 0, log_msg, LOG_MSG_SIZE, print_args);
// if an error occurs for FormatMessage, we just output an internal error occurred.
if (rc == 0) {
SQLSRV_STATIC_ASSERT(sizeof(INTERNAL_FORMAT_ERROR) < sizeof(log_msg));
std::copy(INTERNAL_FORMAT_ERROR, INTERNAL_FORMAT_ERROR + sizeof(INTERNAL_FORMAT_ERROR), log_msg);
}
php_log_err(log_msg TSRMLS_CC);
}
}
// SQLSTATE for all internal errors
@ -47,22 +72,24 @@ SQLCHAR SSPWARN[] = "01SSP";
// the script (sqlsrv_configure).
void write_to_log( _In_ unsigned int severity TSRMLS_DC, _In_ const char* msg, ...)
{
SQLSRV_ASSERT( !(g_driver_log == NULL), "Must register a driver log function." );
SQLSRV_ASSERT( !(g_driver_severity == NULL), "Must register a driver checker function." );
if (!g_driver_severity(severity TSRMLS_CC)) {
return;
}
va_list args;
va_start( args, msg );
g_driver_log( severity TSRMLS_CC, msg, &args );
log_activity(msg, &args);
va_end( args );
}
void core_sqlsrv_register_logger( _In_ log_callback driver_logger )
void core_sqlsrv_register_severity_checker(_In_ severity_callback driver_checker)
{
g_driver_log = driver_logger;
g_driver_severity = driver_checker;
}
// convert a string from utf-16 to the encoding and return the new string in the pointer parameter and new
// length in the len parameter. If no errors occurred during convertion, true is returned and the original
// utf-16 string is released by this function if no errors occurred. Otherwise the parameters are not changed

View file

@ -629,10 +629,9 @@ const connection_option SS_CONN_OPTS[] = {
PHP_FUNCTION ( sqlsrv_connect )
{
LOG_FUNCTION( "sqlsrv_connect" );
SET_FUNCTION_NAME( *g_ss_henv_cp );
SET_FUNCTION_NAME( *g_ss_henv_ncp );
g_ss_henv_cp->set_func(_FN_);
g_ss_henv_ncp->set_func(_FN_);
reset_errors( TSRMLS_C );
@ -785,7 +784,7 @@ PHP_FUNCTION( sqlsrv_close )
// dummy context to pass to the error handler
error_ctx = new (sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
SET_FUNCTION_NAME( *error_ctx );
error_ctx->set_func(_FN_);
if( zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &conn_r) == FAILURE ) {
@ -816,7 +815,7 @@ PHP_FUNCTION( sqlsrv_close )
throw ss::SSException();
}
SET_FUNCTION_NAME( *conn );
conn->set_func(_FN_);
// cause any variables still holding a reference to this to be invalid so they cause
// an error when passed to a sqlsrv function. There's nothing we can do if the
@ -845,13 +844,15 @@ PHP_FUNCTION( sqlsrv_close )
void __cdecl sqlsrv_conn_dtor( _Inout_ zend_resource *rsrc TSRMLS_DC )
{
LOG_FUNCTION( "sqlsrv_conn_dtor" );
// Without sqlsrv_close(), this function is invoked by php during the final clean up stage.
// To prevent memory/resource leaks, no more logging at this point.
//LOG_FUNCTION( "sqlsrv_conn_dtor" );
// get the structure
ss_sqlsrv_conn *conn = static_cast<ss_sqlsrv_conn*>( rsrc->ptr );
SQLSRV_ASSERT( conn != NULL, "sqlsrv_conn_dtor: connection was null");
SET_FUNCTION_NAME( *conn );
conn->set_func(__func__);
// close all statements associated with the connection.
sqlsrv_conn_close_stmts( conn TSRMLS_CC );

View file

@ -271,8 +271,8 @@ PHP_MINIT_FUNCTION(sqlsrv)
{
SQLSRV_UNUSED( type );
core_sqlsrv_register_logger( ss_sqlsrv_log );
core_sqlsrv_register_severity_checker(ss_severity_check);
// our global variables are initialized in the RINIT function
#if defined(ZTS)
if( ts_allocate_id( &sqlsrv_globals_id,

View file

@ -313,15 +313,11 @@ public:
#define LOG_FUNCTION( function_name ) \
const char* _FN_ = function_name; \
SQLSRV_G( current_subsystem ) = current_log_subsystem; \
LOG( SEV_NOTICE, "%1!s!: entering", _FN_ );
core_sqlsrv_register_severity_checker(ss_severity_check); \
LOG(SEV_NOTICE, "%1!s!: entering", _FN_);
#define SET_FUNCTION_NAME( context ) \
{ \
(context).set_func( _FN_ ); \
}
// logger for ss_sqlsrv called by the core layer when it wants to log something with the LOG macro
void ss_sqlsrv_log( _In_ unsigned int severity TSRMLS_DC, _In_opt_ const char* msg, _In_opt_ va_list* print_args );
// check the global variables of sqlsrv severity whether the message qualifies to be logged with the LOG macro
bool ss_severity_check(_In_ unsigned int severity TSRMLS_DC);
// subsystems that may report log messages. These may be used to filter which systems write to the log to prevent noise.
enum logging_subsystems {

View file

@ -1371,7 +1371,6 @@ void __cdecl sqlsrv_stmt_dtor( _Inout_ zend_resource *rsrc TSRMLS_DC )
PHP_FUNCTION( sqlsrv_free_stmt )
{
LOG_FUNCTION( "sqlsrv_free_stmt" );
zval* stmt_r = NULL;
@ -1384,7 +1383,7 @@ PHP_FUNCTION( sqlsrv_free_stmt )
// dummy context to pass to the error handler
error_ctx = new (sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
SET_FUNCTION_NAME( *error_ctx );
error_ctx->set_func(_FN_);
// take only the statement resource
if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "r", &stmt_r ) == FAILURE ) {

View file

@ -30,13 +30,6 @@ namespace {
// current subsytem. defined for the CHECK_SQL_{ERROR|WARNING} macros
unsigned int current_log_subsystem = LOG_UTIL;
// buffer used to hold a formatted log message prior to actually logging it.
const int LOG_MSG_SIZE = 2048;
char log_msg[LOG_MSG_SIZE] = {'\0'};
// internal error that says that FormatMessage failed
SQLCHAR INTERNAL_FORMAT_ERROR[] = "An internal error occurred. FormatMessage failed writing an error message.";
// *** internal functions ***
sqlsrv_error_const* get_error_message( _In_ unsigned int sqlsrv_error_code );
@ -457,21 +450,10 @@ ss_error SS_ERRORS[] = {
{ UINT_MAX, {} }
};
// Formats an error message and finally writes it to the php log.
void ss_sqlsrv_log( _In_ unsigned int severity TSRMLS_DC, _In_opt_ const char* msg, _In_opt_ va_list* print_args )
// check the global variables of sqlsrv severity whether the message qualifies to be logged with the LOG macro
bool ss_severity_check(_In_ unsigned int severity TSRMLS_DC)
{
if(( severity & SQLSRV_G( log_severity )) && ( SQLSRV_G( current_subsystem ) & SQLSRV_G( log_subsystems ))) {
DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, msg, 0, 0, log_msg, LOG_MSG_SIZE, print_args );
// if an error occurs for FormatMessage, we just output an internal error occurred.
if( rc == 0 ) {
SQLSRV_STATIC_ASSERT( sizeof( INTERNAL_FORMAT_ERROR ) < sizeof( log_msg ));
std::copy( INTERNAL_FORMAT_ERROR, INTERNAL_FORMAT_ERROR + sizeof( INTERNAL_FORMAT_ERROR ), log_msg );
}
php_log_err( log_msg TSRMLS_CC );
}
return ((severity & SQLSRV_G(log_severity)) && (SQLSRV_G(current_subsystem) & SQLSRV_G(log_subsystems)));
}
bool ss_error_handler( _Inout_ sqlsrv_context& ctx, _In_ unsigned int sqlsrv_error_code, _In_ bool warning TSRMLS_DC, _In_opt_ va_list* print_args )
@ -598,7 +580,7 @@ PHP_FUNCTION( sqlsrv_configure )
// dummy context to pass onto the error handler
error_ctx = new ( sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
SET_FUNCTION_NAME( *error_ctx );
error_ctx->set_func(_FN_);
int zr = zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "sz", &option, &option_len, &value_z );
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
@ -718,7 +700,7 @@ PHP_FUNCTION( sqlsrv_get_config )
// dummy context to pass onto the error handler
error_ctx = new ( sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
SET_FUNCTION_NAME( *error_ctx );
error_ctx->set_func(_FN_);
int zr = zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "s", &option, &option_len );
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {

View file

@ -0,0 +1,65 @@
--TEST--
Test simple logging with connection, simple query and then close
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
require_once("MsCommon_mid-refactor.inc");
function toConnect()
{
require("MsSetup.inc");
// Basic connection
$dsn = getDSN($server, $databaseName, $driver);
$conn = new PDO($dsn, $uid, $pwd);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $conn;
}
try {
ini_set('log_errors', '1');
$logFilename = 'php_errors.log';
$logFilepath = dirname(__FILE__).'/'.$logFilename;
if (file_exists($logFilepath)) {
unlink($logFilepath);
}
ini_set('error_log', $logFilepath);
ini_set('pdo_sqlsrv.log_severity', '-1');
$conn = toConnect();
$stmt = $conn->query("SELECT @@Version");
// Ignore the fetch results
$stmt->fetchAll();
unset($conn);
if (file_exists($logFilepath)) {
echo file_get_contents($logFilepath);
unlink($logFilepath);
} else {
echo "$logFilepath is missing!\n";
}
echo "Done\n";
} catch (Exception $e) {
var_dump($e);
}
?>
--EXPECTF--
[%s UTC] pdo_sqlsrv_db_handle_factory: entering
[%s UTC] pdo_sqlsrv_db_handle_factory: SQLSTATE = 01000
[%s UTC] pdo_sqlsrv_db_handle_factory: error code = 5701
[%s UTC] pdo_sqlsrv_db_handle_factory: message = %s[SQL Server]Changed database context to '%s'.
[%s UTC] pdo_sqlsrv_dbh_prepare: entering
[%s UTC] pdo_sqlsrv_stmt_execute: entering
[%s UTC] pdo_sqlsrv_stmt_describe_col: entering
[%s UTC] pdo_sqlsrv_stmt_fetch: entering
[%s UTC] pdo_sqlsrv_stmt_get_col_data: entering
[%s UTC] pdo_sqlsrv_stmt_fetch: entering
Done

View file

@ -0,0 +1,116 @@
--TEST--
Test different error modes. The queries will try to do a select on a non-existing table
--DESCRIPTION--
This is similar to pdo_errorMode.phpt but will display the contents of php
error logs based on log severity.
--SKIPIF--
<?php require('skipif_mid-refactor.inc'); ?>
--FILE--
<?php
require_once("MsCommon_mid-refactor.inc");
function toConnect()
{
require("MsSetup.inc");
$dsn = getDSN($server, $databaseName, $driver);
$conn = new PDO($dsn, $uid, $pwd);
return $conn;
}
function testException($conn)
{
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
global $sql;
try {
$q = $conn->query($sql);
} catch (Exception $e) {
// do nothing
}
}
function testWarning($conn)
{
// This forces PHP to log errors rather than displaying errors
// on screen -- only required for PDO::ERRMODE_WARNING
ini_set('display_errors', '0');
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
global $sql;
$q = $conn->query($sql);
}
function runtests($severity)
{
global $conn;
$logFilename = 'php_errors' . $severity . '.log';
$logFilepath = dirname(__FILE__).'/'.$logFilename;
if (file_exists($logFilepath)) {
unlink($logFilepath);
}
ini_set('error_log', $logFilepath);
ini_set('pdo_sqlsrv.log_severity', $severity);
if ($severity === '2' ) {
testWarning($conn);
} else {
testException($conn);
}
if (file_exists($logFilepath)) {
if ($severity == '0') {
echo "$logFilepath should not exist\n";
}
echo file_get_contents($logFilepath);
unlink($logFilepath);
}
// Now reset logging by disabling it
ini_set('pdo_sqlsrv.log_severity', '0');
echo "Done with $severity\n\n";
}
try {
ini_set('log_errors', '1');
ini_set('pdo_sqlsrv.log_severity', '0');
$conn = toConnect();
$sql = "SELECT * FROM temp_table";
runtests('0');
runtests('1');
runtests('2');
runtests('4');
runtests('-1');
} catch (Exception $e) {
var_dump($e);
}
?>
--EXPECTF--
Done with 0
[%s UTC] pdo_sqlsrv_stmt_execute: SQLSTATE = 42S02
[%s UTC] pdo_sqlsrv_stmt_execute: error code = 208
[%s UTC] pdo_sqlsrv_stmt_execute: message = %s[SQL Server]Invalid object name 'temp_table'.
Done with 1
[%s UTC] PHP Warning: PDO::query(): SQLSTATE[42S02]: Base table or view not found: 208 %s[SQL Server]Invalid object name 'temp_table'. in %spdo_errorMode_logs.php on line %d
Done with 2
[%s UTC] pdo_sqlsrv_stmt_dtor: entering
[%s UTC] pdo_sqlsrv_dbh_prepare: entering
[%s UTC] pdo_sqlsrv_stmt_execute: entering
Done with 4
[%s UTC] pdo_sqlsrv_stmt_dtor: entering
[%s UTC] pdo_sqlsrv_dbh_prepare: entering
[%s UTC] pdo_sqlsrv_stmt_execute: entering
[%s UTC] pdo_sqlsrv_stmt_execute: SQLSTATE = 42S02
[%s UTC] pdo_sqlsrv_stmt_execute: error code = 208
[%s UTC] pdo_sqlsrv_stmt_execute: message = %s[SQL Server]Invalid object name 'temp_table'.
Done with -1

View file

@ -0,0 +1,63 @@
--TEST--
Test sqlsrv_commit method with logging
--DESCRIPTION--
Similar to sqlsrv_commit.phpt but also test some basic logging activities
By adding integer values together, we can specify more than one logging option at a time.
SQLSRV_LOG_SYSTEM_CONN (2) Turns on logging of connection activity.
SQLSRV_LOG_SYSTEM_STMT (4) Turns on logging of statement activity.
For example, sqlsrv.LogSubsystems = 6
turns on logging of connection and statement activities
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--FILE--
<?php
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_NOTICE);
sqlsrv_configure('LogSubsystems', 6);
require_once('MsCommon.inc');
$conn = connect();
if (!$conn) {
fatalError("Could not connect");
}
$stmt1 = sqlsrv_query($conn, "IF OBJECT_ID('Products', 'U') IS NOT NULL DROP TABLE Products");
$stmt1 = sqlsrv_query($conn, "CREATE TABLE Products (ProductID int PRIMARY KEY, ProductName nvarchar(40), CategoryID int, UnitPrice money)");
if ($stmt1 === false) {
die(print_r(sqlsrv_errors(), true));
}
sqlsrv_free_stmt($stmt1);
$stmt2 = sqlsrv_query($conn, "INSERT INTO Products (ProductID, ProductName, CategoryID, UnitPrice) VALUES (1, 'TestProduct2', 2, '13.55')");
$stmt3 = sqlsrv_query($conn, "SELECT * FROM Products WHERE CategoryID = 2");
if ($stmt2 && $stmt3) {
sqlsrv_commit($conn);
}
$stmt1 = sqlsrv_query($conn, "DROP TABLE Products");
sqlsrv_free_stmt($stmt1);
sqlsrv_free_stmt($stmt2);
sqlsrv_free_stmt($stmt3);
sqlsrv_close($conn);
?>
--EXPECT--
sqlsrv_connect: entering
sqlsrv_query: entering
sqlsrv_query: entering
sqlsrv_stmt_dtor: entering
sqlsrv_free_stmt: entering
sqlsrv_stmt_dtor: entering
sqlsrv_query: entering
sqlsrv_query: entering
sqlsrv_commit: entering
sqlsrv_query: entering
sqlsrv_free_stmt: entering
sqlsrv_stmt_dtor: entering
sqlsrv_free_stmt: entering
sqlsrv_stmt_dtor: entering
sqlsrv_free_stmt: entering
sqlsrv_stmt_dtor: entering
sqlsrv_close: entering

View file

@ -14,7 +14,7 @@ functions return FALSE for errors.
fatalError("sqlsrv_connect should have returned false.");
}
$conn = sqlsrv_connect("_!@#$", array( "Driver" => "Danica Patrick" ));
$conn = sqlsrv_connect("_!@#$", array( "Driver" => "Wrong Driver" ));
if ($conn !== false) {
fatalError("sqlsrv_connect should have returned false.");
}

View file

@ -0,0 +1,56 @@
--TEST--
Test functions return FALSE for errors with logging
--DESCRIPTION--
Similar to sqlsrv_connect_logs.phpt but this time test logging to a log file
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
require_once('MsSetup.inc');
$logFilename = 'php_errors.log';
$logFilepath = dirname(__FILE__).'/'.$logFilename;
if (file_exists($logFilepath)) {
unlink($logFilepath);
}
ini_set('log_errors', '1');
ini_set('error_log', $logFilepath);
ini_set("sqlsrv.LogSeverity", SQLSRV_LOG_SEVERITY_ALL);
ini_set("sqlsrv.LogSubsystems", SQLSRV_LOG_SYSTEM_ALL);
$conn = sqlsrv_connect($server, array( "Driver" => "Wrong Driver" ));
if ($conn !== false) {
fatalError("sqlsrv_connect should have returned false.");
}
ini_set("sqlsrv.LogSeverity", SQLSRV_LOG_SEVERITY_NOTICE);
$conn = sqlsrv_connect($server, array( "uid" => $uid , "pwd" => $pwd ));
if ($conn === false) {
fatalError("sqlsrv_connect should have connected.");
}
ini_set("sqlsrv.LogSeverity", SQLSRV_LOG_SEVERITY_ERROR);
$stmt = sqlsrv_query($conn, "SELECT * FROM some_bogus_table");
if ($stmt !== false) {
fatalError("sqlsrv_query should have returned false.");
}
ini_set("sqlsrv.LogSeverity", SQLSRV_LOG_SEVERITY_ALL);
if (file_exists($logFilepath)) {
echo file_get_contents($logFilepath);
unlink($logFilepath);
}
sqlsrv_close($conn);
?>
--EXPECTF--
[%s UTC] sqlsrv_connect: entering
[%s UTC] sqlsrv_connect: SQLSTATE = IMSSP
[%s UTC] sqlsrv_connect: error code = -106
[%s UTC] sqlsrv_connect: message = Invalid value Wrong Driver was specified for Driver option.
[%s UTC] sqlsrv_connect: entering
[%s UTC] sqlsrv_query: SQLSTATE = 42S02
[%s UTC] sqlsrv_query: error code = 208
[%s UTC] sqlsrv_query: message = %s[SQL Server]Invalid object name 'some_bogus_table'.

View file

@ -0,0 +1,49 @@
--TEST--
Test functions return FALSE for errors with logging
--DESCRIPTION--
Similar to sqlsrv_connect.phpt but also test different settings of logging activities
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
sqlsrv_configure('WarningsReturnAsErrors', 0);
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_ALL);
sqlsrv_configure('LogSubsystems', SQLSRV_LOG_SYSTEM_ALL);
require_once('MsSetup.inc');
$conn = sqlsrv_connect($server, array( "Driver" => "Wrong Driver" ));
if ($conn !== false) {
fatalError("sqlsrv_connect should have returned false.");
}
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_NOTICE);
$conn = sqlsrv_connect($server, array( "uid" => $uid , "pwd" => $pwd ));
if ($conn === false) {
fatalError("sqlsrv_connect should have connected.");
}
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_ERROR);
$stmt = sqlsrv_query($conn, "SELECT * FROM some_bogus_table");
if ($stmt !== false) {
fatalError("sqlsrv_query should have returned false.");
}
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_WARNING);
sqlsrv_close($conn);
?>
--EXPECTF--
sqlsrv.LogSubsystems = -1
sqlsrv_connect: entering
sqlsrv_connect: SQLSTATE = IMSSP
sqlsrv_connect: error code = -106
sqlsrv_connect: message = Invalid value Wrong Driver was specified for Driver option.
sqlsrv_configure: entering
sqlsrv.LogSeverity = 4
sqlsrv_connect: entering
sqlsrv_configure: entering
sqlsrv_query: SQLSTATE = 42S02
sqlsrv_query: error code = 208
sqlsrv_query: message = %s[SQL Server]Invalid object name 'some_bogus_table'.