Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

5.11.0 Release #1445

Merged
merged 5 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,33 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)

## 5.11.0 - 2023-02-28
Updated PECL release packages. Here is the list of updates:

### Added
- Support for PHP 8.2

### Removed
- Support for PHP 7.4

### Limitations
- No support for inout / output params when using sql_variant type
- No support for inout / output params when formatting decimal values
- In Linux and macOS, setlocale() only takes effect if it is invoked before the first connection. Attempting to set the locale after connecting will not work
- Always Encrypted requires [MS ODBC Driver 17+](https://docs.microsoft.com/sql/connect/odbc/linux-mac/installing-the-microsoft-odbc-driver-for-sql-server)
- Only Windows Certificate Store and Azure Key Vault are supported. Custom Keystores are not yet supported
- Issue [#716](https://github.com/Microsoft/msphpsql/issues/716) - With Always Encrypted enabled, named parameters in subqueries are not supported
- Issue [#1050](https://github.com/microsoft/msphpsql/issues/1050) - With Always Encrypted enabled, insertion requires the column list for any tables with identity columns
- [Always Encrypted limitations](https://docs.microsoft.com/sql/connect/php/using-always-encrypted-php-drivers#limitations-of-the-php-drivers-when-using-always-encrypted)

### Known Issues
- This release requires ODBC Driver 17.4.2 or above. Otherwise, a warning about failing to set an attribute may be suppressed when using an older ODBC driver.
- Connection pooling on Linux or macOS is not recommended with [unixODBC](http://www.unixodbc.org/) < 2.3.7
- When pooling is enabled in Linux or macOS
- unixODBC <= 2.3.4 (Linux and macOS) might not return proper diagnostic information, such as error messages, warnings and informative messages
- due to this unixODBC bug, fetch large data (such as xml, binary) as streams as a workaround. See the examples [here](https://github.com/Microsoft/msphpsql/wiki/Features#pooling)


## 5.11.0-beta1 - 2023-01-25
Updated PECL release packages. Here is the list of updates:

Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pr:
jobs:
- job: macOS
pool:
vmImage: 'macOS-10.15'
vmImage: 'macos-latest'
steps:
- checkout: self
clean: true
Expand Down
Binary file removed media/os_development.PNG
Binary file not shown.
Binary file removed media/os_production.PNG
Binary file not shown.
Binary file removed media/php_versions.PNG
Binary file not shown.
Binary file removed media/sql_server.PNG
Binary file not shown.
274 changes: 137 additions & 137 deletions source/pdo_sqlsrv/pdo_dbh.cpp

Large diffs are not rendered by default.

128 changes: 64 additions & 64 deletions source/pdo_sqlsrv/pdo_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@
// File: pdo_parser.cpp
//
// Contents: Implements a parser to parse the PDO DSN.
//
//
// Copyright Microsoft Corporation
//
// Microsoft Drivers 5.11 for PHP for SQL Server
// Copyright(c) Microsoft Corporation
// All rights reserved.
// MIT License
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
// to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//---------------------------------------------------------------------------------------------------------------------------------

Expand All @@ -34,7 +34,7 @@ conn_string_parser:: conn_string_parser( _In_ sqlsrv_context& ctx, _In_ const ch
this->pos = -1;
this->ctx = &ctx;
this->current_key = 0;
this->current_key_name = NULL;
this->current_key_name = NULL;
}

sql_string_parser:: sql_string_parser( _In_ sqlsrv_context& ctx, _In_ const char* sql_str, _In_ int len, _In_ HashTable* placeholders_ht )
Expand All @@ -55,16 +55,16 @@ inline bool string_parser::next( void )

return false;
}

SQLSRV_ASSERT( this->pos < len, "Unexpected cursor position in conn_string_parser::next" );

this->pos++;
this->pos++;

if ( this->is_eos() ) {

return false;
}

return true;
}

Expand All @@ -77,12 +77,12 @@ inline bool string_parser::is_eos( void )
}

SQLSRV_ASSERT(this->pos < len, "Unexpected cursor position in conn_string_parser::is_eos" );

return false;
}

// Check for white space.
inline bool string_parser::is_white_space( _In_ char c )
// Check for white space.
inline bool string_parser::is_white_space( _In_ char c )
{
if( c == ' ' || c == '\r' || c == '\n' || c == '\t' ) {
return true;
Expand All @@ -94,9 +94,9 @@ inline bool string_parser::is_white_space( _In_ char c )
int conn_string_parser::discard_trailing_white_spaces( _In_reads_(len) const char* str, _Inout_ int len )
{
const char* end = str + ( len - 1 );

while(( this->is_white_space( *end ) ) && (len > 0) ) {

len--;
end--;
}
Expand All @@ -108,16 +108,16 @@ int conn_string_parser::discard_trailing_white_spaces( _In_reads_(len) const cha
bool string_parser::discard_white_spaces()
{
if( this->is_eos() ) {

return false;
}

while( this->is_white_space( this->orig_str[pos] )) {

if( !next() )
return false;
}
}

return true;
}

Expand All @@ -128,22 +128,22 @@ void string_parser::add_key_value_pair( _In_reads_(len) const char* value, _In_
ZVAL_UNDEF( &value_z );

if( len == 0 ) {

ZVAL_STRINGL( &value_z, "", 0);
}
else {

ZVAL_STRINGL( &value_z, const_cast<char*>( value ), len );
}
}

core::sqlsrv_zend_hash_index_update( *ctx, this->element_ht, this->current_key, &value_z );
core::sqlsrv_zend_hash_index_update( *ctx, this->element_ht, this->current_key, &value_z );
}

// Add a key-value pair to the hashtable with int value
void sql_string_parser::add_key_int_value_pair( _In_ unsigned int value ) {
zval value_z;
ZVAL_LONG( &value_z, value );

core::sqlsrv_zend_hash_index_update( *ctx, this->element_ht, this->current_key, &value_z );
}

Expand All @@ -168,9 +168,9 @@ void conn_string_parser::validate_key( _In_reads_(key_len) const char *key, _Ino
key_name = static_cast<char*>( sqlsrv_malloc( new_len + 1 ));
memcpy_s( key_name, new_len + 1 ,key, new_len );

key_name[new_len] = '\0';
key_name[new_len] = '\0';

THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_KEY, static_cast<char*>( key_name ) );
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_KEY, static_cast<char*>( key_name ), NULL );
}

inline bool sql_string_parser::is_placeholder_char( char c )
Expand All @@ -183,25 +183,25 @@ inline bool sql_string_parser::is_placeholder_char( char c )
}

// Primary function which parses the connection string/DSN.
void conn_string_parser:: parse_conn_string( void )
void conn_string_parser:: parse_conn_string( void )
{
States state = FirstKeyValuePair; // starting state
int start_pos = -1;

try {

while( !this->is_eos() ) {

switch( state ) {

case FirstKeyValuePair:
{
// discard leading spaces
if( !next() || !discard_white_spaces() ) {

THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_STRING ); //EOS
}

state = Key;
break;
}
Expand All @@ -212,15 +212,15 @@ void conn_string_parser:: parse_conn_string( void )

// read the key name
while( this->orig_str[pos] != '=' ) {

if( !next() ) {

THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_DSN_STRING_ENDED_UNEXPECTEDLY ); //EOS
}
}

this->validate_key( &( this->orig_str[start_pos] ), ( pos - start_pos ) );

THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_DSN_STRING_ENDED_UNEXPECTEDLY ); //EOS
}
}

