PHP 8.1 dev (#1282)

This commit is contained in:
Jenny Tam 2021-07-28 15:45:04 -07:00 committed by GitHub
parent 277872619e
commit 5e607a802c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
50 changed files with 816 additions and 278 deletions

View file

@ -436,36 +436,66 @@ const connection_option PDO_CONN_OPTS[] = {
}; };
#if PHP_VERSION_ID < 80100
// close the connection // close the connection
int pdo_sqlsrv_dbh_close( _Inout_ pdo_dbh_t *dbh ); int pdo_sqlsrv_dbh_close(_Inout_ pdo_dbh_t *dbh);
// execute queries // execute queries
int pdo_sqlsrv_dbh_prepare( _Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const char *sql, int pdo_sqlsrv_dbh_prepare(_Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const char *sql,
_Inout_ size_t sql_len, _Inout_ pdo_stmt_t *stmt, _In_ zval *driver_options ); _Inout_ size_t sql_len, _Inout_ pdo_stmt_t *stmt, _In_ zval *driver_options);
zend_long pdo_sqlsrv_dbh_do( _Inout_ pdo_dbh_t *dbh, _In_reads_bytes_(sql_len) const char *sql, _In_ size_t sql_len ); zend_long pdo_sqlsrv_dbh_do(_Inout_ pdo_dbh_t *dbh, _In_reads_bytes_(sql_len) const char *sql, _In_ size_t sql_len);
// quote a string, meaning put quotes around it and escape any quotes within it
int pdo_sqlsrv_dbh_quote(_Inout_ pdo_dbh_t* dbh, _In_reads_(unquotedlen) const char* unquoted, _In_ size_t unquotedlen, _Outptr_result_buffer_(*quotedlen) char **quoted, _Out_ size_t* quotedlen,
enum pdo_param_type paramtype);
// transaction support functions // transaction support functions
int pdo_sqlsrv_dbh_commit( _Inout_ pdo_dbh_t *dbh ); int pdo_sqlsrv_dbh_commit(_Inout_ pdo_dbh_t *dbh);
int pdo_sqlsrv_dbh_begin( _Inout_ pdo_dbh_t *dbh ); int pdo_sqlsrv_dbh_begin(_Inout_ pdo_dbh_t *dbh);
int pdo_sqlsrv_dbh_rollback( _Inout_ pdo_dbh_t *dbh ); int pdo_sqlsrv_dbh_rollback(_Inout_ pdo_dbh_t *dbh);
// attribute functions // attribute functions
int pdo_sqlsrv_dbh_set_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val ); int pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val);
int pdo_sqlsrv_dbh_get_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *return_value ); int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *return_value);
// return more information
int pdo_sqlsrv_dbh_return_error( _In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt,
_Out_ zval *info);
// return the last id generated by an executed SQL statement // return the last id generated by an executed SQL statement
char * pdo_sqlsrv_dbh_last_id( _Inout_ pdo_dbh_t *dbh, _In_z_ const char *name, _Out_ size_t* len ); char * pdo_sqlsrv_dbh_last_id(_Inout_ pdo_dbh_t *dbh, _In_z_ const char *name, _Out_ size_t* len);
// return more information
int pdo_sqlsrv_dbh_return_error(_In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt, _Out_ zval *info);
#else
// close the connection
void pdo_sqlsrv_dbh_close(_Inout_ pdo_dbh_t *dbh);
// execute queries
bool pdo_sqlsrv_dbh_prepare(_Inout_ pdo_dbh_t *dbh, _In_ zend_string *sql,
_Inout_ pdo_stmt_t *stmt, _In_ zval *driver_options);
zend_long pdo_sqlsrv_dbh_do(_Inout_ pdo_dbh_t *dbh, _In_ const zend_string *sql);
// quote a string, meaning put quotes around it and escape any quotes within it
zend_string* pdo_sqlsrv_dbh_quote(_Inout_ pdo_dbh_t* dbh, _In_ const zend_string *unquoted, _In_ enum pdo_param_type paramtype);
// transaction support functions
bool pdo_sqlsrv_dbh_commit(_Inout_ pdo_dbh_t *dbh);
bool pdo_sqlsrv_dbh_begin(_Inout_ pdo_dbh_t *dbh);
bool pdo_sqlsrv_dbh_rollback(_Inout_ pdo_dbh_t *dbh);
// attribute functions
bool pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val);
int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *return_value);
// return the last id generated by an executed SQL statement
zend_string * pdo_sqlsrv_dbh_last_id(_Inout_ pdo_dbh_t *dbh, _In_ const zend_string *name);
// return more information
void pdo_sqlsrv_dbh_return_error(_In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt, _Out_ zval *info);
#endif
// additional methods are supported in this function // additional methods are supported in this function
pdo_sqlsrv_function_entry *pdo_sqlsrv_get_driver_methods( _Inout_ pdo_dbh_t *dbh, int kind ); pdo_sqlsrv_function_entry *pdo_sqlsrv_get_driver_methods( _Inout_ pdo_dbh_t *dbh, int kind );
// quote a string, meaning put quotes around it and escape any quotes within it
int pdo_sqlsrv_dbh_quote( _Inout_ pdo_dbh_t* dbh, _In_reads_(unquotedlen) const char* unquoted, _In_ size_t unquotedlen, _Outptr_result_buffer_(*quotedlen) char **quoted, _Out_ size_t* quotedlen,
enum pdo_param_type paramtype );
struct pdo_dbh_methods pdo_sqlsrv_dbh_methods = { struct pdo_dbh_methods pdo_sqlsrv_dbh_methods = {
@ -632,15 +662,22 @@ int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_
// Parameters: // Parameters:
// dbh - The PDO managed connection object. // dbh - The PDO managed connection object.
// Return: // Return:
// Always returns 1 for success. // Always returns 1 for success. (for PHP_VERSION_ID < 80100)
#if PHP_VERSION_ID < 80100
int pdo_sqlsrv_dbh_close( _Inout_ pdo_dbh_t *dbh ) int pdo_sqlsrv_dbh_close( _Inout_ pdo_dbh_t *dbh )
#else
void pdo_sqlsrv_dbh_close(_Inout_ pdo_dbh_t *dbh)
#endif
{ {
LOG( SEV_NOTICE, "pdo_sqlsrv_dbh_close: entering" ); LOG( SEV_NOTICE, "pdo_sqlsrv_dbh_close: entering" );
// if the connection didn't complete properly, driver_data isn't initialized. // if the connection didn't complete properly, driver_data isn't initialized.
if( dbh->driver_data == NULL ) { if( dbh->driver_data == NULL ) {
#if PHP_VERSION_ID < 80100
return 1; return 1;
#else
return;
#endif
} }
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
@ -649,8 +686,10 @@ int pdo_sqlsrv_dbh_close( _Inout_ pdo_dbh_t *dbh )
core_sqlsrv_close( reinterpret_cast<sqlsrv_conn*>( dbh->driver_data ) ); core_sqlsrv_close( reinterpret_cast<sqlsrv_conn*>( dbh->driver_data ) );
dbh->driver_data = NULL; dbh->driver_data = NULL;
#if PHP_VERSION_ID < 80100
// always return success that the connection is closed // always return success that the connection is closed
return 1; return 1;
#endif
} }
// pdo_sqlsrv_dbh_prepare // pdo_sqlsrv_dbh_prepare
@ -664,8 +703,12 @@ int pdo_sqlsrv_dbh_close( _Inout_ pdo_dbh_t *dbh )
// driver_options - User provided list of statement options. // driver_options - User provided list of statement options.
// Return: // Return:
// 0 for failure, 1 for success. // 0 for failure, 1 for success.
int pdo_sqlsrv_dbh_prepare( _Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const char *sql, #if PHP_VERSION_ID < 80100
_Inout_ size_t sql_len, _Inout_ pdo_stmt_t *stmt, _In_ zval *driver_options ) int pdo_sqlsrv_dbh_prepare(_Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const char *sql,
_Inout_ size_t sql_len, _Inout_ pdo_stmt_t *stmt, _In_ zval *driver_options)
#else
bool pdo_sqlsrv_dbh_prepare(_Inout_ pdo_dbh_t *dbh, _In_ zend_string *sql_zstr, _Inout_ pdo_stmt_t *stmt, _In_ zval *driver_options)
#endif
{ {
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN; PDO_VALIDATE_CONN;
@ -707,27 +750,44 @@ int pdo_sqlsrv_dbh_prepare( _Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const ch
driver_stmt->buffered_query_limit = driver_dbh->client_buffer_max_size; driver_stmt->buffered_query_limit = driver_dbh->client_buffer_max_size;
} }
#if PHP_VERSION_ID >= 80100
zend_string* sql_rewrite_zstr = NULL;
const char* sql = ZSTR_VAL(sql_zstr);
size_t sql_len = ZSTR_LEN(sql_zstr);
#endif
// rewrite named parameters in the query to positional parameters if we aren't letting PDO do the // rewrite named parameters in the query to positional parameters if we aren't letting PDO do the
// parameter substitution for us // parameter substitution for us
if( stmt->supports_placeholders != PDO_PLACEHOLDER_NONE ) { if( stmt->supports_placeholders != PDO_PLACEHOLDER_NONE ) {
// 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.
#if PHP_VERSION_ID < 80100
int zr = pdo_parse_params( stmt, const_cast<char*>( sql ), sql_len, &sql_rewrite, &sql_rewrite_len ); int zr = pdo_parse_params( stmt, const_cast<char*>( sql ), sql_len, &sql_rewrite, &sql_rewrite_len );
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 != 0) { if (sql_rewrite != 0) {
sql = sql_rewrite; sql = sql_rewrite;
sql_len = sql_rewrite_len; sql_len = sql_rewrite_len;
} }
#else
int zr = pdo_parse_params(stmt, sql_zstr, &sql_rewrite_zstr);
CHECK_ZEND_ERROR(zr, driver_dbh, PDO_SQLSRV_ERROR_PARAM_PARSE) {
throw core::CoreException();
}
// if parameter substitution happened, use that query instead of the original
if (sql_rewrite_zstr != NULL) {
sql = ZSTR_VAL(sql_rewrite_zstr);
sql_len = ZSTR_LEN(sql_rewrite_zstr);
}
#endif
} }
if( !driver_stmt->direct_query && stmt->supports_placeholders != PDO_PLACEHOLDER_NONE ) { if( !driver_stmt->direct_query && stmt->supports_placeholders != PDO_PLACEHOLDER_NONE ) {
core_sqlsrv_prepare(driver_stmt, sql, sql_len);
core_sqlsrv_prepare( driver_stmt, sql, sql_len );
} }
else if( driver_stmt->direct_query ) { else if( driver_stmt->direct_query ) {
@ -739,14 +799,26 @@ int pdo_sqlsrv_dbh_prepare( _Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const ch
driver_stmt->direct_query_subst_string = estrdup( sql ); driver_stmt->direct_query_subst_string = estrdup( sql );
driver_stmt->direct_query_subst_string_len = sql_len; driver_stmt->direct_query_subst_string_len = sql_len;
} }
#if PHP_VERSION_ID >= 80100
if (sql_rewrite_zstr != NULL) {
zend_string_release(sql_rewrite_zstr);
}
#endif
// else if stmt->support_placeholders == PDO_PLACEHOLDER_NONE means that stmt->active_query_string will be // else if stmt->support_placeholders == PDO_PLACEHOLDER_NONE means that stmt->active_query_string will be
// set to the substituted query // set to the substituted query
if ( stmt->supports_placeholders == PDO_PLACEHOLDER_NONE ) { if ( stmt->supports_placeholders == PDO_PLACEHOLDER_NONE ) {
// parse placeholders in the sql query into the placeholders ht // parse placeholders in the sql query into the placeholders ht
ALLOC_HASHTABLE( placeholders ); ALLOC_HASHTABLE( placeholders );
core::sqlsrv_zend_hash_init( *driver_dbh, placeholders, 5, ZVAL_PTR_DTOR /* dtor */, 0 /* persistent */ ); core::sqlsrv_zend_hash_init(*driver_dbh, placeholders, 5, ZVAL_PTR_DTOR /* dtor */, 0 /* persistent */);
sql_parser = new ( sqlsrv_malloc( sizeof( sql_string_parser ))) sql_string_parser( *driver_dbh, stmt->query_string, #if PHP_VERSION_ID < 80100
static_cast<int>(stmt->query_stringlen), placeholders ); sql_parser = new (sqlsrv_malloc(sizeof(sql_string_parser))) sql_string_parser(*driver_dbh, stmt->query_string,
static_cast<int>(stmt->query_stringlen), placeholders);
#else
sql_parser = new (sqlsrv_malloc(sizeof(sql_string_parser))) sql_string_parser(*driver_dbh, ZSTR_VAL(stmt->query_string),
ZSTR_LEN(stmt->query_string), placeholders);
#endif
sql_parser->parse_sql_string(); sql_parser->parse_sql_string();
driver_stmt->placeholders = placeholders; driver_stmt->placeholders = placeholders;
placeholders.transferred(); placeholders.transferred();
@ -772,7 +844,11 @@ int pdo_sqlsrv_dbh_prepare( _Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const ch
reinterpret_cast<const char*>( driver_dbh->last_error()->sqlstate )); reinterpret_cast<const char*>( driver_dbh->last_error()->sqlstate ));
} }
#if PHP_VERSION_ID < 80100
return 0; return 0;
#else
return false;
#endif
} }
// catch any errant exception and die // catch any errant exception and die
@ -781,7 +857,11 @@ int pdo_sqlsrv_dbh_prepare( _Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const ch
DIE( "pdo_sqlsrv_dbh_prepare: Unknown exception caught." ); DIE( "pdo_sqlsrv_dbh_prepare: Unknown exception caught." );
} }
#if PHP_VERSION_ID < 80100
return 1; return 1;
#else
return true;
#endif
} }
@ -795,7 +875,11 @@ int pdo_sqlsrv_dbh_prepare( _Inout_ pdo_dbh_t *dbh, _In_reads_(sql_len) const ch
// sql_len - length of sql query // sql_len - length of sql query
// Return // Return
// # of rows affected, -1 for an error. // # of rows affected, -1 for an error.
#if PHP_VERSION_ID < 80100
zend_long pdo_sqlsrv_dbh_do( _Inout_ pdo_dbh_t *dbh, _In_reads_bytes_(sql_len) const char *sql, _In_ size_t sql_len ) zend_long pdo_sqlsrv_dbh_do( _Inout_ pdo_dbh_t *dbh, _In_reads_bytes_(sql_len) const char *sql, _In_ size_t sql_len )
#else
zend_long pdo_sqlsrv_dbh_do(_Inout_ pdo_dbh_t *dbh, _In_ const zend_string *sql)
#endif
{ {
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN; PDO_VALIDATE_CONN;
@ -823,8 +907,11 @@ zend_long pdo_sqlsrv_dbh_do( _Inout_ pdo_dbh_t *dbh, _In_reads_bytes_(sql_len) c
NULL /*valid_stmt_opts*/, pdo_sqlsrv_handle_stmt_error, &temp_stmt ); NULL /*valid_stmt_opts*/, pdo_sqlsrv_handle_stmt_error, &temp_stmt );
driver_stmt->set_func( __FUNCTION__ ); driver_stmt->set_func( __FUNCTION__ );
SQLRETURN execReturn = core_sqlsrv_execute( driver_stmt, sql, static_cast<int>( sql_len ) ); #if PHP_VERSION_ID < 80100
SQLRETURN execReturn = core_sqlsrv_execute(driver_stmt, sql, static_cast<int>(sql_len));
#else
SQLRETURN execReturn = core_sqlsrv_execute(driver_stmt, ZSTR_VAL(sql), ZSTR_LEN(sql));
#endif
// since the user can give us a compound statement, we return the row count for the last set, and since the row count // since the user can give us a compound statement, we return the row count for the last set, and since the row count
// isn't guaranteed to be valid until all the results have been fetched, we fetch them all first. // isn't guaranteed to be valid until all the results have been fetched, we fetch them all first.
@ -883,8 +970,13 @@ zend_long pdo_sqlsrv_dbh_do( _Inout_ pdo_dbh_t *dbh, _In_reads_bytes_(sql_len) c
// Parameters: // Parameters:
// dbh - The PDO managed connection object. // dbh - The PDO managed connection object.
// Return: // Return:
// 0 for failure and 1 for success. // 0 for failure and 1 for success. (if PHP_VERSION_ID < 80100)
int pdo_sqlsrv_dbh_begin( _Inout_ pdo_dbh_t *dbh ) // Return true if currently inside a transaction, false otherwise
#if PHP_VERSION_ID < 80100
int pdo_sqlsrv_dbh_begin(_Inout_ pdo_dbh_t *dbh)
#else
bool pdo_sqlsrv_dbh_begin(_Inout_ pdo_dbh_t *dbh)
#endif
{ {
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN; PDO_VALIDATE_CONN;
@ -902,18 +994,29 @@ int pdo_sqlsrv_dbh_begin( _Inout_ pdo_dbh_t *dbh )
core_sqlsrv_begin_transaction( driver_conn ); core_sqlsrv_begin_transaction( driver_conn );
#if PHP_VERSION_ID < 80100
return 1; return 1;
#else
return true;
#endif
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
#if PHP_VERSION_ID < 80100
return 0; return 0;
#else
return false;
#endif
} }
catch( ... ) { catch( ... ) {
DIE ("pdo_sqlsrv_dbh_begin: Uncaught exception occurred."); DIE ("pdo_sqlsrv_dbh_begin: Uncaught exception occurred.");
} }
// Should not have reached here but adding this due to compilation warnings // Should not have reached here but adding this due to compilation warnings
#if PHP_VERSION_ID < 80100
return 0; return 0;
#else
return false;
#endif
} }
@ -927,8 +1030,13 @@ int pdo_sqlsrv_dbh_begin( _Inout_ pdo_dbh_t *dbh )
// Parameters: // Parameters:
// dbh - The PDO managed connection object. // dbh - The PDO managed connection object.
// Return: // Return:
// 0 for failure and 1 for success. // 0 for failure and 1 for success. (if PHP_VERSION_ID < 80100)
int pdo_sqlsrv_dbh_commit( _Inout_ pdo_dbh_t *dbh ) // Return true for success and false otherwise
#if PHP_VERSION_ID < 80100
int pdo_sqlsrv_dbh_commit(_Inout_ pdo_dbh_t *dbh)
#else
bool pdo_sqlsrv_dbh_commit(_Inout_ pdo_dbh_t *dbh)
#endif
{ {
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN; PDO_VALIDATE_CONN;
@ -946,18 +1054,30 @@ int pdo_sqlsrv_dbh_commit( _Inout_ pdo_dbh_t *dbh )
core_sqlsrv_commit( driver_conn ); core_sqlsrv_commit( driver_conn );
#if PHP_VERSION_ID < 80100
return 1; return 1;
#else
return true;
#endif
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
#if PHP_VERSION_ID < 80100
return 0; return 0;
#else
return false;
#endif
} }
catch( ... ) { catch( ... ) {
DIE ("pdo_sqlsrv_dbh_commit: Uncaught exception occurred."); DIE ("pdo_sqlsrv_dbh_commit: Uncaught exception occurred.");
} }
// Should not have reached here but adding this due to compilation warnings // Should not have reached here but adding this due to compilation warnings
#if PHP_VERSION_ID < 80100
return 0; return 0;
#else
return false;
#endif
} }
// pdo_sqlsrv_dbh_rollback // pdo_sqlsrv_dbh_rollback
@ -969,8 +1089,13 @@ int pdo_sqlsrv_dbh_commit( _Inout_ pdo_dbh_t *dbh )
// Parameters: // Parameters:
// dbh - The PDO managed connection object. // dbh - The PDO managed connection object.
// Return: // Return:
// 0 for failure and 1 for success. // 0 for failure and 1 for success. (if PHP_VERSION_ID < 80100)
int pdo_sqlsrv_dbh_rollback( _Inout_ pdo_dbh_t *dbh ) // Return true for success and false otherwise
#if PHP_VERSION_ID < 80100
int pdo_sqlsrv_dbh_rollback(_Inout_ pdo_dbh_t *dbh)
#else
bool pdo_sqlsrv_dbh_rollback(_Inout_ pdo_dbh_t *dbh)
#endif
{ {
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN; PDO_VALIDATE_CONN;
@ -987,18 +1112,30 @@ int pdo_sqlsrv_dbh_rollback( _Inout_ pdo_dbh_t *dbh )
core_sqlsrv_rollback( driver_conn ); core_sqlsrv_rollback( driver_conn );
#if PHP_VERSION_ID < 80100
return 1; return 1;
#else
return true;
#endif
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
#if PHP_VERSION_ID < 80100
return 0; return 0;
#else
return false;
#endif
} }
catch( ... ) { catch( ... ) {
DIE ("pdo_sqlsrv_dbh_rollback: Uncaught exception occurred."); DIE ("pdo_sqlsrv_dbh_rollback: Uncaught exception occurred.");
} }
// Should not have reached here but adding this due to compilation warnings // Should not have reached here but adding this due to compilation warnings
#if PHP_VERSION_ID < 80100
return 0; return 0;
#else
return false;
#endif
} }
// pdo_sqlsrv_dbh_set_attr // pdo_sqlsrv_dbh_set_attr
@ -1010,8 +1147,13 @@ int pdo_sqlsrv_dbh_rollback( _Inout_ pdo_dbh_t *dbh )
// attr - The attribute to be set. // attr - The attribute to be set.
// val - The value of the attribute to be set. // val - The value of the attribute to be set.
// Return: // Return:
// 0 for failure, 1 for success. // 0 for failure, 1 for success. (if PHP_VERSION_ID < 80100)
int pdo_sqlsrv_dbh_set_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val ) // Return true on success and false in case of failure
#if PHP_VERSION_ID < 80100
int pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val)
#else
bool pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *val)
#endif
{ {
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN; PDO_VALIDATE_CONN;
@ -1158,11 +1300,18 @@ int pdo_sqlsrv_dbh_set_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
} }
} }
catch( pdo::PDOException& ) { catch( pdo::PDOException& ) {
#if PHP_VERSION_ID < 80100
return 0; return 0;
#else
return false;
#endif
} }
#if PHP_VERSION_ID < 80100
return 1; return 1;
#else
return true;
#endif
} }
@ -1173,8 +1322,12 @@ int pdo_sqlsrv_dbh_set_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
// attr - The attribute to get. // attr - The attribute to get.
// return_value - zval in which to return the attribute value. // return_value - zval in which to return the attribute value.
// Return: // Return:
// 0 for failure, 1 for success. // 0 for failure, 1 for success. (if PHP_VERSION_ID < 80100)
int pdo_sqlsrv_dbh_get_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *return_value ) // There are 3 return states:
// -1 for errors while retrieving a valid attribute
// 0 for attempting to retrieve an attribute which is not supported by the driver
// any other value for success, *return_value must be set to the attribute value
int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_ zval *return_value)
{ {
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN; PDO_VALIDATE_CONN;
@ -1196,8 +1349,12 @@ int pdo_sqlsrv_dbh_get_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
case PDO_ATTR_AUTOCOMMIT: case PDO_ATTR_AUTOCOMMIT:
case PDO_ATTR_TIMEOUT: case PDO_ATTR_TIMEOUT:
{ {
#if PHP_VERSION_ID < 80100
// PDO does not throw "not supported" error message for these attributes. // PDO does not throw "not supported" error message for these attributes.
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_UNSUPPORTED_DBH_ATTR ); THROW_PDO_ERROR(driver_dbh, PDO_SQLSRV_ERROR_UNSUPPORTED_DBH_ATTR);
#else
return 0;
#endif
} }
// Statement level only // Statement level only
@ -1303,10 +1460,18 @@ int pdo_sqlsrv_dbh_get_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
} }
} }
#if PHP_VERSION_ID < 80100
return 1; return 1;
#else
return 1;
#endif
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
#if PHP_VERSION_ID < 80100
return 0; return 0;
#else
return -1;
#endif
} }
} }
@ -1318,8 +1483,11 @@ int pdo_sqlsrv_dbh_get_attr( _Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
// info - zval in which to return the error info. // info - zval in which to return the error info.
// Return: // Return:
// 0 for failure, 1 for success. // 0 for failure, 1 for success.
int pdo_sqlsrv_dbh_return_error( _In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt, #if PHP_VERSION_ID < 80100
_Out_ zval *info) int pdo_sqlsrv_dbh_return_error(_In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt, _Out_ zval *info)
#else
void pdo_sqlsrv_dbh_return_error(_In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt, _Out_ zval *info)
#endif
{ {
SQLSRV_ASSERT( dbh != NULL || stmt != NULL, "Either dbh or stmt must not be NULL to dereference the error." ); SQLSRV_ASSERT( dbh != NULL || stmt != NULL, "Either dbh or stmt must not be NULL to dereference the error." );
@ -1333,7 +1501,9 @@ int pdo_sqlsrv_dbh_return_error( _In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt,
pdo_sqlsrv_retrieve_context_error( ctx_error, info ); pdo_sqlsrv_retrieve_context_error( ctx_error, info );
#if PHP_VERSION_ID < 80100
return 1; return 1;
#endif
} }
// pdo_sqlsrv_dbh_last_id // pdo_sqlsrv_dbh_last_id
@ -1344,8 +1514,13 @@ int pdo_sqlsrv_dbh_return_error( _In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt,
// name - Table name. // name - Table name.
// len - Length of the name. // len - Length of the name.
// Return: // Return:
// Returns the last insert id as a string. // Returns the last insert id as a string. (if PHP_VERSION_ID < 80100)
char * pdo_sqlsrv_dbh_last_id( _Inout_ pdo_dbh_t *dbh, _In_z_ const char *name, _Out_ size_t* len ) // Returning NULL indicates an error condition. The input "name" MIGHT be NULL
#if PHP_VERSION_ID < 80100
char * pdo_sqlsrv_dbh_last_id(_Inout_ pdo_dbh_t *dbh, _In_z_ const char *name, _Out_ size_t* len)
#else
zend_string * pdo_sqlsrv_dbh_last_id(_Inout_ pdo_dbh_t *dbh, _In_ const zend_string *name)
#endif
{ {
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN; PDO_VALIDATE_CONN;
@ -1372,7 +1547,12 @@ char * pdo_sqlsrv_dbh_last_id( _Inout_ pdo_dbh_t *dbh, _In_z_ const char *name,
wsql_string = utf16_string_from_mbcs_string(SQLSRV_ENCODING_CHAR, LAST_INSERT_ID_QUERY, sizeof(LAST_INSERT_ID_QUERY), &wsql_len); wsql_string = utf16_string_from_mbcs_string(SQLSRV_ENCODING_CHAR, LAST_INSERT_ID_QUERY, sizeof(LAST_INSERT_ID_QUERY), &wsql_len);
} else { } else {
char buffer[LAST_INSERT_ID_QUERY_MAX_LEN] = { '\0' }; char buffer[LAST_INSERT_ID_QUERY_MAX_LEN] = { '\0' };
#if PHP_VERSION_ID < 80100
snprintf(buffer, LAST_INSERT_ID_QUERY_MAX_LEN, SEQUENCE_CURRENT_VALUE_QUERY, name); snprintf(buffer, LAST_INSERT_ID_QUERY_MAX_LEN, SEQUENCE_CURRENT_VALUE_QUERY, name);
#else
const char *name_str = ZSTR_VAL(name);
snprintf(buffer, LAST_INSERT_ID_QUERY_MAX_LEN, SEQUENCE_CURRENT_VALUE_QUERY, ZSTR_VAL(name));
#endif
wsql_string = utf16_string_from_mbcs_string(SQLSRV_ENCODING_CHAR, buffer, sizeof(buffer), &wsql_len); wsql_string = utf16_string_from_mbcs_string(SQLSRV_ENCODING_CHAR, buffer, sizeof(buffer), &wsql_len);
} }
CHECK_CUSTOM_ERROR(wsql_string == 0, driver_stmt, SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE, get_last_error_message()) { CHECK_CUSTOM_ERROR(wsql_string == 0, driver_stmt, SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE, get_last_error_message()) {
@ -1408,20 +1588,31 @@ char * pdo_sqlsrv_dbh_last_id( _Inout_ pdo_dbh_t *dbh, _In_z_ const char *name,
if( driver_stmt ) { if( driver_stmt ) {
driver_stmt->~sqlsrv_stmt(); driver_stmt->~sqlsrv_stmt();
} }
#if PHP_VERSION_ID < 80100
*len = 0; *len = 0;
str = reinterpret_cast<char*>(sqlsrv_malloc(0, sizeof(char), 1)); // return an empty string with a null terminator str = reinterpret_cast<char*>(sqlsrv_malloc(0, sizeof(char), 1)); // return an empty string with a null terminator
str[0] = '\0'; str[0] = '\0';
return str; return str;
#else
return NULL;
#endif
} }
// restore error handling to its previous mode // restore error handling to its previous mode
dbh->error_mode = prev_err_mode; dbh->error_mode = prev_err_mode;
// copy the last ID string and return it // copy the last ID string and return it
*len = static_cast<size_t>(cbID);
str = reinterpret_cast<char*>(sqlsrv_malloc(cbID, sizeof(char), 1)); // include space for null terminator str = reinterpret_cast<char*>(sqlsrv_malloc(cbID, sizeof(char), 1)); // include space for null terminator
strcpy_s(str, cbID + 1, idSTR); strcpy_s(str, cbID + 1, idSTR);
#if PHP_VERSION_ID < 80100
*len = static_cast<size_t>(cbID);
return str; return str;
#else
zend_string *zstr = zend_string_init(str, cbID, 0);
sqlsrv_free(str);
return zstr;
#endif
} }
// pdo_sqlsrv_dbh_quote // pdo_sqlsrv_dbh_quote
@ -1435,8 +1626,12 @@ char * pdo_sqlsrv_dbh_last_id( _Inout_ pdo_dbh_t *dbh, _In_z_ const char *name,
// quoted_len - Length of the output string. // quoted_len - Length of the output string.
// Return: // Return:
// 0 for failure, 1 for success. // 0 for failure, 1 for success.
#if PHP_VERSION_ID < 80100
int pdo_sqlsrv_dbh_quote( _Inout_ pdo_dbh_t* dbh, _In_reads_(unquoted_len) const char* unquoted, _In_ size_t unquoted_len, _Outptr_result_buffer_(*quoted_len) char **quoted, _Out_ size_t* quoted_len, int pdo_sqlsrv_dbh_quote( _Inout_ pdo_dbh_t* dbh, _In_reads_(unquoted_len) const char* unquoted, _In_ size_t unquoted_len, _Outptr_result_buffer_(*quoted_len) char **quoted, _Out_ size_t* quoted_len,
enum pdo_param_type paramtype ) enum pdo_param_type paramtype )
#else
zend_string* pdo_sqlsrv_dbh_quote(_Inout_ pdo_dbh_t* dbh, _In_ const zend_string *unquoted, _In_ enum pdo_param_type paramtype)
#endif
{ {
PDO_RESET_DBH_ERROR; PDO_RESET_DBH_ERROR;
PDO_VALIDATE_CONN; PDO_VALIDATE_CONN;
@ -1513,7 +1708,8 @@ int pdo_sqlsrv_dbh_quote( _Inout_ pdo_dbh_t* dbh, _In_reads_(unquoted_len) const
} }
#endif #endif
if ( encoding == SQLSRV_ENCODING_BINARY ) { if (encoding == SQLSRV_ENCODING_BINARY) {
#if PHP_VERSION_ID < 80100
*quoted_len = (unquoted_len * 2) + 2; // each character will be converted to 2 hex digits and prepend '0x' to the result *quoted_len = (unquoted_len * 2) + 2; // each character will be converted to 2 hex digits and prepend '0x' to the result
*quoted = reinterpret_cast<char*>(sqlsrv_malloc(*quoted_len, sizeof(char), 1)); // include space for null terminator *quoted = reinterpret_cast<char*>(sqlsrv_malloc(*quoted_len, sizeof(char), 1)); // include space for null terminator
memset(*quoted, '\0', *quoted_len + 1); memset(*quoted, '\0', *quoted_len + 1);
@ -1534,7 +1730,38 @@ int pdo_sqlsrv_dbh_quote( _Inout_ pdo_dbh_t* dbh, _In_reads_(unquoted_len) const
} }
pos += 2; pos += 2;
} }
return 1; return 1;
#else
size_t unquoted_len = ZSTR_LEN(unquoted);
const char *unquoted_str = ZSTR_VAL(unquoted);
sqlsrv_malloc_auto_ptr<char> quoted;
size_t quoted_len = (unquoted_len * 2) + 2; // each character will be converted to 2 hex digits and prepend '0x' to the result
quoted = reinterpret_cast<char*>(sqlsrv_malloc(quoted_len, sizeof(char), 1)); // include space for null terminator
memset(quoted, '\0', quoted_len + 1);
unsigned int pos = 0;
quoted[pos++] = '0';
quoted[pos++] = 'x';
char *p = quoted;
for (size_t index = 0; index < unquoted_len && unquoted_str[index] != '\0'; ++index) {
// On success, snprintf returns the total number of characters written
// On failure, a negative number is returned
// The generated string has a length of at most len - 1, so
// len is 3 (2 hex digits + 1)
int n = snprintf((char*)(p + pos), 3, "%02X", unquoted_str[index]);
if (n < 0) {
// Something went wrong, simply return NULL (failure)
return NULL;
}
pos += 2;
}
zend_string* zstr = zend_string_init(quoted, quoted_len, 0);
return zstr;
#endif
} }
else { else {
// The minimum number of single quotes needed is 2 -- the initial start and end quotes // The minimum number of single quotes needed is 2 -- the initial start and end quotes
@ -1542,18 +1769,35 @@ int pdo_sqlsrv_dbh_quote( _Inout_ pdo_dbh_t* dbh, _In_reads_(unquoted_len) const
int quotes_needed = (use_national_char_set) ? 3 : 2; int quotes_needed = (use_national_char_set) ? 3 : 2;
char c = '\''; char c = '\'';
#if PHP_VERSION_ID < 80100
std::string tmp_str(unquoted, unquoted_len); // Copy all unquoted_len characters from unquoted std::string tmp_str(unquoted, unquoted_len); // Copy all unquoted_len characters from unquoted
#else
size_t unquoted_len = ZSTR_LEN(unquoted);
const char *unquoted_str = ZSTR_VAL(unquoted);
std::string tmp_str(unquoted_str, unquoted_len); // Copy all unquoted_len characters from unquoted
#endif
std::size_t found = tmp_str.find(c); // Find the first single quote std::size_t found = tmp_str.find(c); // Find the first single quote
while (found != std::string::npos) { while (found != std::string::npos) {
tmp_str.insert(found + 1, 1, c); // Insert an additional single quote tmp_str.insert(found + 1, 1, c); // Insert an additional single quote
found = tmp_str.find(c, found + 2); // Find the next single quote found = tmp_str.find(c, found + 2); // Find the next single quote
} }
size_t len = tmp_str.length(); size_t len = tmp_str.length();
#if PHP_VERSION_ID < 80100
*quoted_len = quotes_needed + len; // The new length should be number of quotes plus the length of tmp_str *quoted_len = quotes_needed + len; // The new length should be number of quotes plus the length of tmp_str
*quoted = reinterpret_cast<char*>(sqlsrv_malloc(*quoted_len, sizeof(char), 1)); // include space for null terminator *quoted = reinterpret_cast<char*>(sqlsrv_malloc(*quoted_len, sizeof(char), 1)); // include space for null terminator
memset(*quoted, '\0', *quoted_len + 1); memset(*quoted, '\0', *quoted_len + 1);
char *p = *quoted; char *p = *quoted;
#else
sqlsrv_malloc_auto_ptr<char> quoted;
size_t quoted_len = quotes_needed + len; // length returned to the caller should not account for null terminator
quoted = reinterpret_cast<char*>(sqlsrv_malloc(quoted_len, sizeof(char), 1)); // include space for null terminator
memset(quoted, '\0', quoted_len + 1);
char *p = quoted;
#endif
size_t pos = 0; size_t pos = 0;
if (use_national_char_set) { // Insert the letter N if the encoding is UTF8 if (use_national_char_set) { // Insert the letter N if the encoding is UTF8
*(p + (pos++)) = 'N'; *(p + (pos++)) = 'N';
@ -1562,7 +1806,13 @@ int pdo_sqlsrv_dbh_quote( _Inout_ pdo_dbh_t* dbh, _In_reads_(unquoted_len) const
tmp_str.copy(p + pos, len, 0); // Copy tmp_str to *quoted tmp_str.copy(p + pos, len, 0); // Copy tmp_str to *quoted
pos += len; pos += len;
*(p + pos) = c; // Add the end quote *(p + pos) = c; // Add the end quote
#if PHP_VERSION_ID < 80100
return 1; return 1;
#else
zend_string* zstr = zend_string_init(quoted, quoted_len, 0);
return zstr;
#endif
} }
} }

View file

@ -278,8 +278,13 @@ int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orienta
int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt, int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
_Inout_ struct pdo_bound_param_data *param, _In_ enum pdo_param_event event_type ); _Inout_ struct pdo_bound_param_data *param, _In_ enum pdo_param_event event_type );
int pdo_sqlsrv_stmt_describe_col( _Inout_ pdo_stmt_t *stmt, _In_ int colno ); int pdo_sqlsrv_stmt_describe_col( _Inout_ pdo_stmt_t *stmt, _In_ int colno );
#if PHP_VERSION_ID < 80100
int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno, int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno,
_Out_writes_bytes_opt_(*len) char **ptr, _Inout_ size_t *len, _Out_opt_ int *caller_frees ); _Out_writes_bytes_opt_(*len) char **ptr, _Inout_ size_t *len, _Out_opt_ int *caller_frees );
#else
int pdo_sqlsrv_stmt_get_col_data(_Inout_ pdo_stmt_t *stmt, _In_ int colno, _Inout_ zval *result, _Inout_ enum pdo_param_type *type);
#endif
int pdo_sqlsrv_stmt_set_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _Inout_ zval *val ); int pdo_sqlsrv_stmt_set_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _Inout_ zval *val );
int pdo_sqlsrv_stmt_get_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _Inout_ zval *return_value ); int pdo_sqlsrv_stmt_get_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _Inout_ zval *return_value );
int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno, _Inout_ zval *return_value ); int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno, _Inout_ zval *return_value );
@ -453,9 +458,10 @@ int pdo_sqlsrv_stmt_describe_col( _Inout_ pdo_stmt_t *stmt, _In_ int colno)
// Set the precision // Set the precision
column_data->precision = core_meta_data->field_scale; column_data->precision = core_meta_data->field_scale;
#if PHP_VERSION_ID < 80100
// Set the param_type // Set the param_type
column_data->param_type = PDO_PARAM_ZVAL; column_data->param_type = PDO_PARAM_ZVAL;
#endif
// store the field data for use by pdo_sqlsrv_stmt_get_col_data // store the field data for use by pdo_sqlsrv_stmt_get_col_data
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 );
SQLSRV_ASSERT( driver_stmt != NULL, "Invalid driver statement in pdo_sqlsrv_stmt_describe_col" ); SQLSRV_ASSERT( driver_stmt != NULL, "Invalid driver statement in pdo_sqlsrv_stmt_describe_col" );
@ -551,8 +557,13 @@ int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt )
zend_hash_internal_pointer_reset(driver_stmt->placeholders); zend_hash_internal_pointer_reset(driver_stmt->placeholders);
#if PHP_VERSION_ID < 80100
query = stmt->active_query_string; query = stmt->active_query_string;
query_len = static_cast<unsigned int>(stmt->active_query_stringlen); query_len = static_cast<unsigned int>(stmt->active_query_stringlen);
#else
query = ZSTR_VAL(stmt->active_query_string);
query_len = ZSTR_LEN(stmt->active_query_string);
#endif
} }
// The query timeout setting is inherited from the corresponding connection attribute, but // The query timeout setting is inherited from the corresponding connection attribute, but
@ -652,14 +663,23 @@ int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orienta
pdo_bound_param_data* bind_data = NULL; pdo_bound_param_data* bind_data = NULL;
if( !driver_stmt->bound_column_param_types ) { if( !driver_stmt->bound_column_param_types ) {
#if PHP_VERSION_ID < 80100
driver_stmt->bound_column_param_types = driver_stmt->bound_column_param_types =
reinterpret_cast<pdo_param_type*>( sqlsrv_malloc( stmt->column_count, sizeof( pdo_param_type ), 0 )); reinterpret_cast<pdo_param_type*>( sqlsrv_malloc( stmt->column_count, sizeof( pdo_param_type ), 0 ));
std::fill( driver_stmt->bound_column_param_types, driver_stmt->bound_column_param_types + stmt->column_count, std::fill( driver_stmt->bound_column_param_types, driver_stmt->bound_column_param_types + stmt->column_count,
PDO_PARAM_ZVAL ); PDO_PARAM_ZVAL );
#else
// TODO: possibly no longer need bound_column_param_types?? default to PDO_PARAM_STR???
driver_stmt->bound_column_param_types =
reinterpret_cast<pdo_param_type*>(sqlsrv_malloc(stmt->column_count, sizeof(pdo_param_type), 0));
std::fill(driver_stmt->bound_column_param_types, driver_stmt->bound_column_param_types + stmt->column_count,
PDO_PARAM_STR);
#endif
} }
for( long i = 0; i < stmt->column_count; ++i ) { for( long i = 0; i < stmt->column_count; ++i ) {
#if PHP_VERSION_ID < 80100
if (NULL== (bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_index_find_ptr(stmt->bound_columns, i))) && if (NULL== (bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_index_find_ptr(stmt->bound_columns, i))) &&
(NULL == (bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_find_ptr(stmt->bound_columns, stmt->columns[i].name))))) { (NULL == (bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_find_ptr(stmt->bound_columns, stmt->columns[i].name))))) {
@ -672,6 +692,15 @@ int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orienta
driver_stmt->bound_column_param_types[i] = bind_data->param_type; driver_stmt->bound_column_param_types[i] = bind_data->param_type;
bind_data->param_type = PDO_PARAM_ZVAL; bind_data->param_type = PDO_PARAM_ZVAL;
} }
#else
if (NULL == (bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_index_find_ptr(stmt->bound_columns, i))) &&
(NULL == (bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_find_ptr(stmt->bound_columns, stmt->columns[i].name))))) {
continue;
}
// TODO: possibly no longer need bound_column_param_types??
driver_stmt->bound_column_param_types[i] = bind_data->param_type;
#endif
} }
} }
@ -730,8 +759,13 @@ int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orienta
// freeing the memory. // freeing the memory.
// Return: // Return:
// 0 for failure, 1 for success. // 0 for failure, 1 for success.
#if PHP_VERSION_ID < 80100
int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno, int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno,
_Out_writes_bytes_opt_(*len) char **ptr, _Inout_ size_t *len, _Out_opt_ int *caller_frees) _Out_writes_bytes_opt_(*len) char **ptr, _Inout_ size_t *len, _Out_opt_ int *caller_frees)
#else
int pdo_sqlsrv_stmt_get_col_data(_Inout_ pdo_stmt_t *stmt, _In_ int colno, _Inout_ zval *result_z, _Inout_ enum pdo_param_type *type)
#endif
{ {
PDO_RESET_STMT_ERROR; PDO_RESET_STMT_ERROR;
PDO_VALIDATE_STMT; PDO_VALIDATE_STMT;
@ -739,39 +773,44 @@ int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno,
try { try {
SQLSRV_ASSERT( stmt != NULL, "pdo_sqlsrv_stmt_get_col_data: pdo_stmt object was null" ); SQLSRV_ASSERT(stmt != NULL, "pdo_sqlsrv_stmt_get_col_data: pdo_stmt object was null");
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);
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_get_col_data: driver_data object was null" ); SQLSRV_ASSERT(driver_stmt != NULL, "pdo_sqlsrv_stmt_get_col_data: driver_data object was null");
CHECK_CUSTOM_ERROR((colno < 0), driver_stmt, PDO_SQLSRV_ERROR_INVALID_COLUMN_INDEX ) { CHECK_CUSTOM_ERROR((colno < 0), driver_stmt, PDO_SQLSRV_ERROR_INVALID_COLUMN_INDEX) {
return 0; return 0;
} }
#if PHP_VERSION_ID < 80100
// Let PDO free the memory after use. // Let PDO free the memory after use.
*caller_frees = 1; * caller_frees = 1;
#endif
// 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");
// 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
// save the php type for next use // save the php type for next use
sqlsrv_php_type = driver_stmt->sql_type_to_php_type( sqlsrv_php_type = driver_stmt->sql_type_to_php_type(
static_cast<SQLINTEGER>(driver_stmt->current_meta_data[colno]->field_type), static_cast<SQLINTEGER>(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);
driver_stmt->current_meta_data[colno]->sqlsrv_php_type = sqlsrv_php_type; driver_stmt->current_meta_data[colno]->sqlsrv_php_type = sqlsrv_php_type;
// if a column is bound to a type different than the column type, figure out a way to convert it to the // if a column is bound to a type different than the column type, figure out a way to convert it to the
// type they want // type they want
if( stmt->bound_columns && driver_stmt->bound_column_param_types[colno] != PDO_PARAM_ZVAL ) { #if PHP_VERSION_ID < 80100
if (stmt->bound_columns && driver_stmt->bound_column_param_types[colno] != PDO_PARAM_ZVAL) {
sqlsrv_php_type.typeinfo.type = pdo_type_to_sqlsrv_php_type( driver_stmt, #else
driver_stmt->bound_column_param_types[colno] if (stmt->bound_columns) {
); #endif
sqlsrv_php_type.typeinfo.type = pdo_type_to_sqlsrv_php_type(driver_stmt,
driver_stmt->bound_column_param_types[colno]
);
pdo_bound_param_data* bind_data = NULL; pdo_bound_param_data* bind_data = NULL;
bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_index_find_ptr(stmt->bound_columns, colno)); bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_index_find_ptr(stmt->bound_columns, colno));
@ -780,30 +819,30 @@ int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno,
bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_find_ptr(stmt->bound_columns, stmt->columns[colno].name)); bind_data = reinterpret_cast<pdo_bound_param_data*>(zend_hash_find_ptr(stmt->bound_columns, stmt->columns[colno].name));
} }
if( bind_data != NULL && !Z_ISUNDEF(bind_data->driver_params) ) { if (bind_data != NULL && !Z_ISUNDEF(bind_data->driver_params)) {
CHECK_CUSTOM_ERROR( Z_TYPE( bind_data->driver_params ) != IS_LONG, driver_stmt, CHECK_CUSTOM_ERROR(Z_TYPE(bind_data->driver_params) != IS_LONG, driver_stmt,
PDO_SQLSRV_ERROR_INVALID_COLUMN_DRIVER_DATA, colno + 1 ) { PDO_SQLSRV_ERROR_INVALID_COLUMN_DRIVER_DATA, colno + 1) {
throw pdo::PDOException(); throw pdo::PDOException();
} }
CHECK_CUSTOM_ERROR( driver_stmt->bound_column_param_types[colno] != PDO_PARAM_STR CHECK_CUSTOM_ERROR(driver_stmt->bound_column_param_types[colno] != PDO_PARAM_STR
&& driver_stmt->bound_column_param_types[colno] != PDO_PARAM_LOB, driver_stmt, && driver_stmt->bound_column_param_types[colno] != PDO_PARAM_LOB, driver_stmt,
PDO_SQLSRV_ERROR_COLUMN_TYPE_DOES_NOT_SUPPORT_ENCODING, colno + 1 ) { PDO_SQLSRV_ERROR_COLUMN_TYPE_DOES_NOT_SUPPORT_ENCODING, colno + 1) {
throw pdo::PDOException(); throw pdo::PDOException();
} }
sqlsrv_php_type.typeinfo.encoding = Z_LVAL( bind_data->driver_params ); sqlsrv_php_type.typeinfo.encoding = Z_LVAL(bind_data->driver_params);
switch( sqlsrv_php_type.typeinfo.encoding ) { switch (sqlsrv_php_type.typeinfo.encoding) {
case SQLSRV_ENCODING_SYSTEM: case SQLSRV_ENCODING_SYSTEM:
case SQLSRV_ENCODING_BINARY: case SQLSRV_ENCODING_BINARY:
case SQLSRV_ENCODING_UTF8: case SQLSRV_ENCODING_UTF8:
break; break;
default: default:
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_DRIVER_COLUMN_ENCODING, colno ); THROW_PDO_ERROR(driver_stmt, PDO_SQLSRV_ERROR_INVALID_DRIVER_COLUMN_ENCODING, colno);
break; break;
} }
} }
@ -812,8 +851,9 @@ int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno,
} }
SQLSRV_PHPTYPE sqlsrv_phptype_out = SQLSRV_PHPTYPE_INVALID; SQLSRV_PHPTYPE sqlsrv_phptype_out = SQLSRV_PHPTYPE_INVALID;
core_sqlsrv_get_field( driver_stmt, colno, sqlsrv_php_type, false, *(reinterpret_cast<void**>(ptr)), #if PHP_VERSION_ID < 80100
reinterpret_cast<SQLLEN*>( len ), true, &sqlsrv_phptype_out ); core_sqlsrv_get_field(driver_stmt, colno, sqlsrv_php_type, false, *(reinterpret_cast<void**>(ptr)),
reinterpret_cast<SQLLEN*>(len), true, &sqlsrv_phptype_out);
if (ptr) { if (ptr) {
zval* zval_ptr = reinterpret_cast<zval*>(sqlsrv_malloc(sizeof(zval))); zval* zval_ptr = reinterpret_cast<zval*>(sqlsrv_malloc(sizeof(zval)));
@ -821,7 +861,14 @@ int pdo_sqlsrv_stmt_get_col_data( _Inout_ pdo_stmt_t *stmt, _In_ int colno,
*ptr = reinterpret_cast<char*>(zval_ptr); *ptr = reinterpret_cast<char*>(zval_ptr);
*len = sizeof(zval); *len = sizeof(zval);
} }
#else
SQLLEN len = 0;
void *ptr = NULL;
core_sqlsrv_get_field(driver_stmt, colno, sqlsrv_php_type, false, ptr, &len, true, &sqlsrv_phptype_out);
if (ptr) {
*result_z = convert_to_zval(driver_stmt, sqlsrv_phptype_out, &ptr, len);
}
#endif
return 1; return 1;
} }
catch ( core::CoreException& ) { catch ( core::CoreException& ) {
@ -1114,9 +1161,15 @@ int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno
&out_buff_len, &field_type_num ); &out_buff_len, &field_type_num );
add_assoc_string( return_value, "table", table_name ); add_assoc_string( return_value, "table", table_name );
#if PHP_VERSION_ID < 80100
if( stmt->columns && stmt->columns[colno].param_type == PDO_PARAM_ZVAL ) { if( stmt->columns && stmt->columns[colno].param_type == PDO_PARAM_ZVAL ) {
add_assoc_long( return_value, "pdo_type", pdo_type ); add_assoc_long( return_value, "pdo_type", pdo_type );
} }
#else
if (stmt->columns) {
add_assoc_long(return_value, "pdo_type", pdo_type);
}
#endif
} }
catch( core::CoreException& ) { catch( core::CoreException& ) {
zval_ptr_dtor(return_value); zval_ptr_dtor(return_value);

View file

@ -23,20 +23,20 @@ $stmt->debugDumpParams();
$stmt=null; $stmt=null;
$conn=null; $conn=null;
?> ?>
--EXPECT-- --EXPECTREGEX--
SQL: [52] select * from Person.ContactType where name = :param SQL: \[52\] select \* from Person.ContactType where name = \:param
Params: 1 Params: 1
Key: Name: [6] :param Key: Name: \[6\] :param
paramno=0 paramno=0
name=[6] ":param" name=\[6\] ":param"
is_param=1 is_param=1
param_type=2 param_type=(2|3)
SQL: [47] select * from Person.ContactType where name = ? SQL: \[47\] select \* from Person.ContactType where name = \?
Params: 1 Params: 1
Key: Position #0: Key: Position #0:
paramno=0 paramno=0
name=[0] "" name=\[0\] ""
is_param=1 is_param=1
param_type=2 param_type=(2|3)

View file

@ -19,24 +19,24 @@ print $metadata['name'];
$stmt = null; $stmt = null;
$conn = null; $conn = null;
?> ?>
--EXPECT-- --EXPECTREGEX--
array(8) { array\(8\) {
["flags"]=> \["flags"\]=>
int(0) int\(0\)
["sqlsrv:decl_type"]=> \["sqlsrv:decl_type"\]=>
string(8) "datetime" string\(8\) "datetime"
["native_type"]=> \["native_type"\]=>
string(6) "string" string\(6\) "string"
["table"]=> \["table"\]=>
string(0) "" string\(0\) ""
["pdo_type"]=> \["pdo_type"\]=>
int(2) int\((2|3)\)
["name"]=> \["name"\]=>
string(12) "ModifiedDate" string\(12\) "ModifiedDate"
["len"]=> \["len"\]=>
int(23) int\(23\)
["precision"]=> \["precision"\]=>
int(3) int\(3\)
} }
datetime datetime
string string

View file

@ -306,7 +306,7 @@ class BindParamOp
} }
if ($length >= 0 || is_null($length)) { if ($length >= 0 || is_null($length)) {
$this->length = $length; $this->length = is_null($length) ? 0 : $length;
} else { } else {
printf("BindParamOp construct: The length provided must be greater or equal to 0.\n"); printf("BindParamOp construct: The length provided must be greater or equal to 0.\n");
exit; exit;
@ -531,14 +531,11 @@ function fetchAll($conn, $tbname)
* @param string $fetchStyle : fetch_style argument passed to PDOStatement::fetchAll * @param string $fetchStyle : fetch_style argument passed to PDOStatement::fetchAll
* @return array rows in a result set * @return array rows in a result set
*/ */
function selectAll($conn, $tbname, $fetchStyle = null) function selectAll($conn, $tbname, $fetchStyle = PDO::FETCH_BOTH)
{ {
try { try {
$sql = "SELECT * FROM $tbname"; $sql = "SELECT * FROM $tbname";
$stmt = $conn->query($sql); $stmt = $conn->query($sql);
if ($fetchStyle) {
$fetchStyle = constant($fetchStyle);
}
$data = $stmt->fetchAll($fetchStyle); $data = $stmt->fetchAll($fetchStyle);
return $data; return $data;
} catch (PDOException $e) { } catch (PDOException $e) {
@ -1806,3 +1803,22 @@ function getTodayDateAsString($conn)
$row = $stmt->fetch(PDO::FETCH_NUM); $row = $stmt->fetch(PDO::FETCH_NUM);
return $row[0]; return $row[0];
} }
function compareResourceToInput($actual, $expected)
{
$size = 8192;
$pos = 0;
$matched = true;
while (!feof($actual)) {
$original = fread($actual, $size);
$str = substr($expected, $pos, $size);
if ($original !== $str) {
$matched = false;
break;
}
$pos += $size;
}
return $matched;
}

View file

@ -65,7 +65,7 @@ function insertNullsTest($bindType)
$stmt2->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_BINARY); $stmt2->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_BINARY);
$stmt2->bindValue(":p1", null, $bindType); $stmt2->bindValue(":p1", null, $bindType);
} elseif ($bindType == PDO::PARAM_STR) { } elseif ($bindType == PDO::PARAM_STR) {
$stmt2->bindParam(":p1", $outvar, $bindType, null, PDO::SQLSRV_ENCODING_BINARY); $stmt2->bindParam(":p1", $outvar, $bindType, 0, PDO::SQLSRV_ENCODING_BINARY);
} }
} else { } else {
$stmt2->bindParam(":p1", $outvar); $stmt2->bindParam(":p1", $outvar);

View file

@ -10,7 +10,7 @@ PHPT_EXEC=true
<?php <?php
include 'MsCommon.inc'; include 'MsCommon.inc';
function ReadOnly() function testReadOnly()
{ {
include 'MsSetup.inc'; include 'MsSetup.inc';
@ -62,7 +62,7 @@ function Repro()
try try
{ {
ReadOnly(); testReadOnly();
} }
catch (Exception $e) catch (Exception $e)
{ {

View file

@ -81,7 +81,7 @@ function Repro()
Repro(); Repro();
?> ?>
--EXPECT-- --EXPECTF--
array(8) { array(8) {
["flags"]=> ["flags"]=>
int(0) int(0)
@ -92,7 +92,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(2) "id" string(2) "id"
["len"]=> ["len"]=>
@ -110,7 +110,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(3) "val" string(3) "val"
["len"]=> ["len"]=>
@ -128,7 +128,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(4) "val2" string(4) "val2"
["len"]=> ["len"]=>
@ -146,7 +146,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(0) "" string(0) ""
["len"]=> ["len"]=>

View file

@ -61,8 +61,14 @@ function fetchLob($offset, $conn, $table, $sqlType, $data1, $data2)
if ($id != $data1) { if ($id != $data1) {
logInfo($offset, "ID data corruption: [$id] instead of [$data1]"); logInfo($offset, "ID data corruption: [$id] instead of [$data1]");
} }
if ($label != $data2) { if (PHP_VERSION_ID < 80100) {
logInfo($offset, "Label data corruption: [$label] instead of [$data2]"); if ($label != $data2) {
logInfo($offset, "Label data corruption: [$label] instead of [$data2]");
}
} else {
if (!compareResourceToInput($label, $data2)) {
logInfo($offset, "Label data corruption");
}
} }
unset($stmt); unset($stmt);
unset($label); unset($label);

View file

@ -42,7 +42,7 @@ try {
} }
// Get data // Get data
$row = selectAll($conn, $tableName, "PDO::FETCH_ASSOC"); $row = selectAll($conn, $tableName, PDO::FETCH_ASSOC);
var_dump($row); var_dump($row);
// Close connection // Close connection

View file

@ -29,7 +29,16 @@ try {
$stmt->bindColumn('Value', $val1, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY); $stmt->bindColumn('Value', $val1, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
$stmt->execute(); $stmt->execute();
$stmt->fetch(PDO::FETCH_BOUND); $stmt->fetch(PDO::FETCH_BOUND);
var_dump($val1 === $value);
if (PHP_VERSION_ID < 80100) {
var_dump($val1 === $value);
} else {
// $val1 is a stream object
if (!feof($val1)) {
$str = fread($val1, 8192);
var_dump($str === $value);
}
}
// Close connection // Close connection
dropTable($conn, $tableName); dropTable($conn, $tableName);

View file

@ -148,7 +148,16 @@ try {
$stmt->bindColumn('Value', $val1, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY); $stmt->bindColumn('Value', $val1, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
$stmt->execute(); $stmt->execute();
$stmt->fetch(PDO::FETCH_BOUND); $stmt->fetch(PDO::FETCH_BOUND);
var_dump($val1 === $value);
if (PHP_VERSION_ID < 80100) {
var_dump($val1 === $value);
} else {
// $val1 is a stream object
if (!feof($val1)) {
$str = fread($val1, 8192);
var_dump($str === $value);
}
}
// Close connection // Close connection
dropTable($conn, $tableName); dropTable($conn, $tableName);

View file

@ -57,7 +57,12 @@ try {
// Start testing quote function // Start testing quote function
$conn->setAttribute(PDO::ATTR_DEFAULT_STR_PARAM, PDO::PARAM_STR_CHAR); $conn->setAttribute(PDO::ATTR_DEFAULT_STR_PARAM, PDO::PARAM_STR_CHAR);
var_dump($conn->quote(null, PDO::PARAM_NULL)); // Deprecated: PDO::quote(): Passing null to parameter #1 ($string) of type string is being deprecated
if (PHP_VERSION_ID < 80100) {
var_dump($conn->quote(null, PDO::PARAM_NULL));
} else {
var_dump($conn->quote('', PDO::PARAM_NULL));
}
var_dump($conn->quote('\'', PDO::PARAM_STR)); var_dump($conn->quote('\'', PDO::PARAM_STR));
var_dump($conn->quote('foo', PDO::PARAM_STR)); var_dump($conn->quote('foo', PDO::PARAM_STR));
var_dump($conn->quote('foo', PDO::PARAM_STR | PDO::PARAM_STR_CHAR)); var_dump($conn->quote('foo', PDO::PARAM_STR | PDO::PARAM_STR_CHAR));

View file

@ -38,7 +38,7 @@ try {
} }
?> ?>
--EXPECT-- --EXPECTF--
array(8) { array(8) {
["flags"]=> ["flags"]=>
int(0) int(0)
@ -49,7 +49,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(6) "RESULT" string(6) "RESULT"
["len"]=> ["len"]=>

View file

@ -50,7 +50,23 @@ try {
var_dump($e->errorInfo); var_dump($e->errorInfo);
} }
//calls various fetch methods function verifyBinaryResult($result, $input, $len, $message)
{
if (PHP_VERSION_ID < 80100) {
if (strncmp($result, $input, $len) !== 0) {
print_r($message);
}
} else {
if (!feof($result)) {
$str = fread($result, $len);
if (strncmp($str, $input, $len) !== 0) {
print_r($message);
}
}
}
}
//calls various fetch methods
function testFetch($conn, $tableName, $columnName, $input) function testFetch($conn, $tableName, $columnName, $input)
{ {
$len = strlen($input); $len = strlen($input);
@ -60,17 +76,13 @@ function testFetch($conn, $tableName, $columnName, $input)
$stmt->bindColumn(1, $result, PDO::PARAM_LOB); $stmt->bindColumn(1, $result, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND); $stmt->fetch(PDO::FETCH_BOUND);
//binary is fixed size, to evaluate output, compare it using strncmp //binary is fixed size, to evaluate output, compare it using strncmp
if (strncmp($result, $input, $len) !== 0) { verifyBinaryResult($result, $input, $len, "\nRetrieving using bindColumn failed");
print_r("\nRetrieving using bindColumn failed");
}
$result = ""; $result = "";
$stmt = $conn->query($sql); $stmt = $conn->query($sql);
$stmt->bindColumn(1, $result, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY); $stmt->bindColumn(1, $result, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
$stmt->fetch(PDO::FETCH_BOUND); $stmt->fetch(PDO::FETCH_BOUND);
if (strncmp($result, $input, $len) !== 0) { verifyBinaryResult($result, $input, $len, "\nRetrieving using bindColumn with encoding set failed");
print_r("\nRetrieving using bindColumn with encoding set failed");
}
$result = ""; $result = "";
$stmt = $conn->query($sql); $stmt = $conn->query($sql);

View file

@ -45,9 +45,23 @@ try {
$stmt->bindColumn(2, $value, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_SYSTEM); $stmt->bindColumn(2, $value, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_SYSTEM);
$result = $stmt->fetch(PDO::FETCH_BOUND); $result = $stmt->fetch(PDO::FETCH_BOUND);
if (!$result || $value !== $input[1]) { if (PHP_VERSION_ID < 80100) {
echo "Expected $input[1] but got: "; if (!$result || $value !== $input[1]) {
var_dump($result); echo "Expected $input[1] but got: ";
var_dump($value);
}
} else {
if (!$result || !is_resource($value)) {
echo "Expected a stream resource but got: ";
var_dump($value);
}
if (!feof($value)) {
$str = fread($value, strlen($input[1]));
if ($str !== $input[1]) {
echo "Expected $input[1] but got: ";
var_dump($str);
}
}
} }
$stmt->bindColumn(2, $value, PDO::PARAM_STR); $stmt->bindColumn(2, $value, PDO::PARAM_STR);

View file

@ -79,7 +79,7 @@ unset($stmt);
unset($conn); unset($conn);
?> ?>
--EXPECT-- --EXPECTF--
Number of columns after UPDATE: 0 Number of columns after UPDATE: 0
array(8) { array(8) {
["flags"]=> ["flags"]=>
@ -91,7 +91,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(2) "id" string(2) "id"
["len"]=> ["len"]=>
@ -109,7 +109,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(4) "name" string(4) "name"
["len"]=> ["len"]=>

View file

@ -52,9 +52,15 @@ try {
if (!is_null($det) || !is_null($rand)) { if (!is_null($det) || !is_null($rand)) {
echo "Retrieving $typeFull data as $pdoParamType should not be supported\n"; echo "Retrieving $typeFull data as $pdoParamType should not be supported\n";
} }
// check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB // check the case when fetching as PDO::PARAM_STR
// with or without AE: should work // with or without AE: should work
} else { } else {
if (PHP_VERSION_ID >= 80100 && $pdoParamType == "PDO::PARAM_LOB") {
// Starting with PHP 8.1 fetching as PDO::PARAM_LOB will return a resource obj
$det = fread($det, 8192);
$rand = fread($rand, 8192);
}
if (trim($det) == $inputValues[0] && trim($rand) == $inputValues[1]) { if (trim($det) == $inputValues[0] && trim($rand) == $inputValues[1]) {
echo "****Retrieving $typeFull data as $pdoParamType is supported****\n"; echo "****Retrieving $typeFull data as $pdoParamType is supported****\n";
} else { } else {

View file

@ -53,6 +53,10 @@ try {
// check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB // check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB
// with or without AE: should work // with or without AE: should work
} else { } else {
if (PHP_VERSION_ID >= 80100 && is_resource($c1)) {
// Starting with PHP 8.1 fetching as PDO::PARAM_LOB will return a resource obj
$c1 = fread($c1, 8192);
}
if (strlen($c1) == $m) { if (strlen($c1) == $m) {
echo "****Retrieving $typeFull as $pdoParamType is supported****\n"; echo "****Retrieving $typeFull as $pdoParamType is supported****\n";
} else { } else {

View file

@ -47,6 +47,11 @@ try {
// only check if input values are part of fetched values because some input values do not contain any deicmal places, the value retrieved however has 3 decimal places if the type is a datetime // only check if input values are part of fetched values because some input values do not contain any deicmal places, the value retrieved however has 3 decimal places if the type is a datetime
// with or without AE: should work // with or without AE: should work
} else { } else {
if (PHP_VERSION_ID >= 80100 && $pdoParamType == "PDO::PARAM_LOB") {
// Starting with PHP 8.1 fetching as PDO::PARAM_LOB will return a resource obj
$det = fread($det, 8192);
$rand = fread($rand, 8192);
}
if (strpos($det, $inputValues[0]) !== false && strpos($rand, $inputValues[1]) !== false) { if (strpos($det, $inputValues[0]) !== false && strpos($rand, $inputValues[1]) !== false) {
echo "****Retrieving $dataType as $pdoParamType is supported****\n"; echo "****Retrieving $dataType as $pdoParamType is supported****\n";
} else { } else {

View file

@ -83,6 +83,11 @@ try {
// check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB // check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB
// with or without AE: should work // with or without AE: should work
} else { } else {
if (PHP_VERSION_ID >= 80100 && $pdoParamType == "PDO::PARAM_LOB") {
// Starting with PHP 8.1 fetching as PDO::PARAM_LOB will return a resource obj
$det = fread($det, 8192);
$rand = fread($rand, 8192);
}
if (compareDate($det, $inputValues[0], $dataType) && compareDate($rand, $inputValues[1], $dataType)) { if (compareDate($det, $inputValues[0], $dataType) && compareDate($rand, $inputValues[1], $dataType)) {
echo "****Retrieving $typeFull as $pdoParamType is supported****\n"; echo "****Retrieving $typeFull as $pdoParamType is supported****\n";
} else { } else {

View file

@ -114,6 +114,11 @@ try {
$succeeded = compareIntegers($pdoParamType, $det, $rand, $inputValues, $m1, $m2); $succeeded = compareIntegers($pdoParamType, $det, $rand, $inputValues, $m1, $m2);
} }
} else { } else {
if (PHP_VERSION_ID >= 80100 && $pdoParamType == "PDO::PARAM_LOB") {
// Starting with PHP 8.1 fetching as PDO::PARAM_LOB will return a resource obj
$det = fread($det, 8192);
$rand = fread($rand, 8192);
}
if (abs($det - $inputValues[0]) < $epsilon && if (abs($det - $inputValues[0]) < $epsilon &&
abs($rand - $inputValues[1]) < $epsilon) { abs($rand - $inputValues[1]) < $epsilon) {
$succeeded = true; $succeeded = true;

View file

@ -57,6 +57,12 @@ try {
echo "Retriving $typeFull data as $pdoParamType should return NULL\n"; echo "Retriving $typeFull data as $pdoParamType should return NULL\n";
} }
} else { } else {
if (PHP_VERSION_ID >= 80100 && $pdoParamType == "PDO::PARAM_LOB") {
// Starting with PHP 8.1 fetching as PDO::PARAM_LOB will return a resource obj
$det = fread($det, 8192);
$rand = fread($rand, 8192);
}
if (abs($det - $inputValues[0]) < $epsilon && abs($rand - $inputValues[1]) < $epsilon) { if (abs($det - $inputValues[0]) < $epsilon && abs($rand - $inputValues[1]) < $epsilon) {
echo "****Retrieving $typeFull as $pdoParamType is supported****\n"; echo "****Retrieving $typeFull as $pdoParamType is supported****\n";
} else { } else {

View file

@ -53,6 +53,10 @@ try {
// check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB // check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB
// with or without AE: should work // with or without AE: should work
} else { } else {
if (PHP_VERSION_ID >= 80100 && is_resource($c1)) {
// Starting with PHP 8.1 fetching as PDO::PARAM_LOB will return a resource obj
$c1 = fread($c1, 8192);
}
if (strlen($c1) == $m) { if (strlen($c1) == $m) {
echo "****Retrieving $typeFull as $pdoParamType is supported****\n"; echo "****Retrieving $typeFull as $pdoParamType is supported****\n";
} else { } else {

View file

@ -48,27 +48,41 @@ try {
} }
// check the case when fetching as PDO::PARAM_BOOL or PDO::PARAM_INT // check the case when fetching as PDO::PARAM_BOOL or PDO::PARAM_INT
// with or without AE: should only not work with bigint // with or without AE: should only not work with bigint
} else if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_INT") { } elseif ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_INT") {
if ($dataType == "bigint") { if ($dataType == "bigint") {
if (!is_null($det) || !is_null($rand)) { if (!is_null($det) || !is_null($rand)) {
echo "Retrieving $dataType data as $pdoParamType should not be supported\n"; echo "Retrieving $dataType data as $pdoParamType should not be supported\n";
} }
} else if ($dataType == "real") { } elseif (PHP_VERSION_ID >= 80100 && $pdoParamType == "PDO::PARAM_BOOL") {
if (abs($det - $inputValues[0]) < $epsilon && abs($rand - $inputValues[1]) < $epsilon) { if ($det == boolval($inputValues[0]) && $rand == boolval($inputValues[1])) {
echo "****Retrieving $dataType as $pdoParamType is supported****\n"; echo "****Retrieving $dataType as $pdoParamType is supported****\n";
} else { } else {
echo "Retrieving $dataType as $pdoParamType fails\n"; echo "Retrieving $dataType as $pdoParamType fails\n";
} }
} else { } else {
if ($det == $inputValues[0] && $rand == $inputValues[1]) { if ($dataType == "real") {
echo "****Retrieving $dataType as $pdoParamType is supported****\n"; if (abs($det - $inputValues[0]) < $epsilon && abs($rand - $inputValues[1]) < $epsilon) {
echo "****Retrieving $dataType as $pdoParamType is supported****\n";
} else {
echo "Retrieving $dataType as $pdoParamType fails\n";
}
} else { } else {
echo "Retrieving $dataType as $pdoParamType fails\n"; if ($det == $inputValues[0] && $rand == $inputValues[1]) {
echo "****Retrieving $dataType as $pdoParamType is supported****\n";
} else {
echo "Retrieving $dataType as $pdoParamType fails\n";
}
} }
} }
// check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_INT, PDO::PARAM_STR or PDO::PARAM_LOB // check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_INT, PDO::PARAM_STR or PDO::PARAM_LOB
// with or without AE: should work // with or without AE: should work
} else { } else {
if ($pdoParamType == "PDO::PARAM_LOB") {
if (PHP_VERSION_ID >= 80100) {
$det = fread($det, 8192);
$rand = fread($rand, 8192);
}
}
if ($dataType == "real") { if ($dataType == "real") {
if (abs($det - $inputValues[0]) < $epsilon && abs($rand - $inputValues[1]) < $epsilon) { if (abs($det - $inputValues[0]) < $epsilon && abs($rand - $inputValues[1]) < $epsilon) {
echo "****Retrieving $dataType as $pdoParamType is supported****\n"; echo "****Retrieving $dataType as $pdoParamType is supported****\n";

View file

@ -129,8 +129,14 @@ function fetchBinaryAsBinary($conn, $tableName, $inputs)
$stmt->bindColumn('c1', $binaryValue, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY); $stmt->bindColumn('c1', $binaryValue, PDO::PARAM_LOB, 0, PDO::SQLSRV_ENCODING_BINARY);
$row = $stmt->fetch(PDO::FETCH_BOUND); $row = $stmt->fetch(PDO::FETCH_BOUND);
if ($binaryValue !== $inputs[0]) { if (PHP_VERSION_ID < 80100) {
echo "Fetched binary value unexpected: $binaryValue\n"; if ($binaryValue !== $inputs[0]) {
echo "Fetched binary value unexpected: $binaryValue\n";
}
} else {
if (!compareResourceToInput($binaryValue, $inputs[0])) {
echo "Fetched binary value unexpected\n";
}
} }
} catch (PdoException $e) { } catch (PdoException $e) {
echo "Caught exception in fetchBinaryAsBinary:\n"; echo "Caught exception in fetchBinaryAsBinary:\n";

View file

@ -50,7 +50,8 @@ function testConnAttrCases()
$conn = new PDO($dsn, $uid, $pwd, $attr); $conn = new PDO($dsn, $uid, $pwd, $attr);
$conn->getAttribute(PDO::SQLSRV_ATTR_DATA_CLASSIFICATION); $conn->getAttribute(PDO::SQLSRV_ATTR_DATA_CLASSIFICATION);
} catch (PDOException $e) { } catch (PDOException $e) {
if (!fnmatch($noSupportErr, $e->getMessage())) { $expected = (PHP_VERSION_ID < 80100) ? $noSupportErr : $stmtErr;
if (!fnmatch($expected, $e->getMessage())) {
echo "Connection attribute test (3) unexpected\n"; echo "Connection attribute test (3) unexpected\n";
var_dump($e->getMessage()); var_dump($e->getMessage());
} }

View file

@ -52,7 +52,8 @@ function testConnAttrCases()
$conn = new PDO($dsn, $uid, $pwd, $attr); $conn = new PDO($dsn, $uid, $pwd, $attr);
$conn->getAttribute(PDO::SQLSRV_ATTR_DATA_CLASSIFICATION); $conn->getAttribute(PDO::SQLSRV_ATTR_DATA_CLASSIFICATION);
} catch (PDOException $e) { } catch (PDOException $e) {
if (!fnmatch($noSupportErr, $e->getMessage())) { $expected = (PHP_VERSION_ID < 80100) ? $noSupportErr : $stmtErr;
if (!fnmatch($expected, $e->getMessage())) {
echo "Connection attribute test (3) unexpected\n"; echo "Connection attribute test (3) unexpected\n";
var_dump($e->getMessage()); var_dump($e->getMessage());
} }

View file

@ -30,6 +30,9 @@ try {
$stmt->execute(); $stmt->execute();
$stmt->bindColumn('exist', $float_col, PDO::PARAM_LOB); $stmt->bindColumn('exist', $float_col, PDO::PARAM_LOB);
$value = $stmt->fetch(); $value = $stmt->fetch();
if (PHP_VERSION_ID >= 80100) {
$float_col = fread($float_col, 8192);
}
var_dump($float_col); var_dump($float_col);
print "\nno buffered cursor, stringify off, fetch_numeric on\n"; print "\nno buffered cursor, stringify off, fetch_numeric on\n";
@ -38,6 +41,9 @@ try {
$stmt->execute(); $stmt->execute();
$stmt->bindColumn('exist', $float_col, PDO::PARAM_LOB); $stmt->bindColumn('exist', $float_col, PDO::PARAM_LOB);
$value = $stmt->fetch(); $value = $stmt->fetch();
if (PHP_VERSION_ID >= 80100) {
$float_col = fread($float_col, 8192);
}
var_dump($float_col); var_dump($float_col);
print "\nno buffered cursor, stringify on, fetch_numeric on\n"; print "\nno buffered cursor, stringify on, fetch_numeric on\n";
@ -63,6 +69,9 @@ try {
$stmt->execute(); $stmt->execute();
$stmt->bindColumn('exist', $float_col, PDO::PARAM_LOB); $stmt->bindColumn('exist', $float_col, PDO::PARAM_LOB);
$value = $stmt->fetch(); $value = $stmt->fetch();
if (PHP_VERSION_ID >= 80100) {
$float_col = fread($float_col, 8192);
}
var_dump($float_col); var_dump($float_col);
print "\nbuffered cursor, stringify off, fetch_numeric on\n"; print "\nbuffered cursor, stringify off, fetch_numeric on\n";
@ -71,6 +80,9 @@ try {
$stmt->execute(); $stmt->execute();
$stmt->bindColumn('exist', $float_col, PDO::PARAM_LOB); $stmt->bindColumn('exist', $float_col, PDO::PARAM_LOB);
$value = $stmt->fetch(); $value = $stmt->fetch();
if (PHP_VERSION_ID >= 80100) {
$float_col = fread($float_col, 8192);
}
var_dump($float_col); var_dump($float_col);
print "\nbuffered cursor, stringify on, fetch_numeric on\n"; print "\nbuffered cursor, stringify on, fetch_numeric on\n";

View file

@ -135,7 +135,12 @@ function runTest($conn, $query, $columns, $values, $useBuffer = false)
// Setting it to true only converts numeric values to strings when fetching // Setting it to true only converts numeric values to strings when fetching
// See http://www.php.net/manual/en/pdo.setattribute.php for details // See http://www.php.net/manual/en/pdo.setattribute.php for details
// stringify on, fetch_numeric off, fetch_datetime on // stringify on, fetch_numeric off, fetch_datetime on
$conn->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); if (PHP_VERSION_ID < 80100) {
// TODO: starting in PHP 8.1 with ATTR_STRINGIFY_FETCHES set to true
// this fails with this error from PHP:
// Fatal error: Uncaught Error: Object of class DateTime could not be converted to string
$conn->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
}
$conn->setAttribute(PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE, false); $conn->setAttribute(PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE, false);
$conn->setAttribute(PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE, true); $conn->setAttribute(PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE, true);
$stmt = $conn->prepare($query, $options); $stmt = $conn->prepare($query, $options);
@ -253,11 +258,7 @@ try {
$query = "INSERT INTO $tableName VALUES(?, ?, ?, ?, ?, ?)"; $query = "INSERT INTO $tableName VALUES(?, ?, ?, ?, ?, ?)";
$stmt = $conn->prepare($query); $stmt = $conn->prepare($query);
for ($i = 0; $i < count($columns); $i++) {
// Bind the first param using the PHP DateTime object
$today = date_create($values[0]);
$stmt->bindParam(1, $today, PDO::PARAM_LOB);
for ($i = 1; $i < count($columns); $i++) {
$stmt->bindParam($i+1, $values[$i], PDO::PARAM_LOB); $stmt->bindParam($i+1, $values[$i], PDO::PARAM_LOB);
} }
$stmt->execute(); $stmt->execute();

View file

@ -23,6 +23,9 @@ $nstrValue = str_repeat("ÃÜðßZZýA©", 200);
function checkData($actual, $expected) function checkData($actual, $expected)
{ {
if (PHP_VERSION_ID >= 80100 && is_resource($actual)) {
$actual = fread($actual, 8192);
}
trace("Actual:\n$actual\n"); trace("Actual:\n$actual\n");
$success = true; $success = true;

View file

@ -7,12 +7,33 @@ Test getting invalid attributes
require_once("MsCommon_mid-refactor.inc"); require_once("MsCommon_mid-refactor.inc");
// When testing with PHP 8.1-dev, pdo_sqlsrv handles unsupported attribute differently.
// Implement a custom warning handler such that this test works with previous PHP versions as well.
function warningHandler($errno, $errstr)
{
$warning = "Driver does not support this function: driver does not support that attribute";
$str = strstr($errstr, $warning);
if ($str == false) {
echo "Unexpected warning message:";
var_dump($errstr);
}
}
try { try {
$conn = connect("", array(), PDO::ERRMODE_SILENT); $conn = connect("", array(), PDO::ERRMODE_SILENT);
set_error_handler("warningHandler", E_WARNING);
@$conn->getAttribute(PDO::ATTR_FETCH_TABLE_NAMES); @$conn->getAttribute(PDO::ATTR_FETCH_TABLE_NAMES);
print_r(($conn->errorInfo())[2]);
echo "\n"; // Starting with PHP 8.1-dev getting an unsupported attribute pdo_sqlsrv will no longer
// throw an exception. PHP PDO will handle the warning instead.
if (PHP_VERSION_ID < 80100) {
$errmsg = ($conn->errorInfo())[2];
if ($errmsg !== "An unsupported attribute was designated on the PDO object.") {
var_dump($conn->errorInfo());
}
}
restore_error_handler();
@$conn->getAttribute(PDO::ATTR_CURSOR); @$conn->getAttribute(PDO::ATTR_CURSOR);
print_r(($conn->errorInfo())[2]); print_r(($conn->errorInfo())[2]);
@ -26,6 +47,5 @@ try {
} }
?> ?>
--EXPECT-- --EXPECT--
An unsupported attribute was designated on the PDO object.
The given attribute is only supported on the PDOStatement object. The given attribute is only supported on the PDOStatement object.
An invalid attribute was designated on the PDO object. An invalid attribute was designated on the PDO object.

View file

@ -26,7 +26,7 @@ try {
$insertSql = "INSERT INTO $tableName (c1) VALUES (?)"; $insertSql = "INSERT INTO $tableName (c1) VALUES (?)";
$stmt = $conn->prepare($insertSql); $stmt = $conn->prepare($insertSql);
$stmt->bindParam(1, $invalidUTF16, PDO::PARAM_STR, null, PDO::SQLSRV_ENCODING_BINARY); $stmt->bindParam(1, $invalidUTF16, PDO::PARAM_STR, 0, PDO::SQLSRV_ENCODING_BINARY);
$stmt->execute(); $stmt->execute();
try { try {

View file

@ -40,7 +40,7 @@ try {
?> ?>
--EXPECT-- --EXPECTREGEX--
string(3) "200" string\(3\) "200"
string(3) "102" string\(3\) "102"
string(0) "" (string\(0\) ""|bool\(false\))

View file

@ -6,7 +6,7 @@ prepare with emulate prepare and binding uft8 characters
<?php <?php
require_once('MsCommon_mid-refactor.inc'); require_once('MsCommon_mid-refactor.inc');
function prepareStmt($conn, $query, $prepareOptions = array(), $dataType = null, $length = null, $driverOptions = null) function prepareStmt($conn, $query, $prepareOptions = array(), $dataType = PDO::PARAM_STR, $length = 0, $driverOptions = null)
{ {
$name = "가각"; $name = "가각";
if (!isColEncrypted()) { if (!isColEncrypted()) {

View file

@ -4,12 +4,38 @@ Test warnings on connection and statement levels
<?php require('skipif_mid-refactor.inc'); ?> <?php require('skipif_mid-refactor.inc'); ?>
--FILE-- --FILE--
<?php <?php
$counter = 0;
// When testing with PHP 8.1-dev it throws different warning messages. Implement a custom
// warning handler such that when testing with previous PHP versions, the warnings are
// handled and verified differently.
function warningHandler($errno, $errstr)
{
global $counter;
$warnings = array("An unsupported attribute was designated on the PDO object.",
"Driver does not support this function: driver does not support that attribute");
if (PHP_VERSION_ID < 80100) {
$str = strstr($errstr, $warnings[$counter++]);
} else {
$str = strstr($errstr, $warnings[1]);
}
if ($str == false) {
echo "Unexpected warning message ($counter):";
var_dump($errstr);
}
}
try { try {
require_once("MsCommon_mid-refactor.inc"); require_once("MsCommon_mid-refactor.inc");
set_error_handler("warningHandler", E_WARNING);
$conn = connect("", array(), PDO::ERRMODE_WARNING); $conn = connect("", array(), PDO::ERRMODE_WARNING);
// raise a warning in connection // raise a warning in connection
$conn->getAttribute(PDO::ATTR_TIMEOUT); $conn->getAttribute(PDO::ATTR_TIMEOUT);
restore_error_handler();
$tbname = "table1"; $tbname = "table1";
dropTable($conn, $tbname); dropTable($conn, $tbname);
@ -22,15 +48,7 @@ try {
unset($conn); unset($conn);
} catch (PDOException $e) { } catch (PDOException $e) {
var_dump($e->errorInfo); var_dump($e->errorInfo);
exit;
} }
?> ?>
--EXPECTREGEX-- --EXPECTREGEX--
Warning: SQLSTATE: IMSSP
Error Code: -38
Error Message: An unsupported attribute was designated on the PDO object\.
in .+(\/|\\)pdo_warnings\.php on line [0-9]+
Warning: PDO::getAttribute\(\): SQLSTATE\[IM001\]: Driver does not support this function: driver does not support that attribute in .+(\/|\\)pdo_warnings\.php on line [0-9]+
Warning: PDOStatement::execute\(\): SQLSTATE\[42000\]: Syntax error or access violation: 156 \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]Incorrect syntax near the keyword 'TABLE'\. in .+(\/|\\)pdo_warnings\.php on line [0-9]+ Warning: PDOStatement::execute\(\): SQLSTATE\[42000\]: Syntax error or access violation: 156 \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]\[SQL Server\]Incorrect syntax near the keyword 'TABLE'\. in .+(\/|\\)pdo_warnings\.php on line [0-9]+

View file

@ -111,8 +111,10 @@ function bindPARAM_NULL($db, $tbname)
$query = "UPDATE PDO_AllTypes SET [BitCol]=:Name WHERE [VarcharCol]=:value"; $query = "UPDATE PDO_AllTypes SET [BitCol]=:Name WHERE [VarcharCol]=:value";
$stmt = $db->prepare($query, array(PDO::ATTR_CURSOR=>PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE=>PDO::SQLSRV_CURSOR_BUFFERED)); $stmt = $db->prepare($query, array(PDO::ATTR_CURSOR=>PDO::CURSOR_SCROLL, PDO::SQLSRV_ATTR_CURSOR_SCROLL_TYPE=>PDO::SQLSRV_CURSOR_BUFFERED));
fwrite($noteID, null); // PHP Deprecated: fwrite(): Passing null to parameter #2 ($data) of type string is deprecated
rewind($noteID); // Also, it is not necessary for this test
// fwrite($noteID, null);
// rewind($noteID);
$stmt->bindParam(':Name', $noteID, PDO::PARAM_NULL); $stmt->bindParam(':Name', $noteID, PDO::PARAM_NULL);
$stmt->bindParam(':value', $data); $stmt->bindParam(':value', $data);
$stmt->execute(); $stmt->execute();

View file

@ -28,16 +28,16 @@ try {
var_dump($e); var_dump($e);
} }
?> ?>
--EXPECT-- --EXPECTF--
SQL: [79] SELECT IntCol FROM PDO_AllTypes WHERE BigIntCol = :bigint AND CharCol = :string SQL: [79] SELECT IntCol FROM PDO_AllTypes WHERE BigIntCol = :bigint AND CharCol = :string
Params: 2 Params: 2
Key: Name: [7] :bigint Key: Name: [7] :bigint
paramno=0 paramno=0
name=[7] ":bigint" name=[7] ":bigint"
is_param=1 is_param=1
param_type=1 param_type=%d
Key: Name: [7] :string Key: Name: [7] :string
paramno=1 paramno=1
name=[7] ":string" name=[7] ":string"
is_param=1 is_param=1
param_type=2 param_type=%d

View file

@ -185,7 +185,7 @@ try {
} }
?> ?>
--EXPECT-- --EXPECTF--
SQLSTATE[IMSSP]: The given attribute is only supported on the PDOStatement object. SQLSTATE[IMSSP]: The given attribute is only supported on the PDOStatement object.
SQLSTATE[IMSSP]: An invalid attribute was designated on the PDOStatement object. SQLSTATE[IMSSP]: An invalid attribute was designated on the PDOStatement object.
Start inserting data... Start inserting data...
@ -271,7 +271,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(6) "Budget" string(6) "Budget"
["len"]=> ["len"]=>

View file

@ -94,7 +94,7 @@ try {
?> ?>
--EXPECT-- --EXPECTF--
array(8) { array(8) {
["flags"]=> ["flags"]=>
@ -106,7 +106,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(6) "IntCol" string(6) "IntCol"
["len"]=> ["len"]=>
@ -124,7 +124,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(7) "CharCol" string(7) "CharCol"
["len"]=> ["len"]=>
@ -142,7 +142,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(8) "NCharCol" string(8) "NCharCol"
["len"]=> ["len"]=>
@ -160,7 +160,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(11) "DateTimeCol" string(11) "DateTimeCol"
["len"]=> ["len"]=>
@ -178,7 +178,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(10) "VarcharCol" string(10) "VarcharCol"
["len"]=> ["len"]=>
@ -196,7 +196,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(11) "NVarCharCol" string(11) "NVarCharCol"
["len"]=> ["len"]=>
@ -214,7 +214,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(8) "FloatCol" string(8) "FloatCol"
["len"]=> ["len"]=>
@ -230,7 +230,7 @@ array(7) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(6) "XmlCol" string(6) "XmlCol"
["len"]=> ["len"]=>

View file

@ -133,7 +133,7 @@ try {
exit; exit;
} }
?> ?>
--EXPECT-- --EXPECTF--
array(8) { array(8) {
["flags"]=> ["flags"]=>
@ -145,7 +145,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(12) "此是後話" string(12) "此是後話"
["len"]=> ["len"]=>
@ -163,7 +163,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(29) "Κοντάוְאַתָּה第" string(29) "Κοντάוְאַתָּה第"
["len"]=> ["len"]=>
@ -181,7 +181,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(30) "NΚοντάוְאַתָּה第" string(30) "NΚοντάוְאַתָּה第"
["len"]=> ["len"]=>
@ -199,7 +199,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(38) "ნომინავიiałopioБун" string(38) "ნომინავიiałopioБун"
["len"]=> ["len"]=>
@ -217,7 +217,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(10) "VarcharCol" string(10) "VarcharCol"
["len"]=> ["len"]=>
@ -235,7 +235,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(33) "NVarΚοντάוְאַתָּה第" string(33) "NVarΚοντάוְאַתָּה第"
["len"]=> ["len"]=>
@ -253,7 +253,7 @@ array(8) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(8) "FloatCol" string(8) "FloatCol"
["len"]=> ["len"]=>
@ -269,7 +269,7 @@ array(7) {
["table"]=> ["table"]=>
string(0) "" string(0) ""
["pdo_type"]=> ["pdo_type"]=>
int(2) int(%d)
["name"]=> ["name"]=>
string(6) "XmlCol" string(6) "XmlCol"
["len"]=> ["len"]=>

View file

@ -74,7 +74,7 @@ class ColumnMeta
$unsupported = array("xml", "timestamp", "image", "ntext", "text", "sql_variant", "hierarchyid", "geography", "geometry", "alias"); $unsupported = array("xml", "timestamp", "image", "ntext", "text", "sql_variant", "hierarchyid", "geography", "geometry", "alias");
if (stripos($this->options, "identity") !== false) { if (!is_null($this->options) && stripos($this->options, "identity") !== false) {
$this->encryptable = false; $this->encryptable = false;
} elseif (in_array(strtolower($this->dataType), $unsupported)) { } elseif (in_array(strtolower($this->dataType), $unsupported)) {
$this->encryptable = false; $this->encryptable = false;
@ -180,7 +180,7 @@ class BindParamOption
$scal = $prec_scal[1]; $scal = $prec_scal[1];
$size = null; $size = null;
} }
if (strpos($size, "max") !== false) { if (!is_null($size) && strpos($size, "max") !== false) {
$size = trim($size, "'"); $size = trim($size, "'");
} }
} }
@ -794,15 +794,14 @@ function getInsertData($rowIndex, $colIndex)
if (empty($inputArray)) { if (empty($inputArray)) {
fatalError("getInsertData: failed to retrieve data at row $rowIndex.\n"); fatalError("getInsertData: failed to retrieve data at row $rowIndex.\n");
} }
$count = 0;
foreach ($inputArray as $key => $value) { $key = getColName($colIndex);
if (++$count == $colIndex) { if (!empty($key)) {
if (is_array($value)) { $value = $inputArray[$key];
return $value[0]; if (is_array($value)) {
} else { return $value[0];
return $value; } else {
} return $value;
break;
} }
} }
@ -988,11 +987,7 @@ function isUnicode($k)
function isUpdatable($k) function isUpdatable($k)
{ {
switch ($k) { return ($k != 27); // timestamp
case 27: return (false); // timestamp
default: break;
}
return (true);
} }
function isLiteral($k) function isLiteral($k)

View file

@ -37,7 +37,7 @@ function deleteQuery()
trace("Deleting rows from $tableName ..."); trace("Deleting rows from $tableName ...");
$delRows = 1; $delRows = 1;
if (strlen($keyValue) == 0) { if (empty($keyValue)) {
$stmt2 = AE\executeQuery($conn1, "DELETE TOP(1) FROM [$tableName]"); $stmt2 = AE\executeQuery($conn1, "DELETE TOP(1) FROM [$tableName]");
$cond = "(top row)"; $cond = "(top row)";
} else { } else {

View file

@ -23,7 +23,7 @@ function fetchFields()
AE\createTestTable($conn1, $tableName); AE\createTestTable($conn1, $tableName);
$startRow = 1; $startRow = 1;
$noRows = 20; $noRows = 14; // 20;
AE\insertTestRowsByRange($conn1, $tableName, $startRow, $startRow + $noRows - 1); AE\insertTestRowsByRange($conn1, $tableName, $startRow, $startRow + $noRows - 1);
$query = "SELECT * FROM [$tableName] ORDER BY c27_timestamp"; $query = "SELECT * FROM [$tableName] ORDER BY c27_timestamp";
@ -49,8 +49,12 @@ function fetchFields()
if (isUpdatable($col)) { if (isUpdatable($col)) {
// should check data even if $fld is null // should check data even if $fld is null
$data = AE\getInsertData($startRow + $i, $col); $data = AE\getInsertData($startRow + $i, $col);
if (!checkData($col, $fld, $data)) { if (!checkData($col, $fld, $data, isBinary($col))) {
echo("\nData error\nExpected:\n$data\nActual:\n$fld\n"); // echo("\nData error\nExpected:\n$data\nActual:\n$fld\n");
echo("\nData error\nExpected:\n");
var_dump($data);
echo("\nActual:\n");
var_dump($fld);
setUTF8Data(false); setUTF8Data(false);
die("Data corruption on row ".($startRow + $i)." column $col"); die("Data corruption on row ".($startRow + $i)." column $col");
@ -66,10 +70,23 @@ function fetchFields()
sqlsrv_close($conn1); sqlsrv_close($conn1);
} }
function checkData($col, $actual, $expected) function checkData($col, $actual, $expected, $isBinary)
{ {
$success = true; $success = true;
// First check for nulls
if (is_null($expected)) {
$success = ($isBinary) ? empty($actual) : is_null($actual);
if (!$success) {
trace("\nData error\nExpected null but Actual:\n$actual\n");
}
return $success;
} elseif (is_null($actual)) {
trace("\nData error\nExpected:\n$expected\nbut Actual is null\n");
return false;
}
// Neither is null, so keep checking
if (isNumeric($col)) { if (isNumeric($col)) {
if (floatval($actual) != floatval($expected)) { if (floatval($actual) != floatval($expected)) {
$success = false; $success = false;

View file

@ -126,9 +126,17 @@ function checkData($row, $stmt, $index, $mode)
} }
} elseif (isBinary($col)) { } elseif (isBinary($col)) {
$expected = sqlsrv_get_field($stmt, $index, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)); $expected = sqlsrv_get_field($stmt, $index, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
$actual = bin2hex($actual); if (is_null($expected)) {
if (strcasecmp($actual, $expected) != 0) { $success = is_null($actual);
$success = false; } else {
if (is_null($actual)) {
$success = false;
} else {
$actual = bin2hex($actual);
if (strcasecmp($actual, $expected) != 0) {
$success = false;
}
}
} }
} else { // if (isChar($col)) } else { // if (isChar($col))
if (useUTF8Data()) { if (useUTF8Data()) {
@ -136,7 +144,9 @@ function checkData($row, $stmt, $index, $mode)
} else { } else {
$expected = sqlsrv_get_field($stmt, $index, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)); $expected = sqlsrv_get_field($stmt, $index, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
} }
if (strcmp($actual, $expected) != 0) { if (is_null($expected)) {
$success = is_null($actual);
} elseif (strcmp($actual, $expected) != 0) {
$success = false; $success = false;
} }
} }

View file

@ -86,15 +86,24 @@ function verifyStream($stmt, $row, $colIndex)
function checkData($col, $actual, $expected) function checkData($col, $actual, $expected)
{ {
if (is_null($expected)) {
return empty($actual);
}
$success = true; $success = true;
if (isBinary($col)) { if (isBinary($col)) {
$actual = bin2hex($actual); if (is_null($actual)) {
if (strncasecmp($actual, $expected, strlen($expected)) != 0) {
$success = false; $success = false;
} else {
$actual = bin2hex($actual);
if (strncasecmp($actual, $expected, strlen($expected)) != 0) {
$success = false;
}
} }
} else { } else {
if (strncasecmp($actual, $expected, strlen($expected)) != 0) { $len = (empty($expected)) ? 0 : strlen($expected);
if (strncasecmp($actual, $expected, $len) != 0) {
if ($col != 19) { // skip ntext if ($col != 19) { // skip ntext
$pos = strpos($actual, $expected); $pos = strpos($actual, $expected);
if (($pos === false) || ($pos > 1)) { if (($pos === false) || ($pos > 1)) {
@ -120,7 +129,8 @@ startTest($testName);
if (isLocaleSupported()) { if (isLocaleSupported()) {
try { try {
setUTF8Data(false); setUTF8Data(false);
streamRead(20, 1); // streamRead(20, 1);
streamRead(14, 1);
} catch (Exception $e) { } catch (Exception $e) {
echo $e->getMessage(); echo $e->getMessage();
} }
@ -132,7 +142,8 @@ startTest($testName);
try { try {
setUTF8Data(true); setUTF8Data(true);
resetLocaleToDefault(); resetLocaleToDefault();
streamRead(20, 1); // streamRead(20, 1);
streamRead(14, 1);
} catch (Exception $e) { } catch (Exception $e) {
echo $e->getMessage(); echo $e->getMessage();
} }

View file

@ -105,15 +105,24 @@ function verifyStream($stmt, $row, $colIndex)
function checkData($col, $actual, $expected) function checkData($col, $actual, $expected)
{ {
if (is_null($expected)) {
return empty($actual);
}
$success = true; $success = true;
if (isBinary($col)) { if (isBinary($col)) {
$actual = bin2hex($actual); if (is_null($actual)) {
if (strncasecmp($actual, $expected, strlen($expected)) != 0) {
$success = false; $success = false;
} else {
$actual = bin2hex($actual);
if (strncasecmp($actual, $expected, strlen($expected)) != 0) {
$success = false;
}
} }
} else { } else {
if (strncasecmp($actual, $expected, strlen($expected)) != 0) { $len = (empty($expected)) ? 0 : strlen($expected);
if (strncasecmp($actual, $expected, $len) != 0) {
if ($col != 19) { if ($col != 19) {
// skip ntext // skip ntext
$pos = strpos($actual, $expected); $pos = strpos($actual, $expected);
@ -143,7 +152,8 @@ startTest($testName);
if (isLocaleSupported()) { if (isLocaleSupported()) {
try { try {
setUTF8Data(false); setUTF8Data(false);
streamScroll(20, 1); // streamScroll(20, 1);
streamScroll(14, 1);
} catch (Exception $e) { } catch (Exception $e) {
echo $e->getMessage(); echo $e->getMessage();
} }
@ -155,7 +165,8 @@ startTest($testName);
try { try {
setUTF8Data(true); setUTF8Data(true);
resetLocaleToDefault(); resetLocaleToDefault();
streamScroll(20, 1); // streamScroll(20, 1);
streamScroll(14, 1);
} catch (Exception $e) { } catch (Exception $e) {
echo $e->getMessage(); echo $e->getMessage();
} }

View file

@ -25,13 +25,14 @@ if (!$stmt) {
} }
// insert new date time types as strings (this works now) // insert new date time types as strings (this works now)
$d1 = date_create();
$insertSql = "INSERT INTO [$tableName] (id, [c1_date], [c2_time], [c3_datetimeoffset], [c4_datetime2]) VALUES (?, ?, ?, ?, ?)"; $insertSql = "INSERT INTO [$tableName] (id, [c1_date], [c2_time], [c3_datetimeoffset], [c4_datetime2]) VALUES (?, ?, ?, ?, ?)";
$stmt = AE\executeQueryParams( $stmt = AE\executeQueryParams(
$conn, $conn,
$insertSql, $insertSql,
array(rand(0, 99999), array(rand(0, 99999),
array(strftime('%Y-%m-%d'), SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'), SQLSRV_SQLTYPE_DATE), array(date_format($d1, 'Y-m-d'), SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'), SQLSRV_SQLTYPE_DATE),
array(strftime('%H:%M:%S'), SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'), SQLSRV_SQLTYPE_TIME), array(date_format($d1, 'H:i:s'), SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'), SQLSRV_SQLTYPE_TIME),
array(date_format(date_create(), 'Y-m-d H:i:s.u P'), SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'), SQLSRV_SQLTYPE_DATETIMEOFFSET), array(date_format(date_create(), 'Y-m-d H:i:s.u P'), SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'), SQLSRV_SQLTYPE_DATETIMEOFFSET),
array(date_format(date_create(), 'Y-m-d H:i:s.u'), SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'), SQLSRV_SQLTYPE_DATETIME2)), array(date_format(date_create(), 'Y-m-d H:i:s.u'), SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING('utf-8'), SQLSRV_SQLTYPE_DATETIME2)),
false, false,
@ -61,10 +62,11 @@ $stmt = AE\executeQueryParams(
); );
// insert new date time types as strings with no type information (this works) // insert new date time types as strings with no type information (this works)
$d2 = date_create();
$stmt = AE\executeQueryParams( $stmt = AE\executeQueryParams(
$conn, $conn,
$insertSql, $insertSql,
array(rand(0, 99999), strftime('%Y-%m-%d'), strftime('%H:%M:%S'), date_format(date_create(), 'Y-m-d H:i:s.u P'), date_format(date_create(), 'Y-m-d H:i:s.u P')), array(rand(0, 99999), date_format($d2, 'Y-m-d'), date_format($d2, 'H:i:s'), date_format(date_create(), 'Y-m-d H:i:s.u P'), date_format(date_create(), 'Y-m-d H:i:s.u P')),
false, false,
"Insert 4 failed" "Insert 4 failed"
); );

View file

@ -60,7 +60,12 @@ function FetchAsStream_Binary()
function CompareValues($actual, $expected) function CompareValues($actual, $expected)
{ {
return (strncasecmp($actual, $expected, strlen($expected)) === 0); if (is_null($expected)) {
return (is_null($actual));
}
$len = (empty($expected)) ? 0 : strlen($expected);
return (strncasecmp($actual, $expected, $len) === 0);
} }
function GetQuery($tableName, $index) function GetQuery($tableName, $index)

View file

@ -218,7 +218,7 @@ function compareDataStream($colType, $rowIndex, $colName, $stream, $expected)
function compareBinaryData($actual, $expected) function compareBinaryData($actual, $expected)
{ {
// this function assumes $actual is a stream of hex // this function assumes $actual is a stream of hex
$len = strlen($expected); $len = (empty($expected)) ? 0 : strlen($expected);
$pos = 0; $pos = 0;
$matched = true; $matched = true;