Merged Linux and Windows PDO_SQLSRV code
This commit is contained in:
parent
dcc4ff2d11
commit
aaa3203e55
|
@ -19,13 +19,9 @@
|
||||||
|
|
||||||
#include "php_pdo_sqlsrv.h"
|
#include "php_pdo_sqlsrv.h"
|
||||||
|
|
||||||
#include <psapi.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <winver.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
typedef const zend_function_entry pdo_sqlsrv_function_entry;
|
typedef const zend_function_entry pdo_sqlsrv_function_entry;
|
||||||
|
|
||||||
// *** internal variables and constants ***
|
// *** internal variables and constants ***
|
||||||
|
@ -355,12 +351,25 @@ struct pdo_dbh_methods pdo_sqlsrv_dbh_methods = {
|
||||||
|
|
||||||
|
|
||||||
// log a function entry point
|
// log a function entry point
|
||||||
|
#ifdef __linux__
|
||||||
|
#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]; \
|
||||||
|
strcpy_s( func, sizeof( __FUNCTION__ ), __FUNCTION__ ); \
|
||||||
|
strcat_s( func, length+1, ": entering" ); \
|
||||||
|
LOG( SEV_NOTICE, func ); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
#define PDO_LOG_DBH_ENTRY \
|
#define PDO_LOG_DBH_ENTRY \
|
||||||
{ \
|
{ \
|
||||||
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( dbh->driver_data ); \
|
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( dbh->driver_data ); \
|
||||||
driver_dbh->set_func( __FUNCTION__ ); \
|
driver_dbh->set_func( __FUNCTION__ ); \
|
||||||
LOG( SEV_NOTICE, __FUNCTION__ ## ": entering" ); \
|
LOG( SEV_NOTICE, __FUNCTION__ ## ": entering" ); \
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// constructor for the internal object for connections
|
// constructor for the internal object for connections
|
||||||
pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC ) :
|
pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( SQLHANDLE h, error_callback e, void* driver TSRMLS_DC ) :
|
||||||
|
@ -465,11 +474,13 @@ int pdo_sqlsrv_db_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC)
|
||||||
|
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
|
||||||
if ( Z_TYPE( server_z ) == IS_STRING ) {
|
if ( Z_TYPE( server_z ) == IS_STRING ) {
|
||||||
zend_string_release( Z_STR( server_z ));
|
zend_string_release( Z_STR( server_z ));
|
||||||
}
|
}
|
||||||
dbh->error_mode = prev_err_mode; // reset the error mode
|
dbh->error_mode = prev_err_mode; // reset the error mode
|
||||||
g_henv_cp->last_error().reset(); // reset the last error; callee will check if last_error exist before freeing it and setting it to NULL
|
g_henv_cp->last_error().reset(); // reset the last error; callee will check if last_error exist before freeing it and setting it to NULL
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch( ... ) {
|
catch( ... ) {
|
||||||
|
@ -574,12 +585,13 @@ int pdo_sqlsrv_dbh_prepare( pdo_dbh_t *dbh, const char *sql,
|
||||||
|
|
||||||
// rewrite the query to map named parameters to positional parameters. We do this rather than use the ODBC named
|
// rewrite the query to map named parameters to positional parameters. We do this rather than use the ODBC named
|
||||||
// parameters for consistency with the PDO MySQL and PDO ODBC drivers.
|
// parameters for consistency with the PDO MySQL and PDO ODBC drivers.
|
||||||
int zr = pdo_subst_named_params( stmt, const_cast<char*>( sql ), sql_len, &sql_rewrite, &sql_rewrite_len TSRMLS_CC );
|
int zr = pdo_parse_params( stmt, const_cast<char*>( sql ), sql_len, &sql_rewrite, &sql_rewrite_len TSRMLS_CC );
|
||||||
CHECK_ZEND_ERROR( zr, driver_dbh, PDO_SQLSRV_ERROR_PARAM_PARSE ) {
|
|
||||||
|
CHECK_ZEND_ERROR( zr, driver_dbh, PDO_SQLSRV_ERROR_PARAM_PARSE) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
// if parameter substitution happened, use that query instead of the original
|
// if parameter substitution happened, use that query instead of the original
|
||||||
if( sql_rewrite != NULL ) {
|
if( sql_rewrite != 0) {
|
||||||
sql = sql_rewrite;
|
sql = sql_rewrite;
|
||||||
sql_len = sql_rewrite_len;
|
sql_len = sql_rewrite_len;
|
||||||
}
|
}
|
||||||
|
@ -910,9 +922,9 @@ int pdo_sqlsrv_dbh_set_attr( pdo_dbh_t *dbh, zend_long attr, zval *val TSRMLS_DC
|
||||||
driver_dbh->client_buffer_max_size = Z_LVAL_P( val );
|
driver_dbh->client_buffer_max_size = Z_LVAL_P( val );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
|
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
|
||||||
driver_dbh->fetch_numeric = (zend_is_true(val)) ? true : false;
|
driver_dbh->fetch_numeric = (zend_is_true(val)) ? true : false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Not supported
|
// Not supported
|
||||||
case PDO_ATTR_FETCH_TABLE_NAMES:
|
case PDO_ATTR_FETCH_TABLE_NAMES:
|
||||||
|
@ -1026,7 +1038,10 @@ int pdo_sqlsrv_dbh_get_attr( pdo_dbh_t *dbh, zend_long attr, zval *return_value
|
||||||
core_sqlsrv_get_client_info( driver_dbh, return_value TSRMLS_CC );
|
core_sqlsrv_get_client_info( driver_dbh, return_value TSRMLS_CC );
|
||||||
|
|
||||||
//Add the PDO SQLSRV driver's file version
|
//Add the PDO SQLSRV driver's file version
|
||||||
core::sqlsrv_add_assoc_string( *driver_dbh, return_value, "ExtensionVer", VER_FILEVERSION_STR, 1 /*duplicate*/
|
//Declarations below eliminate compiler warnings about string constant to char* conversions
|
||||||
|
const char* extver = "ExtensionVer";
|
||||||
|
std::string filever = VER_FILEVERSION_STR;
|
||||||
|
core::sqlsrv_add_assoc_string( *driver_dbh, return_value, extver, &filever[0], 1 /*duplicate*/
|
||||||
TSRMLS_CC );
|
TSRMLS_CC );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1096,7 +1111,7 @@ int pdo_sqlsrv_dbh_return_error( pdo_dbh_t *dbh, pdo_stmt_t *stmt,
|
||||||
ctx_error = static_cast<sqlsrv_conn*>( dbh->driver_data )->last_error();
|
ctx_error = static_cast<sqlsrv_conn*>( dbh->driver_data )->last_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
pdo_sqlsrv_retrieve_context_error( ctx_error, info );
|
pdo_sqlsrv_retrieve_context_error( ctx_error, info );
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1137,8 +1152,8 @@ char * pdo_sqlsrv_dbh_last_id( pdo_dbh_t *dbh, const char *name, _Out_ size_t* l
|
||||||
char* quoted_table = NULL;
|
char* quoted_table = NULL;
|
||||||
size_t quoted_len = 0;
|
size_t quoted_len = 0;
|
||||||
int quoted = pdo_sqlsrv_dbh_quote( dbh, name, strlen( name ), "ed_table, "ed_len, PDO_PARAM_NULL TSRMLS_CC );
|
int quoted = pdo_sqlsrv_dbh_quote( dbh, name, strlen( name ), "ed_table, "ed_len, PDO_PARAM_NULL TSRMLS_CC );
|
||||||
SQLSRV_ASSERT( quoted, "PDO::lastInsertId failed to quote the table name." );
|
SQLSRV_ASSERT( quoted, "PDO::lastInsertId failed to quote the table name.");
|
||||||
sprintf_s( last_insert_id_query, LAST_INSERT_ID_QUERY_MAX_LEN, TABLE_LAST_INSERT_ID_QUERY, quoted_table );
|
snprintf( last_insert_id_query, LAST_INSERT_ID_QUERY_MAX_LEN, TABLE_LAST_INSERT_ID_QUERY, quoted_table );
|
||||||
sqlsrv_free( quoted_table );
|
sqlsrv_free( quoted_table );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1204,81 +1219,79 @@ char * pdo_sqlsrv_dbh_last_id( pdo_dbh_t *dbh, const char *name, _Out_ size_t* l
|
||||||
int pdo_sqlsrv_dbh_quote( pdo_dbh_t* dbh, const char* unquoted, size_t unquoted_len, char **quoted, size_t* quoted_len,
|
int pdo_sqlsrv_dbh_quote( pdo_dbh_t* dbh, const char* unquoted, size_t unquoted_len, char **quoted, size_t* quoted_len,
|
||||||
enum pdo_param_type /*paramtype*/ TSRMLS_DC )
|
enum pdo_param_type /*paramtype*/ TSRMLS_DC )
|
||||||
{
|
{
|
||||||
PDO_RESET_DBH_ERROR;
|
PDO_RESET_DBH_ERROR;
|
||||||
PDO_VALIDATE_CONN;
|
PDO_VALIDATE_CONN;
|
||||||
PDO_LOG_DBH_ENTRY;
|
PDO_LOG_DBH_ENTRY;
|
||||||
|
|
||||||
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );
|
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( dbh->driver_data );
|
||||||
SQLSRV_ENCODING encoding = driver_dbh->bind_param_encoding;
|
SQLSRV_ENCODING encoding = driver_dbh->bind_param_encoding;
|
||||||
|
|
||||||
if ( encoding == SQLSRV_ENCODING_BINARY ) {
|
if ( encoding == SQLSRV_ENCODING_BINARY ) {
|
||||||
// convert from char* to hex digits using os
|
// convert from char* to hex digits using os
|
||||||
std::basic_ostringstream<char> os;
|
std::basic_ostringstream<char> os;
|
||||||
for ( size_t index = 0; index < unquoted_len && unquoted[index] != '\0'; ++index ) {
|
for ( size_t index = 0; index < unquoted_len && unquoted[ index ] != '\0'; ++index ) {
|
||||||
os << std::hex << ( int )unquoted[index];
|
os << std::hex << ( int )unquoted[ index ];
|
||||||
}
|
}
|
||||||
std::basic_string<char> str_hex = os.str();
|
std::basic_string<char> str_hex = os.str();
|
||||||
// each character is represented by 2 digits of hex
|
// each character is represented by 2 digits of hex
|
||||||
size_t unquoted_str_len = unquoted_len * 2; // length returned should not account for null terminator
|
size_t unquoted_str_len = unquoted_len * 2; // length returned should not account for null terminator
|
||||||
char* unquoted_str = reinterpret_cast<char*>( sqlsrv_malloc( unquoted_str_len, sizeof( char ), 1 )); // include space for null terminator
|
char* unquoted_str = reinterpret_cast<char*>( sqlsrv_malloc( unquoted_str_len, sizeof( char ), 1 )); // include space for null terminator
|
||||||
strcpy_s( unquoted_str, unquoted_str_len + 1 /* include null terminator*/, str_hex.c_str());
|
strcpy_s( unquoted_str, unquoted_str_len + 1 /* include null terminator*/, str_hex.c_str() );
|
||||||
// include length of '0x' in the binary string
|
// include length of '0x' in the binary string
|
||||||
*quoted_len = unquoted_str_len + 2;
|
*quoted_len = unquoted_str_len + 2;
|
||||||
*quoted = reinterpret_cast<char*>( sqlsrv_malloc( *quoted_len, sizeof( char ), 1 ));
|
*quoted = reinterpret_cast<char*>( sqlsrv_malloc( *quoted_len, sizeof( char ), 1 ));
|
||||||
unsigned int out_current = 0;
|
unsigned int out_current = 0;
|
||||||
// insert '0x'
|
// insert '0x'
|
||||||
( *quoted )[out_current++] = '0';
|
( *quoted )[ out_current++ ] = '0';
|
||||||
( *quoted )[out_current++] = 'x';
|
( *quoted )[ out_current++ ] = 'x';
|
||||||
for ( size_t index = 0; index < unquoted_str_len && unquoted_str[index] != '\0'; ++index ) {
|
for ( size_t index = 0; index < unquoted_str_len && unquoted_str[ index ] != '\0'; ++index ) {
|
||||||
( *quoted )[out_current++] = unquoted_str[index];
|
( *quoted )[ out_current++ ] = unquoted_str[ index ];
|
||||||
}
|
}
|
||||||
// null terminator
|
// null terminator
|
||||||
( *quoted )[out_current] = '\0';
|
( *quoted )[ out_current ] = '\0';
|
||||||
sqlsrv_free( unquoted_str );
|
sqlsrv_free( unquoted_str );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// count the number of quotes needed
|
// count the number of quotes needed
|
||||||
unsigned int quotes_needed = 2; // the initial start and end quotes of course
|
unsigned int quotes_needed = 2; // the initial start and end quotes of course
|
||||||
// include the N proceeding the initial quote if encoding is UTF8
|
// include the N proceeding the initial quote if encoding is UTF8
|
||||||
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
|
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
|
||||||
quotes_needed = 3;
|
quotes_needed = 3;
|
||||||
}
|
}
|
||||||
|
for ( size_t index = 0; index < unquoted_len && unquoted[ index ] != '\0'; ++index ) {
|
||||||
|
if ( unquoted[ index ] == '\'' ) {
|
||||||
|
++quotes_needed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( size_t index = 0; index < unquoted_len && unquoted[index] != '\0'; ++index ) {
|
*quoted_len = unquoted_len + quotes_needed; // length returned to the caller should not account for null terminator.
|
||||||
if ( unquoted[index] == '\'' ) {
|
*quoted = reinterpret_cast<char*>( sqlsrv_malloc( *quoted_len, sizeof( char ), 1 )); // include space for null terminator.
|
||||||
++quotes_needed;
|
unsigned int out_current = 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*quoted_len = unquoted_len + quotes_needed; // length returned to the caller should not account for null terminator.
|
// insert N if the encoding is UTF8
|
||||||
*quoted = reinterpret_cast<char*>( sqlsrv_malloc( *quoted_len, sizeof( char ), 1 )); // include space for null terminator.
|
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
|
||||||
unsigned int out_current = 0;
|
( *quoted )[ out_current++ ] = 'N';
|
||||||
|
}
|
||||||
|
// insert initial quote
|
||||||
|
( *quoted )[ out_current++ ] = '\'';
|
||||||
|
|
||||||
// insert N if the encoding is UTF8
|
for ( size_t index = 0; index < unquoted_len && unquoted[ index ] != '\0'; ++index ) {
|
||||||
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
|
if ( unquoted[ index ] == '\'' ) {
|
||||||
( *quoted )[out_current++] = 'N';
|
( *quoted )[ out_current++ ] = '\'';
|
||||||
}
|
( *quoted )[ out_current++ ] = '\'';
|
||||||
// insert initial quote
|
}
|
||||||
( *quoted )[out_current++] = '\'';
|
else {
|
||||||
|
( *quoted )[ out_current++ ] = unquoted[ index ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for ( size_t index = 0; index < unquoted_len && unquoted[index] != '\0'; ++index ) {
|
// trailing quote and null terminator
|
||||||
|
( *quoted )[ out_current++ ] = '\'';
|
||||||
|
( *quoted )[ out_current ] = '\0';
|
||||||
|
|
||||||
if ( unquoted[index] == '\'' ) {
|
return 1;
|
||||||
( *quoted )[out_current++] = '\'';
|
}
|
||||||
( *quoted )[out_current++] = '\'';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
( *quoted )[out_current++] = unquoted[index];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// trailing quote and null terminator
|
|
||||||
( *quoted )[out_current++] = '\'';
|
|
||||||
( *quoted )[out_current] = '\0';
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method is not implemented by this driver.
|
// This method is not implemented by this driver.
|
||||||
|
@ -1337,8 +1350,9 @@ void add_stmt_option_key( sqlsrv_context& ctx, size_t key, HashTable* options_ht
|
||||||
option_key = PDO_STMT_OPTION_EMULATE_PREPARES;
|
option_key = PDO_STMT_OPTION_EMULATE_PREPARES;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
|
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
|
||||||
option_key = PDO_STMT_OPTION_FETCHES_NUMERIC_TYPE;
|
option_key = PDO_STMT_OPTION_FETCHES_NUMERIC_TYPE;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CHECK_CUSTOM_ERROR( true, ctx, PDO_SQLSRV_ERROR_INVALID_STMT_OPTION ) {
|
CHECK_CUSTOM_ERROR( true, ctx, PDO_SQLSRV_ERROR_INVALID_STMT_OPTION ) {
|
||||||
|
@ -1421,35 +1435,35 @@ void pdo_txn_isolation_conn_attr_func::func( connection_option const* /*option*/
|
||||||
|
|
||||||
// READ_COMMITTED
|
// READ_COMMITTED
|
||||||
if(( val_len == ( sizeof( PDOTxnIsolationValues::READ_COMMITTED ) - 1 )
|
if(( val_len == ( sizeof( PDOTxnIsolationValues::READ_COMMITTED ) - 1 )
|
||||||
&& !_stricmp( val, PDOTxnIsolationValues::READ_COMMITTED ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::READ_COMMITTED ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_READ_COMMITTED;
|
out_val = SQL_TXN_READ_COMMITTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// READ_UNCOMMITTED
|
// READ_UNCOMMITTED
|
||||||
else if(( val_len == ( sizeof( PDOTxnIsolationValues::READ_UNCOMMITTED ) - 1 )
|
else if(( val_len == ( sizeof( PDOTxnIsolationValues::READ_UNCOMMITTED ) - 1 )
|
||||||
&& !_stricmp( val, PDOTxnIsolationValues::READ_UNCOMMITTED ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::READ_UNCOMMITTED ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_READ_UNCOMMITTED;
|
out_val = SQL_TXN_READ_UNCOMMITTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// REPEATABLE_READ
|
// REPEATABLE_READ
|
||||||
else if(( val_len == ( sizeof( PDOTxnIsolationValues::REPEATABLE_READ ) - 1 )
|
else if(( val_len == ( sizeof( PDOTxnIsolationValues::REPEATABLE_READ ) - 1 )
|
||||||
&& !_stricmp( val, PDOTxnIsolationValues::REPEATABLE_READ ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::REPEATABLE_READ ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_REPEATABLE_READ;
|
out_val = SQL_TXN_REPEATABLE_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SERIALIZABLE
|
// SERIALIZABLE
|
||||||
else if(( val_len == ( sizeof( PDOTxnIsolationValues::SERIALIZABLE ) - 1 )
|
else if(( val_len == ( sizeof( PDOTxnIsolationValues::SERIALIZABLE ) - 1 )
|
||||||
&& !_stricmp( val, PDOTxnIsolationValues::SERIALIZABLE ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::SERIALIZABLE ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_SERIALIZABLE;
|
out_val = SQL_TXN_SERIALIZABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SNAPSHOT
|
// SNAPSHOT
|
||||||
else if(( val_len == ( sizeof( PDOTxnIsolationValues::SNAPSHOT ) - 1 )
|
else if(( val_len == ( sizeof( PDOTxnIsolationValues::SNAPSHOT ) - 1 )
|
||||||
&& !_stricmp( val, PDOTxnIsolationValues::SNAPSHOT ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::SNAPSHOT ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_SS_SNAPSHOT;
|
out_val = SQL_TXN_SS_SNAPSHOT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "php_pdo_sqlsrv.h"
|
#include "php_pdo_sqlsrv.h"
|
||||||
#include <psapi.h>
|
|
||||||
|
|
||||||
#ifdef ZTS
|
#ifdef ZTS
|
||||||
ZEND_TSRMLS_CACHE_DEFINE();
|
ZEND_TSRMLS_CACHE_DEFINE();
|
||||||
|
@ -46,45 +45,11 @@ pdo_driver_t pdo_sqlsrv_driver = {
|
||||||
pdo_sqlsrv_db_handle_factory
|
pdo_sqlsrv_db_handle_factory
|
||||||
};
|
};
|
||||||
|
|
||||||
const char PDO_DLL_NAME[] = "php_pdo.dll";
|
|
||||||
|
|
||||||
// PHP_DEBUG is always defined as either 0 or 1
|
|
||||||
#if PHP_DEBUG == 1 && !defined(ZTS)
|
|
||||||
|
|
||||||
const char PHP_DLL_NAME[] = "php7_debug.dll";
|
|
||||||
|
|
||||||
#elif PHP_DEBUG == 1 && defined(ZTS)
|
|
||||||
|
|
||||||
const char PHP_DLL_NAME[] = "php7ts_debug.dll";
|
|
||||||
|
|
||||||
#elif PHP_DEBUG == 0 && !defined(ZTS)
|
|
||||||
|
|
||||||
const char PHP_DLL_NAME[] = "php7.dll";
|
|
||||||
|
|
||||||
#elif PHP_DEBUG == 0 && defined(ZTS)
|
|
||||||
|
|
||||||
const char PHP_DLL_NAME[] = "php7ts.dll";
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#error Invalid combination of PHP_DEBUG and ZTS macros
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef PDO_API int (*pdo_register_func)(pdo_driver_t *);
|
|
||||||
|
|
||||||
// function pointers to register and unregister this driver
|
|
||||||
pdo_register_func pdo_register_driver;
|
|
||||||
pdo_register_func pdo_unregister_driver;
|
|
||||||
|
|
||||||
// functions to register SQLSRV constants with the PDO class
|
// functions to register SQLSRV constants with the PDO class
|
||||||
// (It's in all CAPS so it looks like the Zend macros that do similar work)
|
// (It's in all CAPS so it looks like the Zend macros that do similar work)
|
||||||
void REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( char const* name, long value TSRMLS_DC );
|
void REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( char const* name, long value TSRMLS_DC );
|
||||||
void REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( char const* name, char const* value TSRMLS_DC );
|
void REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( char const* name, char const* value TSRMLS_DC );
|
||||||
|
|
||||||
// return the Zend class entry for the PDO dbh (connection) class
|
|
||||||
zend_class_entry* (*pdo_get_dbh_class)( void );
|
|
||||||
|
|
||||||
struct sqlsrv_attr_pdo_constant {
|
struct sqlsrv_attr_pdo_constant {
|
||||||
const char *name;
|
const char *name;
|
||||||
int value;
|
int value;
|
||||||
|
@ -134,11 +99,6 @@ zend_module_entry g_pdo_sqlsrv_module_entry =
|
||||||
STANDARD_MODULE_PROPERTIES_EX
|
STANDARD_MODULE_PROPERTIES_EX
|
||||||
};
|
};
|
||||||
|
|
||||||
// functions dynamically linked from the PDO (or PHP) dll and called by other parts of the driver
|
|
||||||
zend_class_entry* (*pdo_get_exception_class)( void );
|
|
||||||
int (*pdo_subst_named_params)(pdo_stmt_t *stmt, char *inquery, size_t inquery_len,
|
|
||||||
char **outquery, size_t *outquery_len TSRMLS_DC);
|
|
||||||
|
|
||||||
// called by Zend for each parameter in the g_pdo_errors_ht hash table when it is destroyed
|
// called by Zend for each parameter in the g_pdo_errors_ht hash table when it is destroyed
|
||||||
void pdo_error_dtor(zval* elem) {
|
void pdo_error_dtor(zval* elem) {
|
||||||
pdo_error* error_to_ignore = reinterpret_cast<pdo_error*>(Z_PTR_P(elem));
|
pdo_error* error_to_ignore = reinterpret_cast<pdo_error*>(Z_PTR_P(elem));
|
||||||
|
@ -168,62 +128,6 @@ PHP_MINIT_FUNCTION(pdo_sqlsrv)
|
||||||
|
|
||||||
LOG( SEV_NOTICE, "pdo_sqlsrv: entering minit" );
|
LOG( SEV_NOTICE, "pdo_sqlsrv: entering minit" );
|
||||||
|
|
||||||
// PHP extensions may be either external DLLs loaded by PHP or statically compiled into the PHP dll
|
|
||||||
// This becomes an issue when we are dependent on other extensions, e.g. PDO. Normally this is solved
|
|
||||||
// by the build process by linking our extension to the appropriate import library (either php*.dll or php_pdo.dll)
|
|
||||||
// However, this leaves us with a problem that the extension has a dependency on that build type.
|
|
||||||
// Since we don't distribute our extension with PHP directly (yet), it would mean that we would have to have SKUs
|
|
||||||
// for both types of PDO builds, internal and external. Rather than this, we just dynamically link the PDO routines we call
|
|
||||||
// against either the PDO dll if it exists and is loaded, otherwise against the PHP dll directly.
|
|
||||||
|
|
||||||
DWORD needed = 0;
|
|
||||||
HANDLE hprocess = GetCurrentProcess();
|
|
||||||
HMODULE pdo_hmodule;
|
|
||||||
|
|
||||||
pdo_hmodule = GetModuleHandle( PDO_DLL_NAME );
|
|
||||||
if( pdo_hmodule == 0 ) {
|
|
||||||
|
|
||||||
pdo_hmodule = GetModuleHandle( PHP_DLL_NAME );
|
|
||||||
if( pdo_hmodule == NULL ) {
|
|
||||||
LOG( SEV_ERROR, "Failed to get PHP module handle." );
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pdo_register_driver = reinterpret_cast<pdo_register_func>( GetProcAddress( pdo_hmodule, "php_pdo_register_driver" ));
|
|
||||||
if( pdo_register_driver == NULL ) {
|
|
||||||
LOG( SEV_ERROR, "Failed to register driver." );
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdo_unregister_driver = reinterpret_cast<pdo_register_func>( GetProcAddress( pdo_hmodule, "php_pdo_unregister_driver" ));
|
|
||||||
if( pdo_unregister_driver == NULL ) {
|
|
||||||
LOG( SEV_ERROR, "Failed to register driver." );
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdo_get_exception_class = reinterpret_cast<zend_class_entry* (*)(void)>( GetProcAddress( pdo_hmodule,
|
|
||||||
"php_pdo_get_exception" ));
|
|
||||||
if( pdo_get_exception_class == NULL ) {
|
|
||||||
LOG( SEV_ERROR, "Failed to register driver." );
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdo_get_dbh_class = reinterpret_cast<zend_class_entry* (*)(void)>( GetProcAddress( pdo_hmodule, "php_pdo_get_dbh_ce" ));
|
|
||||||
if( pdo_get_dbh_class == NULL ) {
|
|
||||||
LOG( SEV_ERROR, "Failed to register driver." );
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdo_subst_named_params =
|
|
||||||
reinterpret_cast<int (*)(pdo_stmt_t *stmt, char *inquery, size_t inquery_len,
|
|
||||||
char **outquery, size_t *outquery_len TSRMLS_DC)>(
|
|
||||||
GetProcAddress( pdo_hmodule, "pdo_parse_params" ));
|
|
||||||
if( pdo_subst_named_params == NULL ) {
|
|
||||||
LOG( SEV_ERROR, "Failed to register driver." );
|
|
||||||
return FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initialize list of pdo errors
|
// initialize list of pdo errors
|
||||||
g_pdo_errors_ht = reinterpret_cast<HashTable*>( pemalloc( sizeof( HashTable ), 1 ));
|
g_pdo_errors_ht = reinterpret_cast<HashTable*>( pemalloc( sizeof( HashTable ), 1 ));
|
||||||
::zend_hash_init( g_pdo_errors_ht, 50, NULL, pdo_error_dtor /*pDestructor*/, 1 );
|
::zend_hash_init( g_pdo_errors_ht, 50, NULL, pdo_error_dtor /*pDestructor*/, 1 );
|
||||||
|
@ -263,13 +167,11 @@ PHP_MINIT_FUNCTION(pdo_sqlsrv)
|
||||||
return FAILURE;
|
return FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdo_register_driver( &pdo_sqlsrv_driver );
|
php_pdo_register_driver( &pdo_sqlsrv_driver );
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Module shutdown function
|
|
||||||
|
|
||||||
// Module shutdown function
|
// Module shutdown function
|
||||||
// This function is called once per execution of the Zend engine
|
// This function is called once per execution of the Zend engine
|
||||||
|
|
||||||
|
@ -281,7 +183,7 @@ PHP_MSHUTDOWN_FUNCTION(pdo_sqlsrv)
|
||||||
|
|
||||||
UNREGISTER_INI_ENTRIES();
|
UNREGISTER_INI_ENTRIES();
|
||||||
|
|
||||||
pdo_unregister_driver( &pdo_sqlsrv_driver );
|
php_pdo_unregister_driver( &pdo_sqlsrv_driver );
|
||||||
|
|
||||||
// clean up the list of pdo errors
|
// clean up the list of pdo errors
|
||||||
zend_hash_destroy( g_pdo_errors_ht );
|
zend_hash_destroy( g_pdo_errors_ht );
|
||||||
|
@ -352,8 +254,9 @@ namespace {
|
||||||
|
|
||||||
void REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( char const* name, long value TSRMLS_DC )
|
void REGISTER_PDO_SQLSRV_CLASS_CONST_LONG( char const* name, long value TSRMLS_DC )
|
||||||
{
|
{
|
||||||
zend_class_entry* zend_class = pdo_get_dbh_class();
|
zend_class_entry* zend_class = php_pdo_get_dbh_ce();
|
||||||
SQLSRV_ASSERT( zend_class != NULL, "REGISTER_PDO_SQLSRV_CLASS_CONST_LONG: pdo_get_dbh_class failed" );
|
|
||||||
|
SQLSRV_ASSERT( zend_class != NULL, "REGISTER_PDO_SQLSRV_CLASS_CONST_LONG: php_pdo_get_dbh_ce failed");
|
||||||
int zr = zend_declare_class_constant_long( zend_class, const_cast<char*>( name ), strlen( name ), value TSRMLS_CC );
|
int zr = zend_declare_class_constant_long( zend_class, const_cast<char*>( name ), strlen( name ), value TSRMLS_CC );
|
||||||
if( zr == FAILURE ) {
|
if( zr == FAILURE ) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
|
@ -362,8 +265,9 @@ namespace {
|
||||||
|
|
||||||
void REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( char const* name, char const* value TSRMLS_DC )
|
void REGISTER_PDO_SQLSRV_CLASS_CONST_STRING( char const* name, char const* value TSRMLS_DC )
|
||||||
{
|
{
|
||||||
zend_class_entry* zend_class = pdo_get_dbh_class();
|
zend_class_entry* zend_class = php_pdo_get_dbh_ce();
|
||||||
SQLSRV_ASSERT( zend_class != NULL, "REGISTER_PDO_SQLSRV_CLASS_CONST_STRING: pdo_get_dbh_class failed" );
|
|
||||||
|
SQLSRV_ASSERT( zend_class != NULL, "REGISTER_PDO_SQLSRV_CLASS_CONST_STRING: php_pdo_get_dbh_ce failed");
|
||||||
int zr = zend_declare_class_constant_string( zend_class, const_cast<char*>( name ), strlen( name ), const_cast<char*>( value ) TSRMLS_CC );
|
int zr = zend_declare_class_constant_string( zend_class, const_cast<char*>( name ), strlen( name ), const_cast<char*>( value ) TSRMLS_CC );
|
||||||
if( zr == FAILURE ) {
|
if( zr == FAILURE ) {
|
||||||
|
|
||||||
|
@ -372,7 +276,7 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
// array of pdo constants.
|
// array of pdo constants.
|
||||||
sqlsrv_attr_pdo_constant pdo_attr_constants[] = {
|
sqlsrv_attr_pdo_constant pdo_attr_constants[] = {
|
||||||
|
|
||||||
// driver specific attributes
|
// driver specific attributes
|
||||||
{ "SQLSRV_ATTR_ENCODING" , SQLSRV_ATTR_ENCODING },
|
{ "SQLSRV_ATTR_ENCODING" , SQLSRV_ATTR_ENCODING },
|
||||||
|
|
|
@ -29,6 +29,8 @@ conn_string_parser:: conn_string_parser( sqlsrv_context& ctx, const char* dsn, i
|
||||||
this->conn_options_ht = conn_options_ht;
|
this->conn_options_ht = conn_options_ht;
|
||||||
this->pos = -1;
|
this->pos = -1;
|
||||||
this->ctx = &ctx;
|
this->ctx = &ctx;
|
||||||
|
this->current_key = 0;
|
||||||
|
this->current_key_name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move to the next character
|
// Move to the next character
|
||||||
|
@ -131,7 +133,7 @@ void conn_string_parser::validate_key(const char *key, int key_len TSRMLS_DC )
|
||||||
for( int i=0; PDO_CONN_OPTS[ i ].conn_option_key != SQLSRV_CONN_OPTION_INVALID; ++i )
|
for( int i=0; PDO_CONN_OPTS[ i ].conn_option_key != SQLSRV_CONN_OPTION_INVALID; ++i )
|
||||||
{
|
{
|
||||||
// discard the null terminator.
|
// discard the null terminator.
|
||||||
if( new_len == ( PDO_CONN_OPTS[ i ].sqlsrv_len - 1 ) && !_strnicmp( key, PDO_CONN_OPTS[ i ].sqlsrv_name, new_len )) {
|
if( new_len == ( PDO_CONN_OPTS[ i ].sqlsrv_len - 1 ) && !strncasecmp( key, PDO_CONN_OPTS[ i ].sqlsrv_name, new_len )) {
|
||||||
|
|
||||||
this->current_key = PDO_CONN_OPTS[ i ].conn_option_key;
|
this->current_key = PDO_CONN_OPTS[ i ].conn_option_key;
|
||||||
this->current_key_name = PDO_CONN_OPTS[ i ].sqlsrv_name;
|
this->current_key_name = PDO_CONN_OPTS[ i ].sqlsrv_name;
|
||||||
|
@ -143,9 +145,10 @@ void conn_string_parser::validate_key(const char *key, int key_len TSRMLS_DC )
|
||||||
sqlsrv_malloc_auto_ptr<char> key_name;
|
sqlsrv_malloc_auto_ptr<char> key_name;
|
||||||
key_name = static_cast<char*>( sqlsrv_malloc( new_len + 1 ));
|
key_name = static_cast<char*>( sqlsrv_malloc( new_len + 1 ));
|
||||||
memcpy_s( key_name, new_len + 1 ,key, new_len );
|
memcpy_s( key_name, new_len + 1 ,key, new_len );
|
||||||
|
|
||||||
key_name[ new_len ] = '\0';
|
key_name[ new_len ] = '\0';
|
||||||
|
|
||||||
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_KEY, key_name );
|
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_KEY, static_cast<char*>(key_name) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primary function which parses the connection string/DSN.
|
// Primary function which parses the connection string/DSN.
|
||||||
|
|
|
@ -39,9 +39,11 @@ const int SQL_SERVER_IDENT_SIZE_MAX = 128;
|
||||||
|
|
||||||
inline SQLSMALLINT pdo_fetch_ori_to_odbc_fetch_ori (enum pdo_fetch_orientation ori)
|
inline SQLSMALLINT pdo_fetch_ori_to_odbc_fetch_ori (enum pdo_fetch_orientation ori)
|
||||||
{
|
{
|
||||||
SQLSRV_ASSERT( ori >= PDO_FETCH_ORI_NEXT && ori <= PDO_FETCH_ORI_REL, "Fetch orientation out of range." );
|
SQLSRV_ASSERT( ori >= PDO_FETCH_ORI_NEXT && ori <= PDO_FETCH_ORI_REL, "Fetch orientation out of range.");
|
||||||
|
#ifndef __linux__
|
||||||
OACR_WARNING_SUPPRESS( 26001, "Buffer length verified above" );
|
OACR_WARNING_SUPPRESS( 26001, "Buffer length verified above" );
|
||||||
OACR_WARNING_SUPPRESS( 26000, "Buffer length verified above" );
|
OACR_WARNING_SUPPRESS( 26000, "Buffer length verified above" );
|
||||||
|
#endif
|
||||||
return odbc_fetch_orientation[ori];
|
return odbc_fetch_orientation[ori];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,18 +334,31 @@ void stmt_option_emulate_prepares:: operator()( sqlsrv_stmt* stmt, stmt_option c
|
||||||
|
|
||||||
void stmt_option_fetch_numeric:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
|
void stmt_option_fetch_numeric:: operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC )
|
||||||
{
|
{
|
||||||
pdo_sqlsrv_stmt *pdo_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt );
|
pdo_sqlsrv_stmt *pdo_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt );
|
||||||
pdo_stmt->fetch_numeric = ( zend_is_true( value_z )) ? true : false;
|
pdo_stmt->fetch_numeric = ( zend_is_true( value_z )) ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// log a function entry point
|
// log a function entry point
|
||||||
|
#ifdef __linux__
|
||||||
|
#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]; \
|
||||||
|
strcpy_s( func, sizeof( __FUNCTION__ ), __FUNCTION__ ); \
|
||||||
|
strcat_s( func, length+1, ": entering" ); \
|
||||||
|
LOG( SEV_NOTICE, func ); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
#define PDO_LOG_STMT_ENTRY \
|
#define PDO_LOG_STMT_ENTRY \
|
||||||
{ \
|
{ \
|
||||||
pdo_sqlsrv_stmt* driver_stmt = reinterpret_cast<pdo_sqlsrv_stmt*>( stmt->driver_data ); \
|
pdo_sqlsrv_stmt* driver_stmt = reinterpret_cast<pdo_sqlsrv_stmt*>( stmt->driver_data ); \
|
||||||
driver_stmt->set_func( __FUNCTION__ ); \
|
driver_stmt->set_func( __FUNCTION__ ); \
|
||||||
LOG( SEV_NOTICE, __FUNCTION__ ## ": entering" ); \
|
LOG( SEV_NOTICE, __FUNCTION__ ## ": entering" ); \
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// PDO SQLSRV statement destructor
|
// PDO SQLSRV statement destructor
|
||||||
pdo_sqlsrv_stmt::~pdo_sqlsrv_stmt( void )
|
pdo_sqlsrv_stmt::~pdo_sqlsrv_stmt( void )
|
||||||
|
@ -699,16 +714,13 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
|
||||||
// Let PDO free the memory after use.
|
// Let PDO free the memory after use.
|
||||||
*caller_frees = 1;
|
*caller_frees = 1;
|
||||||
|
|
||||||
// set the metadata for the current column
|
|
||||||
pdo_column_data* column_data = &(stmt->columns[colno]);
|
|
||||||
|
|
||||||
// translate the pdo type to a type the core layer understands
|
// translate the pdo type to a type the core layer understands
|
||||||
sqlsrv_phptype sqlsrv_php_type;
|
sqlsrv_phptype sqlsrv_php_type;
|
||||||
SQLSRV_ASSERT( colno >= 0 && colno < static_cast<int>( driver_stmt->current_meta_data.size()),
|
SQLSRV_ASSERT( colno >= 0 && colno < static_cast<int>( driver_stmt->current_meta_data.size()),
|
||||||
"Invalid column number in pdo_sqlsrv_stmt_get_col_data" );
|
"Invalid column number in pdo_sqlsrv_stmt_get_col_data" );
|
||||||
sqlsrv_php_type = driver_stmt->sql_type_to_php_type( static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_type ),
|
sqlsrv_php_type = driver_stmt->sql_type_to_php_type( static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_type ),
|
||||||
static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_size ),
|
static_cast<SQLUINTEGER>( driver_stmt->current_meta_data[ colno ]->field_size ),
|
||||||
true );
|
true );
|
||||||
|
|
||||||
// set the encoding if the user specified one via bindColumn, otherwise use the statement's encoding
|
// set the encoding if the user specified one via bindColumn, otherwise use the statement's encoding
|
||||||
sqlsrv_php_type.typeinfo.encoding = driver_stmt->encoding();
|
sqlsrv_php_type.typeinfo.encoding = driver_stmt->encoding();
|
||||||
|
@ -756,7 +768,7 @@ int pdo_sqlsrv_stmt_get_col_data(pdo_stmt_t *stmt, int colno,
|
||||||
core_sqlsrv_get_field( driver_stmt, colno, sqlsrv_php_type, false, *(reinterpret_cast<void**>(ptr)),
|
core_sqlsrv_get_field( driver_stmt, colno, sqlsrv_php_type, false, *(reinterpret_cast<void**>(ptr)),
|
||||||
reinterpret_cast<SQLLEN*>( len ), true, &sqlsrv_phptype_out TSRMLS_CC );
|
reinterpret_cast<SQLLEN*>( len ), true, &sqlsrv_phptype_out TSRMLS_CC );
|
||||||
|
|
||||||
zval* zval_ptr = ( zval* )( sqlsrv_malloc( sizeof( zval )));
|
zval* zval_ptr = reinterpret_cast<zval*>( sqlsrv_malloc( sizeof( zval )));
|
||||||
*zval_ptr = convert_to_zval( sqlsrv_phptype_out, reinterpret_cast<void**>( ptr ), *len );
|
*zval_ptr = convert_to_zval( sqlsrv_phptype_out, reinterpret_cast<void**>( ptr ), *len );
|
||||||
*ptr = reinterpret_cast<char*>( zval_ptr );
|
*ptr = reinterpret_cast<char*>( zval_ptr );
|
||||||
|
|
||||||
|
@ -787,7 +799,7 @@ int pdo_sqlsrv_stmt_set_attr(pdo_stmt_t *stmt, zend_long attr, zval *val TSRMLS_
|
||||||
PDO_VALIDATE_STMT;
|
PDO_VALIDATE_STMT;
|
||||||
PDO_LOG_STMT_ENTRY;
|
PDO_LOG_STMT_ENTRY;
|
||||||
|
|
||||||
pdo_sqlsrv_stmt* driver_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
|
pdo_sqlsrv_stmt* driver_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -817,9 +829,9 @@ int pdo_sqlsrv_stmt_set_attr(pdo_stmt_t *stmt, zend_long attr, zval *val TSRMLS_
|
||||||
core_sqlsrv_set_buffered_query_limit( driver_stmt, val TSRMLS_CC );
|
core_sqlsrv_set_buffered_query_limit( driver_stmt, val TSRMLS_CC );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
|
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
|
||||||
driver_stmt->fetch_numeric = ( zend_is_true( val )) ? true : false;
|
driver_stmt->fetch_numeric = ( zend_is_true( val )) ? true : false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_STMT_ATTR );
|
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_STMT_ATTR );
|
||||||
|
@ -896,11 +908,11 @@ int pdo_sqlsrv_stmt_get_attr( pdo_stmt_t *stmt, zend_long attr, zval *return_val
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
|
case SQLSRV_ATTR_FETCHES_NUMERIC_TYPE:
|
||||||
{
|
{
|
||||||
ZVAL_BOOL( return_value, driver_stmt->fetch_numeric );
|
ZVAL_BOOL( return_value, driver_stmt->fetch_numeric );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_STMT_ATTR );
|
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_STMT_ATTR );
|
||||||
|
@ -966,7 +978,12 @@ int pdo_sqlsrv_stmt_get_col_meta(pdo_stmt_t *stmt, zend_long colno, zval *return
|
||||||
long pdo_type = sql_type_to_pdo_type( core_meta_data->field_type );
|
long pdo_type = sql_type_to_pdo_type( core_meta_data->field_type );
|
||||||
switch( pdo_type ) {
|
switch( pdo_type ) {
|
||||||
case PDO_PARAM_STR:
|
case PDO_PARAM_STR:
|
||||||
add_assoc_string( return_value, "native_type", "string" );
|
{
|
||||||
|
//Declarations eliminate compiler warnings about string constant to char* conversions
|
||||||
|
std::string key = "native_type";
|
||||||
|
std::string str = "string";
|
||||||
|
add_assoc_string( return_value, &key[0], &str[0] );
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DIE( "pdo_sqlsrv_stmt_get_col_data: Unknown PDO type returned" );
|
DIE( "pdo_sqlsrv_stmt_get_col_data: Unknown PDO type returned" );
|
||||||
|
@ -1076,11 +1093,11 @@ int pdo_sqlsrv_stmt_param_hook(pdo_stmt_t *stmt,
|
||||||
|
|
||||||
// since the param isn't reliable, we don't do anything here
|
// since the param isn't reliable, we don't do anything here
|
||||||
case PDO_PARAM_EVT_ALLOC:
|
case PDO_PARAM_EVT_ALLOC:
|
||||||
// if emulate prepare is on, set the bind_param_encoding so it can be used in PDO::quote when binding parameters on the client side
|
// if emulate prepare is on, set the bind_param_encoding so it can be used in PDO::quote when binding parameters on the client side
|
||||||
if ( stmt->supports_placeholders == PDO_PLACEHOLDER_NONE ) {
|
if ( stmt->supports_placeholders == PDO_PLACEHOLDER_NONE ) {
|
||||||
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( stmt->dbh->driver_data );
|
pdo_sqlsrv_dbh* driver_dbh = reinterpret_cast<pdo_sqlsrv_dbh*>( stmt->dbh->driver_data );
|
||||||
driver_dbh->bind_param_encoding = static_cast<SQLSRV_ENCODING>( Z_LVAL( param->driver_params ));
|
driver_dbh->bind_param_encoding = static_cast<SQLSRV_ENCODING>( Z_LVAL( param->driver_params ));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PDO_PARAM_EVT_FREE:
|
case PDO_PARAM_EVT_FREE:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -53,8 +53,8 @@ pdo_error PDO_ERRORS[] = {
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_DRIVER_NOT_INSTALLED,
|
SQLSRV_ERROR_DRIVER_NOT_INSTALLED,
|
||||||
{ IMSSP, (SQLCHAR*) "This extension requires the Microsoft ODBC Driver 11 or 13 for SQL Server to "
|
{ IMSSP, (SQLCHAR*) "This extension requires the Microsoft ODBC Driver 13 for SQL Server to "
|
||||||
"communicate with SQL Server. Access the following URL to download the ODBC Driver 11 or 13 for SQL Server "
|
"communicate with SQL Server. Access the following URL to download the ODBC Driver 13 for SQL Server "
|
||||||
"for %1!s!: "
|
"for %1!s!: "
|
||||||
"http://go.microsoft.com/fwlink/?LinkId=163712", -1, true }
|
"http://go.microsoft.com/fwlink/?LinkId=163712", -1, true }
|
||||||
},
|
},
|
||||||
|
@ -535,7 +535,6 @@ bool pdo_sqlsrv_handle_stmt_error( sqlsrv_context& ctx, unsigned int sqlsrv_erro
|
||||||
void pdo_sqlsrv_retrieve_context_error( sqlsrv_error const* last_error, zval* pdo_zval )
|
void pdo_sqlsrv_retrieve_context_error( sqlsrv_error const* last_error, zval* pdo_zval )
|
||||||
{
|
{
|
||||||
if( last_error ) {
|
if( last_error ) {
|
||||||
|
|
||||||
// SQLSTATE is already present in the zval.
|
// SQLSTATE is already present in the zval.
|
||||||
add_next_index_long( pdo_zval, last_error->native_code );
|
add_next_index_long( pdo_zval, last_error->native_code );
|
||||||
add_next_index_string( pdo_zval, reinterpret_cast<char*>( last_error->native_message ));
|
add_next_index_string( pdo_zval, reinterpret_cast<char*>( last_error->native_message ));
|
||||||
|
@ -550,6 +549,7 @@ void pdo_sqlsrv_log( unsigned int severity TSRMLS_DC, const char* msg, va_list*
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, msg, 0, 0, log_msg, LOG_MSG_SIZE, print_args );
|
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 an error occurs for FormatMessage, we just output an internal error occurred.
|
||||||
if( rc == 0 ) {
|
if( rc == 0 ) {
|
||||||
SQLSRV_STATIC_ASSERT( sizeof( INTERNAL_FORMAT_ERROR ) < sizeof( log_msg ));
|
SQLSRV_STATIC_ASSERT( sizeof( INTERNAL_FORMAT_ERROR ) < sizeof( log_msg ));
|
||||||
|
@ -565,7 +565,8 @@ void pdo_sqlsrv_throw_exception( sqlsrv_error_const* error TSRMLS_DC )
|
||||||
{
|
{
|
||||||
zval ex_obj;
|
zval ex_obj;
|
||||||
ZVAL_UNDEF( &ex_obj );
|
ZVAL_UNDEF( &ex_obj );
|
||||||
zend_class_entry* ex_class = pdo_get_exception_class();
|
|
||||||
|
zend_class_entry* ex_class = php_pdo_get_exception();
|
||||||
|
|
||||||
int zr = object_init_ex( &ex_obj, ex_class );
|
int zr = object_init_ex( &ex_obj, ex_class );
|
||||||
SQLSRV_ASSERT( zr != FAILURE, "Failed to initialize exception object" );
|
SQLSRV_ASSERT( zr != FAILURE, "Failed to initialize exception object" );
|
||||||
|
|
|
@ -27,7 +27,6 @@ extern "C" {
|
||||||
|
|
||||||
#include "pdo/php_pdo.h"
|
#include "pdo/php_pdo.h"
|
||||||
#include "pdo/php_pdo_driver.h"
|
#include "pdo/php_pdo_driver.h"
|
||||||
#include "pdo/php_pdo_int.h"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +110,8 @@ extern sqlsrv_context* g_henv_ncp;
|
||||||
// module global variables (initialized in minit and freed in mshutdown)
|
// module global variables (initialized in minit and freed in mshutdown)
|
||||||
extern HashTable* g_pdo_errors_ht;
|
extern HashTable* g_pdo_errors_ht;
|
||||||
|
|
||||||
|
#define phpext_pdo_sqlsrv_ptr &g_pdo_sqlsrv_module_entry
|
||||||
|
|
||||||
// module initialization
|
// module initialization
|
||||||
PHP_MINIT_FUNCTION(pdo_sqlsrv);
|
PHP_MINIT_FUNCTION(pdo_sqlsrv);
|
||||||
// module shutdown function
|
// module shutdown function
|
||||||
|
@ -155,7 +156,7 @@ class conn_string_parser
|
||||||
inline bool is_white_space( char c );
|
inline bool is_white_space( char c );
|
||||||
bool discard_white_spaces( void );
|
bool discard_white_spaces( void );
|
||||||
int discard_trailing_white_spaces( const char* str, int len );
|
int discard_trailing_white_spaces( const char* str, int len );
|
||||||
void conn_string_parser::validate_key( const char *key, int key_len TSRMLS_DC );
|
void validate_key( const char *key, int key_len TSRMLS_DC );
|
||||||
void add_key_value_pair( const char* value, int len TSRMLS_DC );
|
void add_key_value_pair( const char* value, int len TSRMLS_DC );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -214,7 +215,7 @@ struct stmt_option_emulate_prepares : public stmt_option_functor {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct stmt_option_fetch_numeric : public stmt_option_functor {
|
struct stmt_option_fetch_numeric : public stmt_option_functor {
|
||||||
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
|
virtual void operator()( sqlsrv_stmt* stmt, stmt_option const* /*opt*/, zval* value_z TSRMLS_DC );
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct pdo_stmt_methods pdo_sqlsrv_stmt_methods;
|
extern struct pdo_stmt_methods pdo_sqlsrv_stmt_methods;
|
||||||
|
@ -274,7 +275,7 @@ bool pdo_sqlsrv_handle_stmt_error( sqlsrv_context& ctx, unsigned int sqlsrv_erro
|
||||||
va_list* print_args );
|
va_list* print_args );
|
||||||
|
|
||||||
// pointer to the function to return the class entry for the PDO exception Set in MINIT
|
// pointer to the function to return the class entry for the PDO exception Set in MINIT
|
||||||
extern zend_class_entry* (*pdo_get_exception_class)( void );
|
//extern zend_class_entry* (*pdo_get_exception_class)( void );
|
||||||
|
|
||||||
// common routine to transfer a sqlsrv_context's error to a PDO zval
|
// common routine to transfer a sqlsrv_context's error to a PDO zval
|
||||||
void pdo_sqlsrv_retrieve_context_error( sqlsrv_error const* last_error, zval* pdo_zval );
|
void pdo_sqlsrv_retrieve_context_error( sqlsrv_error const* last_error, zval* pdo_zval );
|
||||||
|
@ -375,7 +376,7 @@ enum PDO_ERROR_CODES {
|
||||||
extern pdo_error PDO_ERRORS[];
|
extern pdo_error PDO_ERRORS[];
|
||||||
|
|
||||||
#define THROW_PDO_ERROR( ctx, custom, ... ) \
|
#define THROW_PDO_ERROR( ctx, custom, ... ) \
|
||||||
call_error_handler( ctx, custom TSRMLS_CC, false, __VA_ARGS__ ); \
|
call_error_handler( ctx, custom TSRMLS_CC, false, ## __VA_ARGS__ ); \
|
||||||
throw pdo::PDOException();
|
throw pdo::PDOException();
|
||||||
|
|
||||||
namespace pdo {
|
namespace pdo {
|
||||||
|
@ -393,8 +394,8 @@ namespace pdo {
|
||||||
// called pdo_parse_params in php_pdo_driver.h
|
// called pdo_parse_params in php_pdo_driver.h
|
||||||
// we renamed it for 2 reasons: 1) we can't have the same name since it would conflict with our dynamic linking, and
|
// we renamed it for 2 reasons: 1) we can't have the same name since it would conflict with our dynamic linking, and
|
||||||
// 2) this is a more precise name
|
// 2) this is a more precise name
|
||||||
extern int (*pdo_subst_named_params)(pdo_stmt_t *stmt, char *inquery, size_t inquery_len,
|
//extern int (*pdo_subst_named_params)(pdo_stmt_t *stmt, char *inquery, size_t inquery_len,
|
||||||
char **outquery, size_t *outquery_len TSRMLS_DC);
|
// char **outquery, size_t *outquery_len TSRMLS_DC);
|
||||||
|
|
||||||
// logger for pdo_sqlsrv called by the core layer when it wants to log something with the LOG macro
|
// logger for pdo_sqlsrv called by the core layer when it wants to log something with the LOG macro
|
||||||
void pdo_sqlsrv_log( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );
|
void pdo_sqlsrv_log( unsigned int severity TSRMLS_DC, const char* msg, va_list* print_args );
|
||||||
|
|
Loading…
Reference in a new issue