this->validate_key( &( this->orig_str[start_pos] ), ( pos - start_pos ) );

state = Value;

break;
Expand All @@ -239,23 +239,23 @@ void conn_string_parser:: parse_conn_string( void )
add_key_value_pair( NULL, 0 );

if( this->is_eos() ) {

break; // EOS
}
else {

// this->orig_str[pos] == ';'
// this->orig_str[pos] == ';'
state = NextKeyValuePair;
}
}

// if LCB
else if( this->orig_str[pos] == '{' ) {

start_pos = this->pos; // starting character is LCB
state = ValueContent1;
}

// If NonSP-LCB-SC
else {

Expand All @@ -269,10 +269,10 @@ void conn_string_parser:: parse_conn_string( void )
case ValueContent1:
{
while ( this->orig_str[pos] != '}' ) {

if ( ! next() ) {

THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_RCB_MISSING_IN_DSN_VALUE, this->current_key_name );
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_RCB_MISSING_IN_DSN_VALUE, this->current_key_name, NULL );
}
}

Expand All @@ -287,28 +287,28 @@ void conn_string_parser:: parse_conn_string( void )
while( this->orig_str[pos] != ';' ) {

if( ! next() ) {

break; //EOS
}
}

if( !this->is_eos() && this->orig_str[pos] == ';' ) {

// semi-colon encountered, so go to next key-value pair
state = NextKeyValuePair;
}

add_key_value_pair( &( this->orig_str[start_pos] ), this->pos - start_pos );
SQLSRV_ASSERT((( state == NextKeyValuePair ) || ( this->is_eos() )),

SQLSRV_ASSERT((( state == NextKeyValuePair ) || ( this->is_eos() )),
"conn_string_parser::parse_conn_string: Invalid state encountered " );

break;
}

case RCBEncountered:
{

// Read the next character after RCB.
if( !next() ) {

Expand All @@ -321,11 +321,11 @@ void conn_string_parser:: parse_conn_string( void )

// if second RCB encountered than go back to ValueContent1
if( this->orig_str[pos] == '}' ) {

if( !next() ) {

// EOS after a second RCB is error
THROW_PDO_ERROR( this->ctx, SQLSRV_ERROR_UNESCAPED_RIGHT_BRACE_IN_DSN, this->current_key_name );
THROW_PDO_ERROR( this->ctx, SQLSRV_ERROR_UNESCAPED_RIGHT_BRACE_IN_DSN, this->current_key_name, NULL );
}

state = ValueContent1;
Expand All @@ -336,9 +336,9 @@ void conn_string_parser:: parse_conn_string( void )

// discard any trailing white-spaces.
if( this->is_white_space( this->orig_str[pos] )) {

if( ! this->discard_white_spaces() ) {

//EOS
add_key_value_pair( &( this->orig_str[start_pos] ), end_pos - start_pos );
break;
Expand All @@ -347,32 +347,32 @@ void conn_string_parser:: parse_conn_string( void )

// if semi-colon than go to next key-value pair
if ( this->orig_str[pos] == ';' ) {

add_key_value_pair( &( this->orig_str[start_pos] ), end_pos - start_pos );
state = NextKeyValuePair;
break;
}

// Non - (RCB, SP*, SC, EOS) character. Any other character after an RCB is an error.
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_VALUE, this->current_key_name );
break;
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_VALUE, this->current_key_name, NULL );
break;
}
case NextKeyValuePair:
{
SQLSRV_ASSERT(( this->orig_str[pos] == ';' ),
SQLSRV_ASSERT(( this->orig_str[pos] == ';' ),
"conn_string_parser::parse_conn_string: semi-colon was expected." );

// Call next() to skip the semi-colon.
if( !next() || !this->discard_white_spaces() ) {

// EOS
break;
}

if( this->orig_str[pos] == ';' ) {

// a second semi-colon is error case.
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_EXTRA_SEMI_COLON_IN_DSN_STRING, this->pos );
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_EXTRA_SEMI_COLON_IN_DSN_STRING, this->pos, NULL );
}

else {
Expand All @@ -384,7 +384,7 @@ void conn_string_parser:: parse_conn_string( void )
} //case NextKeyValuePair
} // switch
} //while
}
}
catch( pdo::PDOException& ) {

throw;
Expand Down
Loading