Compare commits
33 commits
debian/lat
...
v5.11.0
Author | SHA1 | Date | |
---|---|---|---|
|
f6f76d4ac1 | ||
|
3cd248fba8 | ||
|
4ca08e5ca2 | ||
|
11509df4d3 | ||
|
e1eb5aa56b | ||
|
cf661d16fb | ||
|
d1980d3570 | ||
|
afdc9b6e8d | ||
|
ee5baccde4 | ||
|
d35c2b0f1b | ||
|
04266af58c | ||
|
ef10e75db8 | ||
|
86e3fbf466 | ||
|
cea2e8cc69 | ||
|
ffafa43095 | ||
|
2c606fe5d2 | ||
|
35bf2a6bbd | ||
|
c72e0eb166 | ||
|
e120fbc422 | ||
|
36b48f02c1 | ||
|
a5c7069b2e | ||
|
fd8457cd55 | ||
|
f764dc80ce | ||
|
93802526c0 | ||
|
efd594b8cf | ||
|
3a630fa8b0 | ||
|
9ffcb9cb2e | ||
|
15d25ceb76 | ||
|
4974fe4334 | ||
|
ed96718152 | ||
|
e2c15977ef | ||
|
25c8a200a5 | ||
|
b5f7469b02 |
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.vs
|
||||||
|
.vscode
|
||||||
|
__pycache__
|
||||||
|
*.diff
|
||||||
|
*.exp
|
||||||
|
*.log
|
||||||
|
*.sh
|
||||||
|
*.out
|
||||||
|
test/**/**/*.php
|
54
CHANGELOG.md
54
CHANGELOG.md
|
@ -3,6 +3,60 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
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:
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Support for PHP 8.2
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Pull request [#1408](https://github.com/microsoft/msphpsql/pull/1408) - Fixed right truncation issue, unit test added by talkinnl
|
||||||
|
|
||||||
|
### 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.10.1 - 2022-05-12
|
## 5.10.1 - 2022-05-12
|
||||||
Updated PECL release packages. Here is the list of updates:
|
Updated PECL release packages. Here is the list of updates:
|
||||||
|
|
||||||
|
|
10
README.md
10
README.md
|
@ -4,13 +4,13 @@
|
||||||
|
|
||||||
The [Microsoft Drivers for PHP for Microsoft SQL Server][phpdoc] are PHP extensions that allow for the reading and writing of SQL Server data from within PHP scripts. The SQLSRV extension provides a procedural interface while the PDO_SQLSRV extension implements PHP Data Objects (PDO) for accessing data in all editions of SQL Server 2012 and later (including Azure SQL DB). These drivers rely on the [Microsoft ODBC Driver for SQL Server][odbcdoc] to handle the low-level communication with SQL Server.
|
The [Microsoft Drivers for PHP for Microsoft SQL Server][phpdoc] are PHP extensions that allow for the reading and writing of SQL Server data from within PHP scripts. The SQLSRV extension provides a procedural interface while the PDO_SQLSRV extension implements PHP Data Objects (PDO) for accessing data in all editions of SQL Server 2012 and later (including Azure SQL DB). These drivers rely on the [Microsoft ODBC Driver for SQL Server][odbcdoc] to handle the low-level communication with SQL Server.
|
||||||
|
|
||||||
This release contains the SQLSRV and PDO_SQLSRV drivers for PHP 7.3+ with improvements on both drivers and some limitations. Upcoming [releases][releases] will contain additional functionalities, bug fixes, and more.
|
This release contains the SQLSRV and PDO_SQLSRV drivers for PHP 8.0+ with improvements on both drivers and some limitations. Upcoming [releases][releases] will contain additional functionalities, bug fixes, and more.
|
||||||
|
|
||||||
## Take our survey
|
## Take our survey
|
||||||
|
|
||||||
Thank you for taking the time to participate in the [sentiment survey](https://github.com/microsoft/msphpsql/wiki/Survey-Results). You can continue to help us improve by letting us know how we are doing and how you use [PHP][phpweb]:
|
Thank you for taking the time to participate in the [sentiment survey](https://github.com/microsoft/msphpsql/wiki/Survey-Results). You can continue to help us improve by letting us know how we are doing and how you use [PHP][phpweb]:
|
||||||
|
|
||||||
<a href="https://aka.ms/mssqlphpsurvey"><img style="float: right;" height="67" width="156" src="https://sqlchoice.blob.core.windows.net/sqlchoice/static/images/survey.png"></a>
|
[**Click here to start the PHP survey**](https://aka.ms/mssqlphpsurvey)
|
||||||
|
|
||||||
### Status of Most Recent Builds
|
### Status of Most Recent Builds
|
||||||
| Azure Pipelines (Linux) | AppVeyor (Windows) | Coverage (Windows) |
|
| Azure Pipelines (Linux) | AppVeyor (Windows) | Coverage (Windows) |
|
||||||
|
@ -37,8 +37,8 @@ Please follow the [Getting started](https://docs.microsoft.com/sql/connect/php/g
|
||||||
For full details on the system requirements for the drivers, see the [system requirements](https://docs.microsoft.com/sql/connect/php/system-requirements-for-the-php-sql-driver) on Microsoft Docs.
|
For full details on the system requirements for the drivers, see the [system requirements](https://docs.microsoft.com/sql/connect/php/system-requirements-for-the-php-sql-driver) on Microsoft Docs.
|
||||||
|
|
||||||
On the client machine:
|
On the client machine:
|
||||||
- 7.4.x, 8.0.x, 8.1.x
|
- 8.0.x, 8.1.x, 8.2.x
|
||||||
- [Microsoft ODBC Driver 17 or Microsoft ODBC Driver 13][odbcdoc]
|
- [Microsoft ODBC Driver 18, 17 or 13][odbcdoc]
|
||||||
- If using a Web server such as Internet Information Services (IIS) or Apache, it must be configured to run PHP
|
- If using a Web server such as Internet Information Services (IIS) or Apache, it must be configured to run PHP
|
||||||
|
|
||||||
On the server side, Microsoft SQL Server 2012 and above on Windows are supported, as are Microsoft SQL Server 2016 and above on Linux.
|
On the server side, Microsoft SQL Server 2012 and above on Windows are supported, as are Microsoft SQL Server 2016 and above on Linux.
|
||||||
|
@ -47,7 +47,7 @@ On the server side, Microsoft SQL Server 2012 and above on Windows are supported
|
||||||
|
|
||||||
The drivers are distributed as pre-compiled extensions for PHP found on the [releases page][releases]. They are available in thread-safe and non-thread-safe versions, and in 32-bit (Windows only) and 64-bit versions. The source code for the drivers is also available, and you can compile them as thread safe or non-thread-safe versions. The thread safety configuration of your web server will determine which version you need.
|
The drivers are distributed as pre-compiled extensions for PHP found on the [releases page][releases]. They are available in thread-safe and non-thread-safe versions, and in 32-bit (Windows only) and 64-bit versions. The source code for the drivers is also available, and you can compile them as thread safe or non-thread-safe versions. The thread safety configuration of your web server will determine which version you need.
|
||||||
|
|
||||||
If you choose to build the drivers, you must be able to build PHP 7.* or 8.* without including these extensions. For help building PHP on Windows, see the [official PHP website][phpbuild]. For details on compiling the drivers, see the [documentation](https://github.com/microsoft/msphpsql/blob/master/buildscripts/README.md) -- an example buildscript is provided, but you can also compile the drivers manually.
|
If you choose to build the drivers, you must be able to build PHP 8.* without including these extensions. For help building PHP on Windows, see the [official PHP website][phpbuild]. For details on compiling the drivers, see the [documentation](https://github.com/microsoft/msphpsql/blob/master/buildscripts/README.md) -- an example buildscript is provided, but you can also compile the drivers manually.
|
||||||
|
|
||||||
To load the drivers, make sure that the driver is in your PHP extension directory and enable it in your PHP installation's php.ini file by adding `extension=php_sqlsrv.dll` and/or `extension=php_pdo_sqlsrv.dll` to the ini file. If necessary, specify the extension directory using `extension_dir`, for example: `extension_dir = "C:\PHP\ext"`. Note that the precompiled binaries have different names -- substitute accordingly in php.ini. For more details on loading the drivers, see [Loading the PHP SQL Driver](https://docs.microsoft.com/sql/connect/php/loading-the-php-sql-driver) on Microsoft Docs.
|
To load the drivers, make sure that the driver is in your PHP extension directory and enable it in your PHP installation's php.ini file by adding `extension=php_sqlsrv.dll` and/or `extension=php_pdo_sqlsrv.dll` to the ini file. If necessary, specify the extension directory using `extension_dir`, for example: `extension_dir = "C:\PHP\ext"`. Note that the precompiled binaries have different names -- substitute accordingly in php.ini. For more details on loading the drivers, see [Loading the PHP SQL Driver](https://docs.microsoft.com/sql/connect/php/loading-the-php-sql-driver) on Microsoft Docs.
|
||||||
|
|
||||||
|
|
41
SECURITY.md
Normal file
41
SECURITY.md
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.7 BLOCK -->
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
|
||||||
|
|
||||||
|
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
|
||||||
|
|
||||||
|
## Reporting Security Issues
|
||||||
|
|
||||||
|
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||||
|
|
||||||
|
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
|
||||||
|
|
||||||
|
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
|
||||||
|
|
||||||
|
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
|
||||||
|
|
||||||
|
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
|
||||||
|
|
||||||
|
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
|
||||||
|
* Full paths of source file(s) related to the manifestation of the issue
|
||||||
|
* The location of the affected source code (tag/branch/commit or direct URL)
|
||||||
|
* Any special configuration required to reproduce the issue
|
||||||
|
* Step-by-step instructions to reproduce the issue
|
||||||
|
* Proof-of-concept or exploit code (if possible)
|
||||||
|
* Impact of the issue, including how an attacker might exploit the issue
|
||||||
|
|
||||||
|
This information will help us triage your report more quickly.
|
||||||
|
|
||||||
|
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
|
||||||
|
|
||||||
|
## Preferred Languages
|
||||||
|
|
||||||
|
We prefer all communications to be in English.
|
||||||
|
|
||||||
|
## Policy
|
||||||
|
|
||||||
|
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
|
||||||
|
|
||||||
|
<!-- END MICROSOFT SECURITY.MD BLOCK -->
|
|
@ -12,6 +12,7 @@ environment:
|
||||||
SQLSRV_DBNAME: msphpsql_sqlsrv
|
SQLSRV_DBNAME: msphpsql_sqlsrv
|
||||||
PDOSQLSRV_DBNAME: msphpsql_pdosqlsrv
|
PDOSQLSRV_DBNAME: msphpsql_pdosqlsrv
|
||||||
PYTHON: c:\Python36
|
PYTHON: c:\Python36
|
||||||
|
APPVEYOR: true
|
||||||
# For details about Appveyor build worker images (VM template): https://www.appveyor.com/docs/build-environment/#build-worker-images
|
# For details about Appveyor build worker images (VM template): https://www.appveyor.com/docs/build-environment/#build-worker-images
|
||||||
matrix:
|
matrix:
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||||
|
|
|
@ -11,6 +11,7 @@ variables:
|
||||||
|
|
||||||
trigger:
|
trigger:
|
||||||
- dev
|
- dev
|
||||||
|
- fix/*
|
||||||
|
|
||||||
pr:
|
pr:
|
||||||
- dev
|
- dev
|
||||||
|
@ -18,7 +19,7 @@ pr:
|
||||||
jobs:
|
jobs:
|
||||||
- job: macOS
|
- job: macOS
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'macOS-10.15'
|
vmImage: 'macos-latest'
|
||||||
steps:
|
steps:
|
||||||
- checkout: self
|
- checkout: self
|
||||||
clean: true
|
clean: true
|
||||||
|
|
|
@ -200,7 +200,11 @@ class BuildDriver(object):
|
||||||
print('Something went wrong, launching log file', logfile)
|
print('Something went wrong, launching log file', logfile)
|
||||||
# display log file only when not testing
|
# display log file only when not testing
|
||||||
if not self.testing:
|
if not self.testing:
|
||||||
os.startfile(os.path.join(root_dir, 'php-sdk', logfile))
|
logfile_path = os.path.join(root_dir, 'php-sdk', logfile)
|
||||||
|
if os.path.isfile(logfile_path):
|
||||||
|
with open(logfile_path, 'r') as f:
|
||||||
|
f.seek(0)
|
||||||
|
print(f.read())
|
||||||
os.chdir(work_dir)
|
os.chdir(work_dir)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
|
@ -321,7 +321,7 @@ class BuildUtil(object):
|
||||||
else: # pdo_sqlsrv
|
else: # pdo_sqlsrv
|
||||||
cmd_line = ' --enable-pdo --with-pdo-sqlsrv=shared ' + cmd_line
|
cmd_line = ' --enable-pdo --with-pdo-sqlsrv=shared ' + cmd_line
|
||||||
|
|
||||||
cmd_line = 'cscript configure.js --disable-all --enable-cli --enable-cgi --enable-json --enable-embed' + cmd_line
|
cmd_line = 'cscript configure.js --disable-all --enable-cli --enable-cgi --enable-json --enable-embed --enable-mbstring --enable-ctype' + cmd_line
|
||||||
if self.thread == 'nts':
|
if self.thread == 'nts':
|
||||||
cmd_line = cmd_line + ' --disable-zts'
|
cmd_line = cmd_line + ' --disable-zts'
|
||||||
return cmd_line
|
return cmd_line
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 91 KiB |
Binary file not shown.
Before Width: | Height: | Size: 107 KiB |
Binary file not shown.
Before Width: | Height: | Size: 48 KiB |
Binary file not shown.
Before Width: | Height: | Size: 67 KiB |
|
@ -4,7 +4,7 @@ dnl
|
||||||
dnl Contents: the code that will go into the configure script, indicating options,
|
dnl Contents: the code that will go into the configure script, indicating options,
|
||||||
dnl external libraries and includes, and what source files are to be compiled.
|
dnl external libraries and includes, and what source files are to be compiled.
|
||||||
dnl
|
dnl
|
||||||
dnl Microsoft Drivers 5.10 for PHP for SQL Server
|
dnl Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
dnl Copyright(c) Microsoft Corporation
|
dnl Copyright(c) Microsoft Corporation
|
||||||
dnl All rights reserved.
|
dnl All rights reserved.
|
||||||
dnl MIT License
|
dnl MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: JScript build configuration used by buildconf.bat
|
// Contents: JScript build configuration used by buildconf.bat
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,17 +3,17 @@
|
||||||
//
|
//
|
||||||
// Contents: Implements the PDO object for PDO_SQLSRV
|
// Contents: Implements the PDO object for PDO_SQLSRV
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
|
// 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,
|
// 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 :
|
// 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 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,
|
// 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
|
// 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
|
// 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.
|
// IN THE SOFTWARE.
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ namespace {
|
||||||
|
|
||||||
const char LAST_INSERT_ID_QUERY[] = "SELECT @@IDENTITY;";
|
const char LAST_INSERT_ID_QUERY[] = "SELECT @@IDENTITY;";
|
||||||
const size_t LAST_INSERT_ID_BUFF_LEN = 50; // size of the buffer to hold the string value of the last inserted id, which may be an int, bigint, decimal(p,0) or numeric(p,0)
|
const size_t LAST_INSERT_ID_BUFF_LEN = 50; // size of the buffer to hold the string value of the last inserted id, which may be an int, bigint, decimal(p,0) or numeric(p,0)
|
||||||
const char SEQUENCE_CURRENT_VALUE_QUERY[] = "SELECT current_value FROM sys.sequences WHERE name=N'%s'";
|
const char SEQUENCE_CURRENT_VALUE_QUERY[] = "SELECT current_value FROM sys.sequences WHERE name=N'%s'";
|
||||||
const int LAST_INSERT_ID_QUERY_MAX_LEN = sizeof( SEQUENCE_CURRENT_VALUE_QUERY ) + SQL_MAX_SQLSERVERNAME + 2; // include the quotes
|
const int LAST_INSERT_ID_QUERY_MAX_LEN = sizeof( SEQUENCE_CURRENT_VALUE_QUERY ) + SQL_MAX_SQLSERVERNAME + 2; // include the quotes
|
||||||
|
|
||||||
// List of PDO supported connection options.
|
// List of PDO supported connection options.
|
||||||
|
@ -95,7 +95,7 @@ enum PDO_STMT_OPTIONS {
|
||||||
|
|
||||||
// List of all the statement options supported by this driver.
|
// List of all the statement options supported by this driver.
|
||||||
const stmt_option PDO_STMT_OPTS[] = {
|
const stmt_option PDO_STMT_OPTS[] = {
|
||||||
|
|
||||||
{ NULL, 0, SQLSRV_STMT_OPTION_QUERY_TIMEOUT, std::unique_ptr<stmt_option_query_timeout>( new stmt_option_query_timeout ) },
|
{ NULL, 0, SQLSRV_STMT_OPTION_QUERY_TIMEOUT, std::unique_ptr<stmt_option_query_timeout>( new stmt_option_query_timeout ) },
|
||||||
{ NULL, 0, SQLSRV_STMT_OPTION_SCROLLABLE, std::unique_ptr<stmt_option_pdo_scrollable>( new stmt_option_pdo_scrollable ) },
|
{ NULL, 0, SQLSRV_STMT_OPTION_SCROLLABLE, std::unique_ptr<stmt_option_pdo_scrollable>( new stmt_option_pdo_scrollable ) },
|
||||||
{ NULL, 0, PDO_STMT_OPTION_ENCODING, std::unique_ptr<stmt_option_encoding>( new stmt_option_encoding ) },
|
{ NULL, 0, PDO_STMT_OPTION_ENCODING, std::unique_ptr<stmt_option_encoding>( new stmt_option_encoding ) },
|
||||||
|
@ -113,12 +113,12 @@ const stmt_option PDO_STMT_OPTS[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
// boolean connection string
|
// boolean connection string
|
||||||
struct pdo_bool_conn_str_func
|
struct pdo_bool_conn_str_func
|
||||||
{
|
{
|
||||||
static void func( _In_ connection_option const* option, _Inout_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str );
|
static void func( _In_ connection_option const* option, _Inout_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str );
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pdo_txn_isolation_conn_attr_func
|
struct pdo_txn_isolation_conn_attr_func
|
||||||
{
|
{
|
||||||
static void func( connection_option const* /*option*/, _In_ zval* value_z, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ );
|
static void func( connection_option const* /*option*/, _In_ zval* value_z, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ );
|
||||||
};
|
};
|
||||||
|
@ -130,7 +130,7 @@ struct pdo_int_conn_str_func {
|
||||||
SQLSRV_ASSERT(Z_TYPE_P(value) == IS_STRING, "Wrong zval type for this keyword");
|
SQLSRV_ASSERT(Z_TYPE_P(value) == IS_STRING, "Wrong zval type for this keyword");
|
||||||
|
|
||||||
std::string val_str = Z_STRVAL_P( value );
|
std::string val_str = Z_STRVAL_P( value );
|
||||||
|
|
||||||
conn_str += option->odbc_name;
|
conn_str += option->odbc_name;
|
||||||
conn_str += "={";
|
conn_str += "={";
|
||||||
conn_str += val_str;
|
conn_str += val_str;
|
||||||
|
@ -180,9 +180,9 @@ struct pdo_int_conn_attr_func {
|
||||||
static void func( connection_option const* /*option*/, _In_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ )
|
static void func( connection_option const* /*option*/, _In_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_STRING, "pdo_int_conn_attr_func: Unexpected zval type." );
|
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_STRING, "pdo_int_conn_attr_func: Unexpected zval type." );
|
||||||
|
|
||||||
size_t val = static_cast<size_t>( atoi( Z_STRVAL_P( value )) );
|
size_t val = static_cast<size_t>( atoi( Z_STRVAL_P( value )) );
|
||||||
core::SQLSetConnectAttr( conn, Attr, reinterpret_cast<SQLPOINTER>( val ), SQL_IS_UINTEGER );
|
core::SQLSetConnectAttr( conn, Attr, reinterpret_cast<SQLPOINTER>( val ), SQL_IS_UINTEGER );
|
||||||
}
|
}
|
||||||
|
@ -198,8 +198,8 @@ struct pdo_bool_conn_attr_func {
|
||||||
static void func( connection_option const* /*option*/, _Inout_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ )
|
static void func( connection_option const* /*option*/, _Inout_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
core::SQLSetConnectAttr( conn, Attr, reinterpret_cast<SQLPOINTER>( core_str_zval_is_true( value )),
|
core::SQLSetConnectAttr( conn, Attr, reinterpret_cast<SQLPOINTER>( core_str_zval_is_true( value )),
|
||||||
SQL_IS_UINTEGER );
|
SQL_IS_UINTEGER );
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
@ -209,7 +209,7 @@ struct pdo_bool_conn_attr_func {
|
||||||
};
|
};
|
||||||
|
|
||||||
// statement options related functions
|
// statement options related functions
|
||||||
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ size_t key, _Inout_ HashTable* options_ht,
|
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ size_t key, _Inout_ HashTable* options_ht,
|
||||||
_Inout_ zval** data );
|
_Inout_ zval** data );
|
||||||
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht );
|
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht );
|
||||||
|
|
||||||
|
@ -218,50 +218,50 @@ void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_opti
|
||||||
|
|
||||||
// List of all connection options supported by this driver.
|
// List of all connection options supported by this driver.
|
||||||
const connection_option PDO_CONN_OPTS[] = {
|
const connection_option PDO_CONN_OPTS[] = {
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::Server,
|
PDOConnOptionNames::Server,
|
||||||
sizeof( PDOConnOptionNames::Server ),
|
sizeof( PDOConnOptionNames::Server ),
|
||||||
PDO_CONN_OPTION_SERVER,
|
PDO_CONN_OPTION_SERVER,
|
||||||
NULL,
|
NULL,
|
||||||
0,
|
0,
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::APP,
|
PDOConnOptionNames::APP,
|
||||||
sizeof( PDOConnOptionNames::APP ),
|
sizeof( PDOConnOptionNames::APP ),
|
||||||
SQLSRV_CONN_OPTION_APP,
|
SQLSRV_CONN_OPTION_APP,
|
||||||
ODBCConnOptions::APP,
|
ODBCConnOptions::APP,
|
||||||
sizeof( ODBCConnOptions::APP ),
|
sizeof( ODBCConnOptions::APP ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::AccessToken,
|
PDOConnOptionNames::AccessToken,
|
||||||
sizeof( PDOConnOptionNames::AccessToken ),
|
sizeof( PDOConnOptionNames::AccessToken ),
|
||||||
SQLSRV_CONN_OPTION_ACCESS_TOKEN,
|
SQLSRV_CONN_OPTION_ACCESS_TOKEN,
|
||||||
ODBCConnOptions::AccessToken,
|
ODBCConnOptions::AccessToken,
|
||||||
sizeof( ODBCConnOptions::AccessToken),
|
sizeof( ODBCConnOptions::AccessToken),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
access_token_set_func::func
|
access_token_set_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::ApplicationIntent,
|
PDOConnOptionNames::ApplicationIntent,
|
||||||
sizeof( PDOConnOptionNames::ApplicationIntent ),
|
sizeof( PDOConnOptionNames::ApplicationIntent ),
|
||||||
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
|
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
|
||||||
ODBCConnOptions::ApplicationIntent,
|
ODBCConnOptions::ApplicationIntent,
|
||||||
sizeof( ODBCConnOptions::ApplicationIntent ),
|
sizeof( ODBCConnOptions::ApplicationIntent ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::AttachDBFileName,
|
PDOConnOptionNames::AttachDBFileName,
|
||||||
sizeof( PDOConnOptionNames::AttachDBFileName ),
|
sizeof( PDOConnOptionNames::AttachDBFileName ),
|
||||||
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
|
SQLSRV_CONN_OPTION_ATTACHDBFILENAME,
|
||||||
ODBCConnOptions::AttachDBFileName,
|
ODBCConnOptions::AttachDBFileName,
|
||||||
sizeof( ODBCConnOptions::AttachDBFileName ),
|
sizeof( ODBCConnOptions::AttachDBFileName ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::Authentication,
|
PDOConnOptionNames::Authentication,
|
||||||
|
@ -339,17 +339,17 @@ const connection_option PDO_CONN_OPTS[] = {
|
||||||
PDOConnOptionNames::Encrypt,
|
PDOConnOptionNames::Encrypt,
|
||||||
sizeof( PDOConnOptionNames::Encrypt ),
|
sizeof( PDOConnOptionNames::Encrypt ),
|
||||||
SQLSRV_CONN_OPTION_ENCRYPT,
|
SQLSRV_CONN_OPTION_ENCRYPT,
|
||||||
ODBCConnOptions::Encrypt,
|
ODBCConnOptions::Encrypt,
|
||||||
sizeof( ODBCConnOptions::Encrypt ),
|
sizeof( ODBCConnOptions::Encrypt ),
|
||||||
CONN_ATTR_MIXED,
|
CONN_ATTR_MIXED,
|
||||||
pdo_encrypt_set_func::func
|
pdo_encrypt_set_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::Failover_Partner,
|
PDOConnOptionNames::Failover_Partner,
|
||||||
sizeof( PDOConnOptionNames::Failover_Partner ),
|
sizeof( PDOConnOptionNames::Failover_Partner ),
|
||||||
SQLSRV_CONN_OPTION_FAILOVER_PARTNER,
|
SQLSRV_CONN_OPTION_FAILOVER_PARTNER,
|
||||||
ODBCConnOptions::Failover_Partner,
|
ODBCConnOptions::Failover_Partner,
|
||||||
sizeof( ODBCConnOptions::Failover_Partner ),
|
sizeof( ODBCConnOptions::Failover_Partner ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
|
@ -360,7 +360,7 @@ const connection_option PDO_CONN_OPTS[] = {
|
||||||
ODBCConnOptions::KeyStoreAuthentication,
|
ODBCConnOptions::KeyStoreAuthentication,
|
||||||
sizeof( ODBCConnOptions::KeyStoreAuthentication ),
|
sizeof( ODBCConnOptions::KeyStoreAuthentication ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
ce_akv_str_set_func::func
|
ce_akv_str_set_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::KeyStorePrincipalId,
|
PDOConnOptionNames::KeyStorePrincipalId,
|
||||||
|
@ -369,7 +369,7 @@ const connection_option PDO_CONN_OPTS[] = {
|
||||||
ODBCConnOptions::KeyStorePrincipalId,
|
ODBCConnOptions::KeyStorePrincipalId,
|
||||||
sizeof( ODBCConnOptions::KeyStorePrincipalId ),
|
sizeof( ODBCConnOptions::KeyStorePrincipalId ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
ce_akv_str_set_func::func
|
ce_akv_str_set_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::KeyStoreSecret,
|
PDOConnOptionNames::KeyStoreSecret,
|
||||||
|
@ -387,7 +387,7 @@ const connection_option PDO_CONN_OPTS[] = {
|
||||||
ODBCConnOptions::LoginTimeout,
|
ODBCConnOptions::LoginTimeout,
|
||||||
sizeof( ODBCConnOptions::LoginTimeout ),
|
sizeof( ODBCConnOptions::LoginTimeout ),
|
||||||
CONN_ATTR_INT,
|
CONN_ATTR_INT,
|
||||||
pdo_int_conn_attr_func<SQL_ATTR_LOGIN_TIMEOUT>::func
|
pdo_int_conn_attr_func<SQL_ATTR_LOGIN_TIMEOUT>::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::MARS_Option,
|
PDOConnOptionNames::MARS_Option,
|
||||||
|
@ -421,9 +421,9 @@ const connection_option PDO_CONN_OPTS[] = {
|
||||||
sizeof( PDOConnOptionNames::TraceFile ),
|
sizeof( PDOConnOptionNames::TraceFile ),
|
||||||
SQLSRV_CONN_OPTION_TRACE_FILE,
|
SQLSRV_CONN_OPTION_TRACE_FILE,
|
||||||
ODBCConnOptions::TraceFile,
|
ODBCConnOptions::TraceFile,
|
||||||
sizeof( ODBCConnOptions::TraceFile ),
|
sizeof( ODBCConnOptions::TraceFile ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
str_conn_attr_func<SQL_ATTR_TRACEFILE>::func
|
str_conn_attr_func<SQL_ATTR_TRACEFILE>::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
PDOConnOptionNames::TraceOn,
|
PDOConnOptionNames::TraceOn,
|
||||||
|
@ -467,7 +467,7 @@ const connection_option PDO_CONN_OPTS[] = {
|
||||||
SQLSRV_CONN_OPTION_WSID,
|
SQLSRV_CONN_OPTION_WSID,
|
||||||
ODBCConnOptions::WSID,
|
ODBCConnOptions::WSID,
|
||||||
sizeof( ODBCConnOptions::WSID ),
|
sizeof( ODBCConnOptions::WSID ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -597,7 +597,7 @@ pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( _In_ SQLHANDLE h, _In_ error_callback e, _In_ vo
|
||||||
fetch_numeric( false ),
|
fetch_numeric( false ),
|
||||||
fetch_datetime( false ),
|
fetch_datetime( false ),
|
||||||
format_decimals( false ),
|
format_decimals( false ),
|
||||||
decimal_places( NO_CHANGE_DECIMAL_PLACES ),
|
decimal_places( NO_CHANGE_DECIMAL_PLACES ),
|
||||||
use_national_characters(CHARSET_PREFERENCE_NOT_SPECIFIED),
|
use_national_characters(CHARSET_PREFERENCE_NOT_SPECIFIED),
|
||||||
emulate_prepare(false)
|
emulate_prepare(false)
|
||||||
{
|
{
|
||||||
|
@ -608,11 +608,11 @@ pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( _In_ SQLHANDLE h, _In_ error_callback e, _In_ vo
|
||||||
}
|
}
|
||||||
|
|
||||||
// pdo_sqlsrv_db_handle_factory
|
// pdo_sqlsrv_db_handle_factory
|
||||||
// Maps to PDO::__construct.
|
// Maps to PDO::__construct.
|
||||||
// Factory method called by the PDO driver manager to create a SQLSRV PDO connection.
|
// Factory method called by the PDO driver manager to create a SQLSRV PDO connection.
|
||||||
// Does the following things:
|
// Does the following things:
|
||||||
// 1.Sets the error handling temporarily to PDO_ERRMODE_EXCEPTION.
|
// 1.Sets the error handling temporarily to PDO_ERRMODE_EXCEPTION.
|
||||||
// (If an error occurs in this function, the PDO specification mandates that
|
// (If an error occurs in this function, the PDO specification mandates that
|
||||||
// an exception be thrown, regardless of the error mode setting.)
|
// an exception be thrown, regardless of the error mode setting.)
|
||||||
// 2. Processes the driver options.
|
// 2. Processes the driver options.
|
||||||
// 3. Creates a core_conn object by calling core_sqlsrv_connect.
|
// 3. Creates a core_conn object by calling core_sqlsrv_connect.
|
||||||
|
@ -623,7 +623,7 @@ pdo_sqlsrv_dbh::pdo_sqlsrv_dbh( _In_ SQLHANDLE h, _In_ error_callback e, _In_ vo
|
||||||
// driver_options - A HashTable (within the zval) of options to use when creating the connection.
|
// driver_options - A HashTable (within the zval) of options to use when creating the connection.
|
||||||
// Return:
|
// Return:
|
||||||
// 0 for failure, 1 for success.
|
// 0 for failure, 1 for success.
|
||||||
int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_options)
|
int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_options)
|
||||||
{
|
{
|
||||||
PDO_LOG_DBH_ENTRY;
|
PDO_LOG_DBH_ENTRY;
|
||||||
|
|
||||||
|
@ -640,7 +640,7 @@ int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_
|
||||||
ZVAL_UNDEF( &server_z );
|
ZVAL_UNDEF( &server_z );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// no matter what the error mode, we want exceptions thrown if the connection fails
|
// no matter what the error mode, we want exceptions thrown if the connection fails
|
||||||
// to happen (per the PDO spec)
|
// to happen (per the PDO spec)
|
||||||
dbh->error_mode = PDO_ERRMODE_EXCEPTION;
|
dbh->error_mode = PDO_ERRMODE_EXCEPTION;
|
||||||
|
@ -656,23 +656,23 @@ int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_
|
||||||
dbh->refcount--;
|
dbh->refcount--;
|
||||||
throw pdo::PDOException();
|
throw pdo::PDOException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the options array to be passed to the core layer
|
// Initialize the options array to be passed to the core layer
|
||||||
ALLOC_HASHTABLE( pdo_conn_options_ht );
|
ALLOC_HASHTABLE( pdo_conn_options_ht );
|
||||||
|
|
||||||
core::sqlsrv_zend_hash_init( *g_pdo_henv_cp, pdo_conn_options_ht, 10 /* # of buckets */,
|
core::sqlsrv_zend_hash_init( *g_pdo_henv_cp, pdo_conn_options_ht, 10 /* # of buckets */,
|
||||||
ZVAL_PTR_DTOR, 0 /*persistent*/ );
|
ZVAL_PTR_DTOR, 0 /*persistent*/ );
|
||||||
|
|
||||||
// Either of g_pdo_henv_cp or g_pdo_henv_ncp can be used to propogate the error.
|
// Either of g_pdo_henv_cp or g_pdo_henv_ncp can be used to propogate the error.
|
||||||
dsn_parser = new ( sqlsrv_malloc( sizeof( conn_string_parser ))) conn_string_parser( *g_pdo_henv_cp, dbh->data_source,
|
dsn_parser = new ( sqlsrv_malloc( sizeof( conn_string_parser ))) conn_string_parser( *g_pdo_henv_cp, dbh->data_source,
|
||||||
static_cast<int>( dbh->data_source_len ), pdo_conn_options_ht );
|
static_cast<int>( dbh->data_source_len ), pdo_conn_options_ht );
|
||||||
dsn_parser->parse_conn_string();
|
dsn_parser->parse_conn_string();
|
||||||
|
|
||||||
// Extract the server name
|
// Extract the server name
|
||||||
temp_server_z = zend_hash_index_find( pdo_conn_options_ht, PDO_CONN_OPTION_SERVER );
|
temp_server_z = zend_hash_index_find( pdo_conn_options_ht, PDO_CONN_OPTION_SERVER );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( temp_server_z == NULL ), g_pdo_henv_cp, PDO_SQLSRV_ERROR_SERVER_NOT_SPECIFIED ) {
|
CHECK_CUSTOM_ERROR(( temp_server_z == NULL ), g_pdo_henv_cp, PDO_SQLSRV_ERROR_SERVER_NOT_SPECIFIED ) {
|
||||||
|
|
||||||
throw pdo::PDOException();
|
throw pdo::PDOException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,13 +682,13 @@ int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_
|
||||||
zval_add_ref( &server_z );
|
zval_add_ref( &server_z );
|
||||||
zend_hash_index_del( pdo_conn_options_ht, PDO_CONN_OPTION_SERVER );
|
zend_hash_index_del( pdo_conn_options_ht, PDO_CONN_OPTION_SERVER );
|
||||||
|
|
||||||
sqlsrv_conn* conn = core_sqlsrv_connect( *g_pdo_henv_cp, *g_pdo_henv_ncp, core::allocate_conn<pdo_sqlsrv_dbh>, Z_STRVAL( server_z ),
|
sqlsrv_conn* conn = core_sqlsrv_connect( *g_pdo_henv_cp, *g_pdo_henv_ncp, core::allocate_conn<pdo_sqlsrv_dbh>, Z_STRVAL( server_z ),
|
||||||
dbh->username, dbh->password, pdo_conn_options_ht, pdo_sqlsrv_handle_dbh_error,
|
dbh->username, dbh->password, pdo_conn_options_ht, pdo_sqlsrv_handle_dbh_error,
|
||||||
PDO_CONN_OPTS, dbh, "pdo_sqlsrv_db_handle_factory" );
|
PDO_CONN_OPTS, dbh, "pdo_sqlsrv_db_handle_factory" );
|
||||||
|
|
||||||
// Free the string in server_z after being used
|
// Free the string in server_z after being used
|
||||||
zend_string_release( Z_STR( server_z ));
|
zend_string_release( Z_STR( server_z ));
|
||||||
|
|
||||||
SQLSRV_ASSERT( conn != NULL, "Invalid connection returned. Exception should have been thrown." );
|
SQLSRV_ASSERT( conn != NULL, "Invalid connection returned. Exception should have been thrown." );
|
||||||
|
|
||||||
// set the driver_data and methods to complete creation of the PDO object
|
// set the driver_data and methods to complete creation of the PDO object
|
||||||
|
@ -699,13 +699,13 @@ int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_
|
||||||
|
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
|
||||||
if ( Z_TYPE( server_z ) == IS_STRING ) {
|
if ( Z_TYPE( server_z ) == IS_STRING ) {
|
||||||
zend_string_release( Z_STR( server_z ));
|
zend_string_release( Z_STR( server_z ));
|
||||||
}
|
}
|
||||||
dbh->error_mode = prev_err_mode; // reset the error mode
|
dbh->error_mode = prev_err_mode; // reset the error mode
|
||||||
g_pdo_henv_cp->last_error().reset(); // reset the last error; callee will check if last_error exist before freeing it and setting it to NULL
|
g_pdo_henv_cp->last_error().reset(); // reset the last error; callee will check if last_error exist before freeing it and setting it to NULL
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch( ... ) {
|
catch( ... ) {
|
||||||
|
@ -719,8 +719,8 @@ int pdo_sqlsrv_db_handle_factory( _Inout_ pdo_dbh_t *dbh, _In_opt_ zval *driver_
|
||||||
// pdo_sqlsrv_dbh_close
|
// pdo_sqlsrv_dbh_close
|
||||||
// Maps to PDO::__destruct.
|
// Maps to PDO::__destruct.
|
||||||
// Called when a PDO object is to be destroyed.
|
// Called when a PDO object is to be destroyed.
|
||||||
// By the time this function is called, PDO has already made sure that
|
// By the time this function is called, PDO has already made sure that
|
||||||
// all statements are disposed and the PDO object is the last item destroyed.
|
// all statements are disposed and the PDO object is the last item destroyed.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// dbh - The PDO managed connection object.
|
// dbh - The PDO managed connection object.
|
||||||
// Return:
|
// Return:
|
||||||
|
@ -788,7 +788,7 @@ bool pdo_sqlsrv_dbh_prepare(_Inout_ pdo_dbh_t *dbh, _In_ zend_string *sql_zstr,
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// assign the methods for the statement object. This is necessary even if the
|
// assign the methods for the statement object. This is necessary even if the
|
||||||
// statement fails so the user can retrieve the error information.
|
// statement fails so the user can retrieve the error information.
|
||||||
stmt->methods = &pdo_sqlsrv_stmt_methods;
|
stmt->methods = &pdo_sqlsrv_stmt_methods;
|
||||||
// if not emulate_prepare, we support parameterized queries with ?, not names
|
// if not emulate_prepare, we support parameterized queries with ?, not names
|
||||||
|
@ -796,20 +796,20 @@ bool pdo_sqlsrv_dbh_prepare(_Inout_ pdo_dbh_t *dbh, _In_ zend_string *sql_zstr,
|
||||||
|
|
||||||
// Initialize the options array to be passed to the core layer
|
// Initialize the options array to be passed to the core layer
|
||||||
ALLOC_HASHTABLE( pdo_stmt_options_ht );
|
ALLOC_HASHTABLE( pdo_stmt_options_ht );
|
||||||
core::sqlsrv_zend_hash_init( *driver_dbh , pdo_stmt_options_ht, 3 /* # of buckets */,
|
core::sqlsrv_zend_hash_init( *driver_dbh , pdo_stmt_options_ht, 3 /* # of buckets */,
|
||||||
ZVAL_PTR_DTOR, 0 /*persistent*/ );
|
ZVAL_PTR_DTOR, 0 /*persistent*/ );
|
||||||
|
|
||||||
// Either of g_pdo_henv_cp or g_pdo_henv_ncp can be used to propogate the error.
|
// Either of g_pdo_henv_cp or g_pdo_henv_ncp can be used to propogate the error.
|
||||||
validate_stmt_options( *driver_dbh, driver_options, pdo_stmt_options_ht );
|
validate_stmt_options( *driver_dbh, driver_options, pdo_stmt_options_ht );
|
||||||
|
|
||||||
driver_stmt = static_cast<pdo_sqlsrv_stmt*>( core_sqlsrv_create_stmt( driver_dbh, core::allocate_stmt<pdo_sqlsrv_stmt>,
|
driver_stmt = static_cast<pdo_sqlsrv_stmt*>( core_sqlsrv_create_stmt( driver_dbh, core::allocate_stmt<pdo_sqlsrv_stmt>,
|
||||||
pdo_stmt_options_ht, PDO_STMT_OPTS,
|
pdo_stmt_options_ht, PDO_STMT_OPTS,
|
||||||
pdo_sqlsrv_handle_stmt_error, stmt ));
|
pdo_sqlsrv_handle_stmt_error, stmt ));
|
||||||
|
|
||||||
// if the user didn't set anything in the prepare options, then set the buffer limit
|
// if the user didn't set anything in the prepare options, then set the buffer limit
|
||||||
// to the value set on the connection.
|
// to the value set on the connection.
|
||||||
if( driver_stmt->buffered_query_limit== sqlsrv_buffered_result_set::BUFFERED_QUERY_LIMIT_INVALID ) {
|
if( driver_stmt->buffered_query_limit== sqlsrv_buffered_result_set::BUFFERED_QUERY_LIMIT_INVALID ) {
|
||||||
|
|
||||||
driver_stmt->buffered_query_limit = driver_dbh->client_buffer_max_size;
|
driver_stmt->buffered_query_limit = driver_dbh->client_buffer_max_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -888,7 +888,7 @@ bool pdo_sqlsrv_dbh_prepare(_Inout_ pdo_dbh_t *dbh, _In_ zend_string *sql_zstr,
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt->driver_data = driver_stmt;
|
stmt->driver_data = driver_stmt;
|
||||||
driver_stmt.transferred();
|
driver_stmt.transferred();
|
||||||
}
|
}
|
||||||
// everything is cleaned up by this point
|
// everything is cleaned up by this point
|
||||||
// catch everything so the exception doesn't spill into the calling PDO code
|
// catch everything so the exception doesn't spill into the calling PDO code
|
||||||
|
@ -903,7 +903,7 @@ bool pdo_sqlsrv_dbh_prepare(_Inout_ pdo_dbh_t *dbh, _In_ zend_string *sql_zstr,
|
||||||
// connection with the error's SQLSTATE.
|
// connection with the error's SQLSTATE.
|
||||||
if( driver_dbh->last_error() ) {
|
if( driver_dbh->last_error() ) {
|
||||||
|
|
||||||
strcpy_s( dbh->error_code, sizeof( dbh->error_code ),
|
strcpy_s( dbh->error_code, sizeof( dbh->error_code ),
|
||||||
reinterpret_cast<const char*>( driver_dbh->last_error()->sqlstate ));
|
reinterpret_cast<const char*>( driver_dbh->last_error()->sqlstate ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,7 +930,7 @@ bool pdo_sqlsrv_dbh_prepare(_Inout_ pdo_dbh_t *dbh, _In_ zend_string *sql_zstr,
|
||||||
|
|
||||||
// pdo_sqlsrv_dbh_do
|
// pdo_sqlsrv_dbh_do
|
||||||
// Maps to PDO::exec.
|
// Maps to PDO::exec.
|
||||||
// Execute a SQL statement, such as an insert, update or delete, and return
|
// Execute a SQL statement, such as an insert, update or delete, and return
|
||||||
// the number of rows affected.
|
// the number of rows affected.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// dbh - the PDO connection object, which contains the ODBC handle
|
// dbh - the PDO connection object, which contains the ODBC handle
|
||||||
|
@ -958,7 +958,7 @@ zend_long pdo_sqlsrv_dbh_do(_Inout_ pdo_dbh_t *dbh, _In_ const zend_string *sql)
|
||||||
SQLSRV_STATIC_ASSERT( sizeof( rows ) == sizeof( SQLLEN ));
|
SQLSRV_STATIC_ASSERT( sizeof( rows ) == sizeof( SQLLEN ));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
SQLSRV_ASSERT( sql != NULL, "NULL or empty SQL string passed." );
|
SQLSRV_ASSERT( sql != NULL, "NULL or empty SQL string passed." );
|
||||||
SQLSRV_ASSERT( driver_dbh != NULL, "pdo_sqlsrv_dbh_do: driver_data object was NULL.");
|
SQLSRV_ASSERT( driver_dbh != NULL, "pdo_sqlsrv_dbh_do: driver_data object was NULL.");
|
||||||
|
|
||||||
|
@ -966,7 +966,7 @@ zend_long pdo_sqlsrv_dbh_do(_Inout_ pdo_dbh_t *dbh, _In_ const zend_string *sql)
|
||||||
pdo_stmt_t temp_stmt;
|
pdo_stmt_t temp_stmt;
|
||||||
temp_stmt.dbh = dbh;
|
temp_stmt.dbh = dbh;
|
||||||
// allocate a full driver statement to take advantage of the error handling
|
// allocate a full driver statement to take advantage of the error handling
|
||||||
driver_stmt = core_sqlsrv_create_stmt( driver_dbh, core::allocate_stmt<pdo_sqlsrv_stmt>, NULL /*options_ht*/,
|
driver_stmt = core_sqlsrv_create_stmt( driver_dbh, core::allocate_stmt<pdo_sqlsrv_stmt>, NULL /*options_ht*/,
|
||||||
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__ );
|
||||||
|
|
||||||
|
@ -1004,11 +1004,11 @@ zend_long pdo_sqlsrv_dbh_do(_Inout_ pdo_dbh_t *dbh, _In_ const zend_string *sql)
|
||||||
strcpy_s( dbh->error_code, sizeof( dbh->error_code ),
|
strcpy_s( dbh->error_code, sizeof( dbh->error_code ),
|
||||||
reinterpret_cast<const char*>( driver_stmt->last_error()->sqlstate ));
|
reinterpret_cast<const char*>( driver_stmt->last_error()->sqlstate ));
|
||||||
driver_dbh->set_last_error( driver_stmt->last_error() );
|
driver_dbh->set_last_error( driver_stmt->last_error() );
|
||||||
|
|
||||||
if( driver_stmt ) {
|
if( driver_stmt ) {
|
||||||
driver_stmt->~sqlsrv_stmt();
|
driver_stmt->~sqlsrv_stmt();
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
catch( ... ) {
|
catch( ... ) {
|
||||||
|
@ -1028,7 +1028,7 @@ zend_long pdo_sqlsrv_dbh_do(_Inout_ pdo_dbh_t *dbh, _In_ const zend_string *sql)
|
||||||
|
|
||||||
// pdo_sqlsrv_dbh_begin
|
// pdo_sqlsrv_dbh_begin
|
||||||
// Maps to PDO::beginTransaction.
|
// Maps to PDO::beginTransaction.
|
||||||
// Begins a transaction. Turns off auto-commit mode. The pdo_dbh_t::in_txn
|
// Begins a transaction. Turns off auto-commit mode. The pdo_dbh_t::in_txn
|
||||||
// flag is maintained by PDO so we dont have to worry about it.
|
// flag is maintained by PDO so we dont have to worry about it.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// dbh - The PDO managed connection object.
|
// dbh - The PDO managed connection object.
|
||||||
|
@ -1046,17 +1046,17 @@ bool pdo_sqlsrv_dbh_begin(_Inout_ pdo_dbh_t *dbh)
|
||||||
PDO_LOG_DBH_ENTRY;
|
PDO_LOG_DBH_ENTRY;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
SQLSRV_ASSERT( dbh != NULL, "pdo_sqlsrv_dbh_begin: pdo_dbh_t object was null" );
|
SQLSRV_ASSERT( dbh != NULL, "pdo_sqlsrv_dbh_begin: pdo_dbh_t object was null" );
|
||||||
|
|
||||||
sqlsrv_conn* driver_conn = reinterpret_cast<sqlsrv_conn*>( dbh->driver_data );
|
sqlsrv_conn* driver_conn = reinterpret_cast<sqlsrv_conn*>( dbh->driver_data );
|
||||||
|
|
||||||
SQLSRV_ASSERT( driver_conn != NULL, "pdo_sqlsrv_dbh_begin: driver_data object was null" );
|
SQLSRV_ASSERT( driver_conn != NULL, "pdo_sqlsrv_dbh_begin: driver_data object was null" );
|
||||||
|
|
||||||
DEBUG_SQLSRV_ASSERT( !dbh->in_txn, "pdo_sqlsrv_dbh_begin: Already in transaction" );
|
DEBUG_SQLSRV_ASSERT( !dbh->in_txn, "pdo_sqlsrv_dbh_begin: Already in transaction" );
|
||||||
|
|
||||||
core_sqlsrv_begin_transaction( driver_conn );
|
core_sqlsrv_begin_transaction( driver_conn );
|
||||||
|
|
||||||
#if PHP_VERSION_ID < 80100
|
#if PHP_VERSION_ID < 80100
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
|
@ -1071,7 +1071,7 @@ bool pdo_sqlsrv_dbh_begin(_Inout_ pdo_dbh_t *dbh)
|
||||||
#endif
|
#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
|
||||||
|
@ -1088,7 +1088,7 @@ bool pdo_sqlsrv_dbh_begin(_Inout_ pdo_dbh_t *dbh)
|
||||||
// Maps to PDO::commit.
|
// Maps to PDO::commit.
|
||||||
// Commits a transaction. Returns the connection to auto-commit mode.
|
// Commits a transaction. Returns the connection to auto-commit mode.
|
||||||
// PDO throws error if PDO::commit is called on a connection that is not in an active
|
// PDO throws error if PDO::commit is called on a connection that is not in an active
|
||||||
// transaction. The pdo_dbh_t::in_txn flag is maintained by PDO so we dont have
|
// transaction. The pdo_dbh_t::in_txn flag is maintained by PDO so we dont have
|
||||||
// to worry about it here.
|
// to worry about it here.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// dbh - The PDO managed connection object.
|
// dbh - The PDO managed connection object.
|
||||||
|
@ -1106,17 +1106,17 @@ bool pdo_sqlsrv_dbh_commit(_Inout_ pdo_dbh_t *dbh)
|
||||||
PDO_LOG_DBH_ENTRY;
|
PDO_LOG_DBH_ENTRY;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
SQLSRV_ASSERT( dbh != NULL, "pdo_sqlsrv_dbh_commit: pdo_dbh_t object was null" );
|
SQLSRV_ASSERT( dbh != NULL, "pdo_sqlsrv_dbh_commit: pdo_dbh_t object was null" );
|
||||||
|
|
||||||
sqlsrv_conn* driver_conn = reinterpret_cast<sqlsrv_conn*>( dbh->driver_data );
|
sqlsrv_conn* driver_conn = reinterpret_cast<sqlsrv_conn*>( dbh->driver_data );
|
||||||
|
|
||||||
SQLSRV_ASSERT( driver_conn != NULL, "pdo_sqlsrv_dbh_commit: driver_data object was null" );
|
SQLSRV_ASSERT( driver_conn != NULL, "pdo_sqlsrv_dbh_commit: driver_data object was null" );
|
||||||
|
|
||||||
DEBUG_SQLSRV_ASSERT( dbh->in_txn, "pdo_sqlsrv_dbh_commit: Not in transaction" );
|
DEBUG_SQLSRV_ASSERT( dbh->in_txn, "pdo_sqlsrv_dbh_commit: Not in transaction" );
|
||||||
|
|
||||||
core_sqlsrv_commit( driver_conn );
|
core_sqlsrv_commit( driver_conn );
|
||||||
|
|
||||||
#if PHP_VERSION_ID < 80100
|
#if PHP_VERSION_ID < 80100
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
|
@ -1131,7 +1131,7 @@ bool pdo_sqlsrv_dbh_commit(_Inout_ pdo_dbh_t *dbh)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
catch( ... ) {
|
catch( ... ) {
|
||||||
|
|
||||||
DIE ("pdo_sqlsrv_dbh_commit: Uncaught exception occurred.");
|
DIE ("pdo_sqlsrv_dbh_commit: Uncaught exception occurred.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1147,7 +1147,7 @@ bool pdo_sqlsrv_dbh_commit(_Inout_ pdo_dbh_t *dbh)
|
||||||
// Maps to PDO::rollback.
|
// Maps to PDO::rollback.
|
||||||
// Rolls back a transaction. Returns the connection in auto-commit mode.
|
// Rolls back a transaction. Returns the connection in auto-commit mode.
|
||||||
// PDO throws error if PDO::rollBack is called on a connection that is not in an active
|
// PDO throws error if PDO::rollBack is called on a connection that is not in an active
|
||||||
// transaction. The pdo_dbh_t::in_txn flag is maintained by PDO so we dont have
|
// transaction. The pdo_dbh_t::in_txn flag is maintained by PDO so we dont have
|
||||||
// to worry about it here.
|
// to worry about it here.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// dbh - The PDO managed connection object.
|
// dbh - The PDO managed connection object.
|
||||||
|
@ -1166,15 +1166,15 @@ bool pdo_sqlsrv_dbh_rollback(_Inout_ pdo_dbh_t *dbh)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SQLSRV_ASSERT( dbh != NULL, "pdo_sqlsrv_dbh_rollback: pdo_dbh_t object was null" );
|
SQLSRV_ASSERT( dbh != NULL, "pdo_sqlsrv_dbh_rollback: pdo_dbh_t object was null" );
|
||||||
|
|
||||||
sqlsrv_conn* driver_conn = reinterpret_cast<sqlsrv_conn*>( dbh->driver_data );
|
sqlsrv_conn* driver_conn = reinterpret_cast<sqlsrv_conn*>( dbh->driver_data );
|
||||||
|
|
||||||
SQLSRV_ASSERT( driver_conn != NULL, "pdo_sqlsrv_dbh_rollback: driver_data object was null" );
|
SQLSRV_ASSERT( driver_conn != NULL, "pdo_sqlsrv_dbh_rollback: driver_data object was null" );
|
||||||
|
|
||||||
DEBUG_SQLSRV_ASSERT( dbh->in_txn, "pdo_sqlsrv_dbh_rollback: Not in transaction" );
|
DEBUG_SQLSRV_ASSERT( dbh->in_txn, "pdo_sqlsrv_dbh_rollback: Not in transaction" );
|
||||||
|
|
||||||
core_sqlsrv_rollback( driver_conn );
|
core_sqlsrv_rollback( driver_conn );
|
||||||
|
|
||||||
#if PHP_VERSION_ID < 80100
|
#if PHP_VERSION_ID < 80100
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
|
@ -1190,7 +1190,7 @@ bool pdo_sqlsrv_dbh_rollback(_Inout_ pdo_dbh_t *dbh)
|
||||||
#endif
|
#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
|
||||||
|
@ -1204,7 +1204,7 @@ bool pdo_sqlsrv_dbh_rollback(_Inout_ pdo_dbh_t *dbh)
|
||||||
// pdo_sqlsrv_dbh_set_attr
|
// pdo_sqlsrv_dbh_set_attr
|
||||||
// Maps to PDO::setAttribute. Sets an attribute on the PDO connection object.
|
// Maps to PDO::setAttribute. Sets an attribute on the PDO connection object.
|
||||||
// PDO driver manager calls this function directly after calling the factory
|
// PDO driver manager calls this function directly after calling the factory
|
||||||
// method for PDO, for any attribute which is specified in the PDO constructor.
|
// method for PDO, for any attribute which is specified in the PDO constructor.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// dbh - The PDO connection object maintained by PDO.
|
// dbh - The PDO connection object maintained by PDO.
|
||||||
// attr - The attribute to be set.
|
// attr - The attribute to be set.
|
||||||
|
@ -1260,7 +1260,7 @@ bool pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
|
||||||
case SQLSRV_ATTR_QUERY_TIMEOUT:
|
case SQLSRV_ATTR_QUERY_TIMEOUT:
|
||||||
if( Z_TYPE_P( val ) != IS_LONG || Z_LVAL_P( val ) < 0 ) {
|
if( Z_TYPE_P( val ) != IS_LONG || Z_LVAL_P( val ) < 0 ) {
|
||||||
convert_to_string( val );
|
convert_to_string( val );
|
||||||
THROW_PDO_ERROR( driver_dbh, SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE, Z_STRVAL_P( val ));
|
THROW_PDO_ERROR( driver_dbh, SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE, Z_STRVAL_P( val ), NULL);
|
||||||
}
|
}
|
||||||
driver_dbh->query_timeout = static_cast<long>( Z_LVAL_P( val ) );
|
driver_dbh->query_timeout = static_cast<long>( Z_LVAL_P( val ) );
|
||||||
break;
|
break;
|
||||||
|
@ -1268,7 +1268,7 @@ bool pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
|
||||||
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
|
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
|
||||||
if( Z_TYPE_P( val ) != IS_LONG || Z_LVAL_P( val ) <= 0 ) {
|
if( Z_TYPE_P( val ) != IS_LONG || Z_LVAL_P( val ) <= 0 ) {
|
||||||
convert_to_string( val );
|
convert_to_string( val );
|
||||||
THROW_PDO_ERROR( driver_dbh, SQLSRV_ERROR_INVALID_BUFFER_LIMIT, Z_STRVAL_P( val ));
|
THROW_PDO_ERROR( driver_dbh, SQLSRV_ERROR_INVALID_BUFFER_LIMIT, Z_STRVAL_P( val ), NULL);
|
||||||
}
|
}
|
||||||
driver_dbh->client_buffer_max_size = Z_LVAL_P( val );
|
driver_dbh->client_buffer_max_size = Z_LVAL_P( val );
|
||||||
break;
|
break;
|
||||||
|
@ -1324,11 +1324,11 @@ bool pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Not supported
|
// Not supported
|
||||||
case PDO_ATTR_FETCH_TABLE_NAMES:
|
case PDO_ATTR_FETCH_TABLE_NAMES:
|
||||||
case PDO_ATTR_FETCH_CATALOG_NAMES:
|
case PDO_ATTR_FETCH_CATALOG_NAMES:
|
||||||
case PDO_ATTR_PREFETCH:
|
case PDO_ATTR_PREFETCH:
|
||||||
case PDO_ATTR_MAX_COLUMN_LEN:
|
case PDO_ATTR_MAX_COLUMN_LEN:
|
||||||
case PDO_ATTR_CURSOR_NAME:
|
case PDO_ATTR_CURSOR_NAME:
|
||||||
case PDO_ATTR_AUTOCOMMIT:
|
case PDO_ATTR_AUTOCOMMIT:
|
||||||
case PDO_ATTR_PERSISTENT:
|
case PDO_ATTR_PERSISTENT:
|
||||||
case PDO_ATTR_TIMEOUT:
|
case PDO_ATTR_TIMEOUT:
|
||||||
|
@ -1338,10 +1338,10 @@ bool pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
|
||||||
|
|
||||||
// Read-only
|
// Read-only
|
||||||
case PDO_ATTR_SERVER_VERSION:
|
case PDO_ATTR_SERVER_VERSION:
|
||||||
case PDO_ATTR_SERVER_INFO:
|
case PDO_ATTR_SERVER_INFO:
|
||||||
case PDO_ATTR_CLIENT_VERSION:
|
case PDO_ATTR_CLIENT_VERSION:
|
||||||
case PDO_ATTR_DRIVER_NAME:
|
case PDO_ATTR_DRIVER_NAME:
|
||||||
case PDO_ATTR_CONNECTION_STATUS:
|
case PDO_ATTR_CONNECTION_STATUS:
|
||||||
{
|
{
|
||||||
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_READ_ONLY_DBH_ATTR );
|
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_READ_ONLY_DBH_ATTR );
|
||||||
}
|
}
|
||||||
|
@ -1356,7 +1356,7 @@ bool pdo_sqlsrv_dbh_set_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout
|
||||||
break;
|
break;
|
||||||
// Statement level only
|
// Statement level only
|
||||||
case PDO_ATTR_CURSOR:
|
case PDO_ATTR_CURSOR:
|
||||||
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
|
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
|
||||||
case SQLSRV_ATTR_DATA_CLASSIFICATION:
|
case SQLSRV_ATTR_DATA_CLASSIFICATION:
|
||||||
{
|
{
|
||||||
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_STMT_LEVEL_ATTR );
|
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_STMT_LEVEL_ATTR );
|
||||||
|
@ -1411,8 +1411,8 @@ int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_
|
||||||
switch( attr ) {
|
switch( attr ) {
|
||||||
|
|
||||||
// Not supported
|
// Not supported
|
||||||
case PDO_ATTR_FETCH_TABLE_NAMES:
|
case PDO_ATTR_FETCH_TABLE_NAMES:
|
||||||
case PDO_ATTR_FETCH_CATALOG_NAMES:
|
case PDO_ATTR_FETCH_CATALOG_NAMES:
|
||||||
case PDO_ATTR_PREFETCH:
|
case PDO_ATTR_PREFETCH:
|
||||||
case PDO_ATTR_MAX_COLUMN_LEN:
|
case PDO_ATTR_MAX_COLUMN_LEN:
|
||||||
case PDO_ATTR_CURSOR_NAME:
|
case PDO_ATTR_CURSOR_NAME:
|
||||||
|
@ -1420,7 +1420,7 @@ int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_
|
||||||
case PDO_ATTR_TIMEOUT:
|
case PDO_ATTR_TIMEOUT:
|
||||||
{
|
{
|
||||||
#if PHP_VERSION_ID < 80100
|
#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
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1435,12 +1435,12 @@ int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_
|
||||||
|
|
||||||
// Statement level only
|
// Statement level only
|
||||||
case PDO_ATTR_CURSOR:
|
case PDO_ATTR_CURSOR:
|
||||||
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
|
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
|
||||||
case SQLSRV_ATTR_DATA_CLASSIFICATION:
|
case SQLSRV_ATTR_DATA_CLASSIFICATION:
|
||||||
{
|
{
|
||||||
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_STMT_LEVEL_ATTR );
|
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_STMT_LEVEL_ATTR );
|
||||||
}
|
}
|
||||||
|
|
||||||
case PDO_ATTR_STRINGIFY_FETCHES:
|
case PDO_ATTR_STRINGIFY_FETCHES:
|
||||||
{
|
{
|
||||||
// For this attribute, if we dont set the return_value than PDO returns NULL.
|
// For this attribute, if we dont set the return_value than PDO returns NULL.
|
||||||
|
@ -1453,13 +1453,13 @@ int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_
|
||||||
core_sqlsrv_get_server_info( driver_dbh, return_value );
|
core_sqlsrv_get_server_info( driver_dbh, return_value );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PDO_ATTR_SERVER_VERSION:
|
case PDO_ATTR_SERVER_VERSION:
|
||||||
{
|
{
|
||||||
core_sqlsrv_get_server_version( driver_dbh, return_value );
|
core_sqlsrv_get_server_version( driver_dbh, return_value );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PDO_ATTR_CLIENT_VERSION:
|
case PDO_ATTR_CLIENT_VERSION:
|
||||||
{
|
{
|
||||||
core_sqlsrv_get_client_info( driver_dbh, return_value );
|
core_sqlsrv_get_client_info( driver_dbh, return_value );
|
||||||
|
@ -1473,13 +1473,13 @@ int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQLSRV_ATTR_ENCODING:
|
case SQLSRV_ATTR_ENCODING:
|
||||||
{
|
{
|
||||||
ZVAL_LONG( return_value, driver_dbh->encoding() );
|
ZVAL_LONG( return_value, driver_dbh->encoding() );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQLSRV_ATTR_QUERY_TIMEOUT:
|
case SQLSRV_ATTR_QUERY_TIMEOUT:
|
||||||
{
|
{
|
||||||
ZVAL_LONG( return_value, ( driver_dbh->query_timeout == QUERY_TIMEOUT_INVALID ? 0 : driver_dbh->query_timeout ));
|
ZVAL_LONG( return_value, ( driver_dbh->query_timeout == QUERY_TIMEOUT_INVALID ? 0 : driver_dbh->query_timeout ));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1491,7 +1491,7 @@ int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
|
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
|
||||||
{
|
{
|
||||||
ZVAL_LONG( return_value, driver_dbh->client_buffer_max_size );
|
ZVAL_LONG( return_value, driver_dbh->client_buffer_max_size );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1515,7 +1515,7 @@ int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQLSRV_ATTR_DECIMAL_PLACES:
|
case SQLSRV_ATTR_DECIMAL_PLACES:
|
||||||
{
|
{
|
||||||
ZVAL_LONG( return_value, driver_dbh->decimal_places );
|
ZVAL_LONG( return_value, driver_dbh->decimal_places );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1528,7 +1528,7 @@ int pdo_sqlsrv_dbh_get_attr(_Inout_ pdo_dbh_t *dbh, _In_ zend_long attr, _Inout_
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_INVALID_DBH_ATTR );
|
THROW_PDO_ERROR( driver_dbh, PDO_SQLSRV_ERROR_INVALID_DBH_ATTR );
|
||||||
break;
|
break;
|
||||||
|
@ -1573,7 +1573,7 @@ void pdo_sqlsrv_dbh_return_error(_In_ pdo_dbh_t *dbh, _In_opt_ pdo_stmt_t *stmt,
|
||||||
else {
|
else {
|
||||||
ctx_error = static_cast<sqlsrv_conn*>( dbh->driver_data )->last_error();
|
ctx_error = static_cast<sqlsrv_conn*>( dbh->driver_data )->last_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
pdo_sqlsrv_retrieve_context_error( ctx_error, info );
|
pdo_sqlsrv_retrieve_context_error( ctx_error, info );
|
||||||
|
|
||||||
#if PHP_VERSION_ID < 80100
|
#if PHP_VERSION_ID < 80100
|
||||||
|
@ -1629,7 +1629,7 @@ zend_string * pdo_sqlsrv_dbh_last_id(_Inout_ pdo_dbh_t *dbh, _In_ const zend_str
|
||||||
#endif
|
#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(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1661,7 +1661,7 @@ zend_string * pdo_sqlsrv_dbh_last_id(_Inout_ pdo_dbh_t *dbh, _In_ const zend_str
|
||||||
strcpy_s( dbh->error_code, sizeof( dbh->error_code ),
|
strcpy_s( dbh->error_code, sizeof( dbh->error_code ),
|
||||||
reinterpret_cast<const char*>( driver_stmt->last_error()->sqlstate ));
|
reinterpret_cast<const char*>( driver_stmt->last_error()->sqlstate ));
|
||||||
driver_dbh->set_last_error( driver_stmt->last_error() );
|
driver_dbh->set_last_error( driver_stmt->last_error() );
|
||||||
|
|
||||||
if( driver_stmt ) {
|
if( driver_stmt ) {
|
||||||
driver_stmt->~sqlsrv_stmt();
|
driver_stmt->~sqlsrv_stmt();
|
||||||
}
|
}
|
||||||
|
@ -1755,7 +1755,7 @@ zend_string* pdo_sqlsrv_dbh_quote(_Inout_ pdo_dbh_t* dbh, _In_ const zend_string
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the placeholder at the current position in driver_stmt->placeholders ht
|
// get the placeholder at the current position in driver_stmt->placeholders ht
|
||||||
// Normally it's not a good idea to alter the internal pointer in a hashed array
|
// Normally it's not a good idea to alter the internal pointer in a hashed array
|
||||||
// (see pull request 634 on GitHub) but in this case this is for internal use only
|
// (see pull request 634 on GitHub) but in this case this is for internal use only
|
||||||
zval* placeholder = NULL;
|
zval* placeholder = NULL;
|
||||||
if ((placeholder = zend_hash_get_current_data(driver_stmt->placeholders)) != NULL && zend_hash_move_forward(driver_stmt->placeholders) == SUCCESS && stmt->bound_params != NULL) {
|
if ((placeholder = zend_hash_get_current_data(driver_stmt->placeholders)) != NULL && zend_hash_move_forward(driver_stmt->placeholders) == SUCCESS && stmt->bound_params != NULL) {
|
||||||
|
@ -1798,7 +1798,7 @@ zend_string* pdo_sqlsrv_dbh_quote(_Inout_ pdo_dbh_t* dbh, _In_ const zend_string
|
||||||
for (size_t index = 0; index < unquoted_len && unquoted[index] != '\0'; ++index) {
|
for (size_t index = 0; index < unquoted_len && unquoted[index] != '\0'; ++index) {
|
||||||
// On success, snprintf returns the total number of characters written
|
// On success, snprintf returns the total number of characters written
|
||||||
// On failure, a negative number is returned
|
// On failure, a negative number is returned
|
||||||
// The generated string has a length of at most len - 1, so
|
// The generated string has a length of at most len - 1, so
|
||||||
// len is 3 (2 hex digits + 1)
|
// len is 3 (2 hex digits + 1)
|
||||||
// Requires "& 0x000000FF", or snprintf will translate "0x90" to "0xFFFFFF90"
|
// Requires "& 0x000000FF", or snprintf will translate "0x90" to "0xFFFFFF90"
|
||||||
int n = snprintf((char*)(*quoted + pos), 3, "%02X", unquoted[index] & 0x000000FF);
|
int n = snprintf((char*)(*quoted + pos), 3, "%02X", unquoted[index] & 0x000000FF);
|
||||||
|
@ -1827,7 +1827,7 @@ zend_string* pdo_sqlsrv_dbh_quote(_Inout_ pdo_dbh_t* dbh, _In_ const zend_string
|
||||||
for (size_t index = 0; index < unquoted_len && unquoted_str[index] != '\0'; ++index) {
|
for (size_t index = 0; index < unquoted_len && unquoted_str[index] != '\0'; ++index) {
|
||||||
// On success, snprintf returns the total number of characters written
|
// On success, snprintf returns the total number of characters written
|
||||||
// On failure, a negative number is returned
|
// On failure, a negative number is returned
|
||||||
// The generated string has a length of at most len - 1, so
|
// The generated string has a length of at most len - 1, so
|
||||||
// len is 3 (2 hex digits + 1)
|
// len is 3 (2 hex digits + 1)
|
||||||
// Requires "& 0x000000FF", or snprintf will translate "0x90" to "0xFFFFFF90"
|
// Requires "& 0x000000FF", or snprintf will translate "0x90" to "0xFFFFFF90"
|
||||||
int n = snprintf((char*)(p + pos), 3, "%02X", unquoted_str[index] & 0x000000FF);
|
int n = snprintf((char*)(p + pos), 3, "%02X", unquoted_str[index] & 0x000000FF);
|
||||||
|
@ -1907,14 +1907,14 @@ pdo_sqlsrv_function_entry *pdo_sqlsrv_get_driver_methods( _Inout_ pdo_dbh_t *dbh
|
||||||
// As per documentation, simply return false if the method does not exist
|
// As per documentation, simply return false if the method does not exist
|
||||||
// https://www.php.net/manual/en/function.is-callable.php
|
// https://www.php.net/manual/en/function.is-callable.php
|
||||||
// But user can call PDO::errorInfo() to check the error message if necessary
|
// But user can call PDO::errorInfo() to check the error message if necessary
|
||||||
CHECK_CUSTOM_WARNING_AS_ERROR(true, driver_conn, PDO_SQLSRV_ERROR_FUNCTION_NOT_IMPLEMENTED);
|
CHECK_CUSTOM_WARNING_AS_ERROR(true, driver_conn, PDO_SQLSRV_ERROR_FUNCTION_NOT_IMPLEMENTED, NULL);
|
||||||
|
|
||||||
return NULL; // return NULL for PDO to take care of the rest
|
return NULL; // return NULL for PDO to take care of the rest
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Maps the PDO driver specific statement option/attribute constants to the core layer
|
// Maps the PDO driver specific statement option/attribute constants to the core layer
|
||||||
// statement option/attribute constants.
|
// statement option/attribute constants.
|
||||||
void add_stmt_option_key(_Inout_ sqlsrv_context& ctx, _In_ size_t key, _Inout_ HashTable* options_ht,
|
void add_stmt_option_key(_Inout_ sqlsrv_context& ctx, _In_ size_t key, _Inout_ HashTable* options_ht,
|
||||||
_Inout_ zval* data)
|
_Inout_ zval* data)
|
||||||
|
@ -1990,19 +1990,19 @@ void add_stmt_option_key(_Inout_ sqlsrv_context& ctx, _In_ size_t key, _Inout_ H
|
||||||
|
|
||||||
|
|
||||||
// validate_stmt_options
|
// validate_stmt_options
|
||||||
// Iterates through the list of statement options provided by the user and validates them
|
// Iterates through the list of statement options provided by the user and validates them
|
||||||
// against the list of statement options provided by this driver. After validation
|
// against the list of statement options provided by this driver. After validation
|
||||||
// creates a Hashtable of statement options to be sent to the core layer for processing.
|
// creates a Hashtable of statement options to be sent to the core layer for processing.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// ctx - The current context.
|
// ctx - The current context.
|
||||||
// stmt_options - The user provided list of statement options.
|
// stmt_options - The user provided list of statement options.
|
||||||
// pdo_stmt_options_ht - Output hashtable of statement options.
|
// pdo_stmt_options_ht - Output hashtable of statement options.
|
||||||
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht )
|
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* pdo_stmt_options_ht )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if( stmt_options ) {
|
if( stmt_options ) {
|
||||||
|
|
||||||
HashTable* options_ht = Z_ARRVAL_P( stmt_options );
|
HashTable* options_ht = Z_ARRVAL_P( stmt_options );
|
||||||
size_t int_key = -1;
|
size_t int_key = -1;
|
||||||
zend_string *key = NULL;
|
zend_string *key = NULL;
|
||||||
|
@ -2029,71 +2029,71 @@ void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_opti
|
||||||
void pdo_bool_conn_str_func::func( _In_ connection_option const* option, _Inout_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str )
|
void pdo_bool_conn_str_func::func( _In_ connection_option const* option, _Inout_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str )
|
||||||
{
|
{
|
||||||
char const* val_str = "no";
|
char const* val_str = "no";
|
||||||
|
|
||||||
if( core_str_zval_is_true( value ) ) {
|
if( core_str_zval_is_true( value ) ) {
|
||||||
|
|
||||||
val_str = "yes";
|
val_str = "yes";
|
||||||
}
|
}
|
||||||
|
|
||||||
conn_str += option->odbc_name;
|
conn_str += option->odbc_name;
|
||||||
conn_str += "={";
|
conn_str += "={";
|
||||||
conn_str += val_str;
|
conn_str += val_str;
|
||||||
conn_str += "};";
|
conn_str += "};";
|
||||||
}
|
}
|
||||||
|
|
||||||
void pdo_txn_isolation_conn_attr_func::func( connection_option const* /*option*/, _In_ zval* value_z, _Inout_ sqlsrv_conn* conn,
|
void pdo_txn_isolation_conn_attr_func::func( connection_option const* /*option*/, _In_ zval* value_z, _Inout_ sqlsrv_conn* conn,
|
||||||
std::string& /*conn_str*/ )
|
std::string& /*conn_str*/ )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
SQLSRV_ASSERT( Z_TYPE_P( value_z ) == IS_STRING, "pdo_txn_isolation_conn_attr_func: Unexpected zval type." );
|
SQLSRV_ASSERT( Z_TYPE_P( value_z ) == IS_STRING, "pdo_txn_isolation_conn_attr_func: Unexpected zval type." );
|
||||||
const char* val = Z_STRVAL_P( value_z );
|
const char* val = Z_STRVAL_P( value_z );
|
||||||
size_t val_len = Z_STRLEN_P( value_z );
|
size_t val_len = Z_STRLEN_P( value_z );
|
||||||
zend_long out_val = SQL_TXN_READ_COMMITTED;
|
zend_long out_val = SQL_TXN_READ_COMMITTED;
|
||||||
|
|
||||||
// READ_COMMITTED
|
// READ_COMMITTED
|
||||||
if(( val_len == ( sizeof( PDOTxnIsolationValues::READ_COMMITTED ) - 1 )
|
if(( val_len == ( sizeof( PDOTxnIsolationValues::READ_COMMITTED ) - 1 )
|
||||||
&& !strcasecmp( val, PDOTxnIsolationValues::READ_COMMITTED ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::READ_COMMITTED ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_READ_COMMITTED;
|
out_val = SQL_TXN_READ_COMMITTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// READ_UNCOMMITTED
|
// READ_UNCOMMITTED
|
||||||
else if(( val_len == ( sizeof( PDOTxnIsolationValues::READ_UNCOMMITTED ) - 1 )
|
else if(( val_len == ( sizeof( PDOTxnIsolationValues::READ_UNCOMMITTED ) - 1 )
|
||||||
&& !strcasecmp( val, PDOTxnIsolationValues::READ_UNCOMMITTED ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::READ_UNCOMMITTED ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_READ_UNCOMMITTED;
|
out_val = SQL_TXN_READ_UNCOMMITTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
// REPEATABLE_READ
|
// REPEATABLE_READ
|
||||||
else if(( val_len == ( sizeof( PDOTxnIsolationValues::REPEATABLE_READ ) - 1 )
|
else if(( val_len == ( sizeof( PDOTxnIsolationValues::REPEATABLE_READ ) - 1 )
|
||||||
&& !strcasecmp( val, PDOTxnIsolationValues::REPEATABLE_READ ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::REPEATABLE_READ ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_REPEATABLE_READ;
|
out_val = SQL_TXN_REPEATABLE_READ;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SERIALIZABLE
|
// SERIALIZABLE
|
||||||
else if(( val_len == ( sizeof( PDOTxnIsolationValues::SERIALIZABLE ) - 1 )
|
else if(( val_len == ( sizeof( PDOTxnIsolationValues::SERIALIZABLE ) - 1 )
|
||||||
&& !strcasecmp( val, PDOTxnIsolationValues::SERIALIZABLE ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::SERIALIZABLE ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_SERIALIZABLE;
|
out_val = SQL_TXN_SERIALIZABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SNAPSHOT
|
// SNAPSHOT
|
||||||
else if(( val_len == ( sizeof( PDOTxnIsolationValues::SNAPSHOT ) - 1 )
|
else if(( val_len == ( sizeof( PDOTxnIsolationValues::SNAPSHOT ) - 1 )
|
||||||
&& !strcasecmp( val, PDOTxnIsolationValues::SNAPSHOT ))) {
|
&& !strcasecmp( val, PDOTxnIsolationValues::SNAPSHOT ))) {
|
||||||
|
|
||||||
out_val = SQL_TXN_SS_SNAPSHOT;
|
out_val = SQL_TXN_SS_SNAPSHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR( true, conn, PDO_SQLSRV_ERROR_INVALID_DSN_VALUE, PDOConnOptionNames::TransactionIsolation ) {
|
CHECK_CUSTOM_ERROR( true, conn, PDO_SQLSRV_ERROR_INVALID_DSN_VALUE, PDOConnOptionNames::TransactionIsolation, NULL) {
|
||||||
|
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
core::SQLSetConnectAttr( conn, SQL_COPT_SS_TXN_ISOLATION, reinterpret_cast<SQLPOINTER>( out_val ), SQL_IS_UINTEGER );
|
core::SQLSetConnectAttr( conn, SQL_COPT_SS_TXN_ISOLATION, reinterpret_cast<SQLPOINTER>( out_val ), SQL_IS_UINTEGER );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: initialization routines for PDO_SQLSRV
|
// Contents: initialization routines for PDO_SQLSRV
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -2,20 +2,20 @@
|
||||||
// File: pdo_parser.cpp
|
// File: pdo_parser.cpp
|
||||||
//
|
//
|
||||||
// Contents: Implements a parser to parse the PDO DSN.
|
// Contents: Implements a parser to parse the PDO DSN.
|
||||||
//
|
//
|
||||||
// Copyright Microsoft Corporation
|
// Copyright Microsoft Corporation
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
|
// 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,
|
// 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 :
|
// 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 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,
|
// 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
|
// 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
|
// 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.
|
// IN THE SOFTWARE.
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ conn_string_parser:: conn_string_parser( _In_ sqlsrv_context& ctx, _In_ const ch
|
||||||
this->pos = -1;
|
this->pos = -1;
|
||||||
this->ctx = &ctx;
|
this->ctx = &ctx;
|
||||||
this->current_key = 0;
|
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 )
|
sql_string_parser:: sql_string_parser( _In_ sqlsrv_context& ctx, _In_ const char* sql_str, _In_ int len, _In_ HashTable* placeholders_ht )
|
||||||
|
@ -55,16 +55,16 @@ inline bool string_parser::next( void )
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLSRV_ASSERT( this->pos < len, "Unexpected cursor position in conn_string_parser::next" );
|
SQLSRV_ASSERT( this->pos < len, "Unexpected cursor position in conn_string_parser::next" );
|
||||||
|
|
||||||
this->pos++;
|
this->pos++;
|
||||||
|
|
||||||
if ( this->is_eos() ) {
|
if ( this->is_eos() ) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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" );
|
SQLSRV_ASSERT(this->pos < len, "Unexpected cursor position in conn_string_parser::is_eos" );
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for white space.
|
// Check for white space.
|
||||||
inline bool string_parser::is_white_space( _In_ char c )
|
inline bool string_parser::is_white_space( _In_ char c )
|
||||||
{
|
{
|
||||||
if( c == ' ' || c == '\r' || c == '\n' || c == '\t' ) {
|
if( c == ' ' || c == '\r' || c == '\n' || c == '\t' ) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -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 )
|
int conn_string_parser::discard_trailing_white_spaces( _In_reads_(len) const char* str, _Inout_ int len )
|
||||||
{
|
{
|
||||||
const char* end = str + ( len - 1 );
|
const char* end = str + ( len - 1 );
|
||||||
|
|
||||||
while(( this->is_white_space( *end ) ) && (len > 0) ) {
|
while(( this->is_white_space( *end ) ) && (len > 0) ) {
|
||||||
|
|
||||||
len--;
|
len--;
|
||||||
end--;
|
end--;
|
||||||
}
|
}
|
||||||
|
@ -108,16 +108,16 @@ int conn_string_parser::discard_trailing_white_spaces( _In_reads_(len) const cha
|
||||||
bool string_parser::discard_white_spaces()
|
bool string_parser::discard_white_spaces()
|
||||||
{
|
{
|
||||||
if( this->is_eos() ) {
|
if( this->is_eos() ) {
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
while( this->is_white_space( this->orig_str[pos] )) {
|
while( this->is_white_space( this->orig_str[pos] )) {
|
||||||
|
|
||||||
if( !next() )
|
if( !next() )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,22 +128,22 @@ void string_parser::add_key_value_pair( _In_reads_(len) const char* value, _In_
|
||||||
ZVAL_UNDEF( &value_z );
|
ZVAL_UNDEF( &value_z );
|
||||||
|
|
||||||
if( len == 0 ) {
|
if( len == 0 ) {
|
||||||
|
|
||||||
ZVAL_STRINGL( &value_z, "", 0);
|
ZVAL_STRINGL( &value_z, "", 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
ZVAL_STRINGL( &value_z, const_cast<char*>( value ), len );
|
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
|
// Add a key-value pair to the hashtable with int value
|
||||||
void sql_string_parser::add_key_int_value_pair( _In_ unsigned int value ) {
|
void sql_string_parser::add_key_int_value_pair( _In_ unsigned int value ) {
|
||||||
zval value_z;
|
zval value_z;
|
||||||
ZVAL_LONG( &value_z, value );
|
ZVAL_LONG( &value_z, value );
|
||||||
|
|
||||||
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 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 ));
|
key_name = static_cast<char*>( sqlsrv_malloc( new_len + 1 ));
|
||||||
memcpy_s( key_name, new_len + 1 ,key, new_len );
|
memcpy_s( key_name, new_len + 1 ,key, new_len );
|
||||||
|
|
||||||
key_name[new_len] = '\0';
|
key_name[new_len] = '\0';
|
||||||
|
|
||||||
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_KEY, 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 )
|
inline bool sql_string_parser::is_placeholder_char( char c )
|
||||||
|
@ -183,7 +183,7 @@ inline bool sql_string_parser::is_placeholder_char( char c )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Primary function which parses the connection string/DSN.
|
// 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
|
States state = FirstKeyValuePair; // starting state
|
||||||
int start_pos = -1;
|
int start_pos = -1;
|
||||||
|
@ -191,17 +191,17 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
try {
|
try {
|
||||||
|
|
||||||
while( !this->is_eos() ) {
|
while( !this->is_eos() ) {
|
||||||
|
|
||||||
switch( state ) {
|
switch( state ) {
|
||||||
|
|
||||||
case FirstKeyValuePair:
|
case FirstKeyValuePair:
|
||||||
{
|
{
|
||||||
// discard leading spaces
|
// discard leading spaces
|
||||||
if( !next() || !discard_white_spaces() ) {
|
if( !next() || !discard_white_spaces() ) {
|
||||||
|
|
||||||
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_STRING ); //EOS
|
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_STRING ); //EOS
|
||||||
}
|
}
|
||||||
|
|
||||||
state = Key;
|
state = Key;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -212,15 +212,15 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
|
|
||||||
// read the key name
|
// read the key name
|
||||||
while( this->orig_str[pos] != '=' ) {
|
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 ) );
|
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 ) );
|
||||||
|
|
||||||
state = Value;
|
state = Value;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -239,23 +239,23 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
add_key_value_pair( NULL, 0 );
|
add_key_value_pair( NULL, 0 );
|
||||||
|
|
||||||
if( this->is_eos() ) {
|
if( this->is_eos() ) {
|
||||||
|
|
||||||
break; // EOS
|
break; // EOS
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// this->orig_str[pos] == ';'
|
// this->orig_str[pos] == ';'
|
||||||
state = NextKeyValuePair;
|
state = NextKeyValuePair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if LCB
|
// if LCB
|
||||||
else if( this->orig_str[pos] == '{' ) {
|
else if( this->orig_str[pos] == '{' ) {
|
||||||
|
|
||||||
start_pos = this->pos; // starting character is LCB
|
start_pos = this->pos; // starting character is LCB
|
||||||
state = ValueContent1;
|
state = ValueContent1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If NonSP-LCB-SC
|
// If NonSP-LCB-SC
|
||||||
else {
|
else {
|
||||||
|
|
||||||
|
@ -269,10 +269,10 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
case ValueContent1:
|
case ValueContent1:
|
||||||
{
|
{
|
||||||
while ( this->orig_str[pos] != '}' ) {
|
while ( this->orig_str[pos] != '}' ) {
|
||||||
|
|
||||||
if ( ! next() ) {
|
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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,20 +287,20 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
while( this->orig_str[pos] != ';' ) {
|
while( this->orig_str[pos] != ';' ) {
|
||||||
|
|
||||||
if( ! next() ) {
|
if( ! next() ) {
|
||||||
|
|
||||||
break; //EOS
|
break; //EOS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !this->is_eos() && this->orig_str[pos] == ';' ) {
|
if( !this->is_eos() && this->orig_str[pos] == ';' ) {
|
||||||
|
|
||||||
// semi-colon encountered, so go to next key-value pair
|
// semi-colon encountered, so go to next key-value pair
|
||||||
state = NextKeyValuePair;
|
state = NextKeyValuePair;
|
||||||
}
|
}
|
||||||
|
|
||||||
add_key_value_pair( &( this->orig_str[start_pos] ), this->pos - start_pos );
|
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 " );
|
"conn_string_parser::parse_conn_string: Invalid state encountered " );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -308,7 +308,7 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
|
|
||||||
case RCBEncountered:
|
case RCBEncountered:
|
||||||
{
|
{
|
||||||
|
|
||||||
// Read the next character after RCB.
|
// Read the next character after RCB.
|
||||||
if( !next() ) {
|
if( !next() ) {
|
||||||
|
|
||||||
|
@ -321,11 +321,11 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
|
|
||||||
// if second RCB encountered than go back to ValueContent1
|
// if second RCB encountered than go back to ValueContent1
|
||||||
if( this->orig_str[pos] == '}' ) {
|
if( this->orig_str[pos] == '}' ) {
|
||||||
|
|
||||||
if( !next() ) {
|
if( !next() ) {
|
||||||
|
|
||||||
// EOS after a second RCB is error
|
// 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;
|
state = ValueContent1;
|
||||||
|
@ -336,9 +336,9 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
|
|
||||||
// discard any trailing white-spaces.
|
// discard any trailing white-spaces.
|
||||||
if( this->is_white_space( this->orig_str[pos] )) {
|
if( this->is_white_space( this->orig_str[pos] )) {
|
||||||
|
|
||||||
if( ! this->discard_white_spaces() ) {
|
if( ! this->discard_white_spaces() ) {
|
||||||
|
|
||||||
//EOS
|
//EOS
|
||||||
add_key_value_pair( &( this->orig_str[start_pos] ), end_pos - start_pos );
|
add_key_value_pair( &( this->orig_str[start_pos] ), end_pos - start_pos );
|
||||||
break;
|
break;
|
||||||
|
@ -347,32 +347,32 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
|
|
||||||
// if semi-colon than go to next key-value pair
|
// if semi-colon than go to next key-value pair
|
||||||
if ( this->orig_str[pos] == ';' ) {
|
if ( this->orig_str[pos] == ';' ) {
|
||||||
|
|
||||||
add_key_value_pair( &( this->orig_str[start_pos] ), end_pos - start_pos );
|
add_key_value_pair( &( this->orig_str[start_pos] ), end_pos - start_pos );
|
||||||
state = NextKeyValuePair;
|
state = NextKeyValuePair;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Non - (RCB, SP*, SC, EOS) character. Any other character after an RCB is an error.
|
// 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 );
|
THROW_PDO_ERROR( this->ctx, PDO_SQLSRV_ERROR_INVALID_DSN_VALUE, this->current_key_name, NULL );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NextKeyValuePair:
|
case NextKeyValuePair:
|
||||||
{
|
{
|
||||||
SQLSRV_ASSERT(( this->orig_str[pos] == ';' ),
|
SQLSRV_ASSERT(( this->orig_str[pos] == ';' ),
|
||||||
"conn_string_parser::parse_conn_string: semi-colon was expected." );
|
"conn_string_parser::parse_conn_string: semi-colon was expected." );
|
||||||
|
|
||||||
// Call next() to skip the semi-colon.
|
// Call next() to skip the semi-colon.
|
||||||
if( !next() || !this->discard_white_spaces() ) {
|
if( !next() || !this->discard_white_spaces() ) {
|
||||||
|
|
||||||
// EOS
|
// EOS
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( this->orig_str[pos] == ';' ) {
|
if( this->orig_str[pos] == ';' ) {
|
||||||
|
|
||||||
// a second semi-colon is error case.
|
// 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 {
|
else {
|
||||||
|
@ -384,7 +384,7 @@ void conn_string_parser:: parse_conn_string( void )
|
||||||
} //case NextKeyValuePair
|
} //case NextKeyValuePair
|
||||||
} // switch
|
} // switch
|
||||||
} //while
|
} //while
|
||||||
}
|
}
|
||||||
catch( pdo::PDOException& ) {
|
catch( pdo::PDOException& ) {
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
|
|
|
@ -3,17 +3,17 @@
|
||||||
//
|
//
|
||||||
// Contents: Implements the PDOStatement object for the PDO_SQLSRV
|
// Contents: Implements the PDOStatement object for the PDO_SQLSRV
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
|
// 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,
|
// 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 :
|
// 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 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,
|
// 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
|
// 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
|
// 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.
|
// IN THE SOFTWARE.
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ SQLSRV_PHPTYPE pdo_type_to_sqlsrv_php_type( _Inout_ sqlsrv_stmt* driver_stmt, _I
|
||||||
{
|
{
|
||||||
pdo_sqlsrv_stmt *pdo_stmt = static_cast<pdo_sqlsrv_stmt*>(driver_stmt);
|
pdo_sqlsrv_stmt *pdo_stmt = static_cast<pdo_sqlsrv_stmt*>(driver_stmt);
|
||||||
SQLSRV_ASSERT(pdo_stmt != NULL, "pdo_type_to_sqlsrv_php_type: pdo_stmt object was null");
|
SQLSRV_ASSERT(pdo_stmt != NULL, "pdo_type_to_sqlsrv_php_type: pdo_stmt object was null");
|
||||||
|
|
||||||
switch( pdo_type ) {
|
switch( pdo_type ) {
|
||||||
|
|
||||||
case PDO_PARAM_BOOL:
|
case PDO_PARAM_BOOL:
|
||||||
|
@ -66,10 +66,10 @@ SQLSRV_PHPTYPE pdo_type_to_sqlsrv_php_type( _Inout_ sqlsrv_stmt* driver_stmt, _I
|
||||||
|
|
||||||
case PDO_PARAM_STR:
|
case PDO_PARAM_STR:
|
||||||
return SQLSRV_PHPTYPE_STRING;
|
return SQLSRV_PHPTYPE_STRING;
|
||||||
|
|
||||||
case PDO_PARAM_NULL:
|
case PDO_PARAM_NULL:
|
||||||
return SQLSRV_PHPTYPE_NULL;
|
return SQLSRV_PHPTYPE_NULL;
|
||||||
|
|
||||||
case PDO_PARAM_LOB:
|
case PDO_PARAM_LOB:
|
||||||
if (pdo_stmt->fetch_datetime) {
|
if (pdo_stmt->fetch_datetime) {
|
||||||
return SQLSRV_PHPTYPE_DATETIME;
|
return SQLSRV_PHPTYPE_DATETIME;
|
||||||
|
@ -84,8 +84,8 @@ SQLSRV_PHPTYPE pdo_type_to_sqlsrv_php_type( _Inout_ sqlsrv_stmt* driver_stmt, _I
|
||||||
default:
|
default:
|
||||||
DIE( "pdo_type_to_sqlsrv_php_type: Unexpected pdo_param_type encountered" );
|
DIE( "pdo_type_to_sqlsrv_php_type: Unexpected pdo_param_type encountered" );
|
||||||
}
|
}
|
||||||
|
|
||||||
return SQLSRV_PHPTYPE_INVALID; // to prevent compiler warning
|
return SQLSRV_PHPTYPE_INVALID; // to prevent compiler warning
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a pdo type for a given SQL type. See pdo_param_type
|
// Returns a pdo type for a given SQL type. See pdo_param_type
|
||||||
|
@ -104,7 +104,7 @@ inline pdo_param_type sql_type_to_pdo_type( _In_ SQLSMALLINT sql_type )
|
||||||
case SQL_BINARY:
|
case SQL_BINARY:
|
||||||
case SQL_CHAR:
|
case SQL_CHAR:
|
||||||
case SQL_DECIMAL:
|
case SQL_DECIMAL:
|
||||||
case SQL_DOUBLE:
|
case SQL_DOUBLE:
|
||||||
case SQL_FLOAT:
|
case SQL_FLOAT:
|
||||||
case SQL_GUID:
|
case SQL_GUID:
|
||||||
case SQL_LONGVARBINARY:
|
case SQL_LONGVARBINARY:
|
||||||
|
@ -159,9 +159,9 @@ void set_stmt_cursors( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z )
|
||||||
|
|
||||||
default:
|
default:
|
||||||
THROW_PDO_ERROR( stmt, PDO_SQLSRV_ERROR_INVALID_CURSOR_TYPE );
|
THROW_PDO_ERROR( stmt, PDO_SQLSRV_ERROR_INVALID_CURSOR_TYPE );
|
||||||
}
|
}
|
||||||
|
|
||||||
core_sqlsrv_set_scrollable( stmt, odbc_cursor_type );
|
core_sqlsrv_set_scrollable( stmt, odbc_cursor_type );
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_stmt_cursor_scroll_type( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z )
|
void set_stmt_cursor_scroll_type( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z )
|
||||||
|
@ -178,12 +178,12 @@ void set_stmt_cursor_scroll_type( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z
|
||||||
|
|
||||||
long odbc_cursor_type = static_cast<long>( Z_LVAL_P( value_z ) );
|
long odbc_cursor_type = static_cast<long>( Z_LVAL_P( value_z ) );
|
||||||
|
|
||||||
core_sqlsrv_set_scrollable( stmt, odbc_cursor_type );
|
core_sqlsrv_set_scrollable( stmt, odbc_cursor_type );
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the statement encoding. Default encoding on the statement
|
// Sets the statement encoding. Default encoding on the statement
|
||||||
// implies use the connection's encoding.
|
// implies use the connection's encoding.
|
||||||
void set_stmt_encoding( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z )
|
void set_stmt_encoding( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z )
|
||||||
{
|
{
|
||||||
|
@ -192,9 +192,9 @@ void set_stmt_encoding( _Inout_ sqlsrv_stmt* stmt, _In_ zval* value_z )
|
||||||
|
|
||||||
THROW_PDO_ERROR( stmt, PDO_SQLSRV_ERROR_INVALID_ENCODING );
|
THROW_PDO_ERROR( stmt, PDO_SQLSRV_ERROR_INVALID_ENCODING );
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_long attr_value = Z_LVAL_P( value_z );
|
zend_long attr_value = Z_LVAL_P( value_z );
|
||||||
|
|
||||||
switch( attr_value ) {
|
switch( attr_value ) {
|
||||||
|
|
||||||
// when the default encoding is applied to a statement, it means use the creating connection's encoding
|
// when the default encoding is applied to a statement, it means use the creating connection's encoding
|
||||||
|
@ -269,7 +269,7 @@ zval convert_to_zval(_Inout_ sqlsrv_stmt* stmt, _In_ SQLSRV_PHPTYPE sqlsrv_php_t
|
||||||
return out_zval;
|
return out_zval;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
int pdo_sqlsrv_stmt_dtor( _Inout_ pdo_stmt_t *stmt );
|
int pdo_sqlsrv_stmt_dtor( _Inout_ pdo_stmt_t *stmt );
|
||||||
int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt );
|
int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt );
|
||||||
|
@ -309,7 +309,7 @@ struct pdo_stmt_methods pdo_sqlsrv_stmt_methods = {
|
||||||
|
|
||||||
void stmt_option_pdo_scrollable:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z )
|
void stmt_option_pdo_scrollable:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z )
|
||||||
{
|
{
|
||||||
set_stmt_cursors( stmt, value_z );
|
set_stmt_cursors( stmt, value_z );
|
||||||
}
|
}
|
||||||
|
|
||||||
void stmt_option_encoding:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z )
|
void stmt_option_encoding:: operator()( _Inout_ sqlsrv_stmt* stmt, stmt_option const* /*opt*/, _In_ zval* value_z )
|
||||||
|
@ -391,7 +391,7 @@ int pdo_sqlsrv_stmt_close_cursor( _Inout_ pdo_stmt_t *stmt )
|
||||||
|
|
||||||
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_close_cursor: driver_data object was null" );
|
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_close_cursor: driver_data object was null" );
|
||||||
|
|
||||||
// to "close the cursor" means we make the statement ready for execution again. To do this, we
|
// to "close the cursor" means we make the statement ready for execution again. To do this, we
|
||||||
// skip all the result sets on the current statement.
|
// skip all the result sets on the current statement.
|
||||||
// If the statement has not been executed there are no next results to iterate over.
|
// If the statement has not been executed there are no next results to iterate over.
|
||||||
if ( driver_stmt && driver_stmt->executed == true )
|
if ( driver_stmt && driver_stmt->executed == true )
|
||||||
|
@ -414,7 +414,7 @@ int pdo_sqlsrv_stmt_close_cursor( _Inout_ pdo_stmt_t *stmt )
|
||||||
}
|
}
|
||||||
|
|
||||||
// pdo_sqlsrv_stmt_describe_col
|
// pdo_sqlsrv_stmt_describe_col
|
||||||
// Gets the metadata for a column based on the column number.
|
// Gets the metadata for a column based on the column number.
|
||||||
// Calls the core_sqlsrv_field_metadata function present in the core layer.
|
// Calls the core_sqlsrv_field_metadata function present in the core layer.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// *stmt - pointer to current statement
|
// *stmt - pointer to current statement
|
||||||
|
@ -433,7 +433,7 @@ int pdo_sqlsrv_stmt_describe_col( _Inout_ pdo_stmt_t *stmt, _In_ int colno)
|
||||||
sqlsrv_malloc_auto_ptr<field_meta_data> core_meta_data;
|
sqlsrv_malloc_auto_ptr<field_meta_data> core_meta_data;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
core_meta_data = core_sqlsrv_field_metadata( reinterpret_cast<sqlsrv_stmt*>( stmt->driver_data ), colno );
|
core_meta_data = core_sqlsrv_field_metadata( reinterpret_cast<sqlsrv_stmt*>( stmt->driver_data ), colno );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,20 +448,20 @@ int pdo_sqlsrv_stmt_describe_col( _Inout_ pdo_stmt_t *stmt, _In_ int colno)
|
||||||
pdo_column_data* column_data = &(stmt->columns[colno]);
|
pdo_column_data* column_data = &(stmt->columns[colno]);
|
||||||
|
|
||||||
SQLSRV_ASSERT( column_data != NULL, "pdo_sqsrv_stmt_describe_col: pdo_column_data was null" );
|
SQLSRV_ASSERT( column_data != NULL, "pdo_sqsrv_stmt_describe_col: pdo_column_data was null" );
|
||||||
|
|
||||||
// Set the name
|
// Set the name
|
||||||
column_data->name = zend_string_init( (const char*)core_meta_data->field_name.get(), core_meta_data->field_name_len, 0 );
|
column_data->name = zend_string_init( (const char*)core_meta_data->field_name.get(), core_meta_data->field_name_len, 0 );
|
||||||
|
|
||||||
// Set the maxlen
|
// Set the maxlen
|
||||||
column_data->maxlen = ( core_meta_data->field_precision > 0 ) ? core_meta_data->field_precision : core_meta_data->field_size;
|
column_data->maxlen = ( core_meta_data->field_precision > 0 ) ? core_meta_data->field_precision : core_meta_data->field_size;
|
||||||
|
|
||||||
// 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
|
#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
|
#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" );
|
||||||
|
@ -474,7 +474,7 @@ int pdo_sqlsrv_stmt_describe_col( _Inout_ pdo_stmt_t *stmt, _In_ int colno)
|
||||||
|
|
||||||
|
|
||||||
// pdo_sqlsrv_stmt_dtor
|
// pdo_sqlsrv_stmt_dtor
|
||||||
// Maps to PDOStatement::__destruct. Destructor for the PDO Statement.
|
// Maps to PDOStatement::__destruct. Destructor for the PDO Statement.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// *stmt - pointer to current statement
|
// *stmt - pointer to current statement
|
||||||
// Return:
|
// Return:
|
||||||
|
@ -512,7 +512,7 @@ int pdo_sqlsrv_stmt_dtor( _Inout_ pdo_stmt_t *stmt )
|
||||||
}
|
}
|
||||||
|
|
||||||
// pdo_sqlsrv_stmt_execute
|
// pdo_sqlsrv_stmt_execute
|
||||||
// Maps to PDOStatement::Execute. Executes the prepared statement.
|
// Maps to PDOStatement::Execute. Executes the prepared statement.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// *stmt - pointer to the current statement.
|
// *stmt - pointer to the current statement.
|
||||||
// Return:
|
// Return:
|
||||||
|
@ -537,7 +537,7 @@ int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt )
|
||||||
core_sqlsrv_next_result( driver_stmt, false );
|
core_sqlsrv_next_result( driver_stmt, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* query = NULL;
|
const char* query = NULL;
|
||||||
unsigned int query_len = 0;
|
unsigned int query_len = 0;
|
||||||
|
|
||||||
|
@ -548,11 +548,11 @@ int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt )
|
||||||
query_len = static_cast<unsigned int>( driver_stmt->direct_query_subst_string_len );
|
query_len = static_cast<unsigned int>( driver_stmt->direct_query_subst_string_len );
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the user is using prepare emulation (PDO::ATTR_EMULATE_PREPARES), set the query to the
|
// if the user is using prepare emulation (PDO::ATTR_EMULATE_PREPARES), set the query to the
|
||||||
// subtituted query provided by PDO
|
// subtituted query provided by PDO
|
||||||
if (stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
|
if (stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
|
||||||
// reset the placeholders hashtable internal in case the user reexecutes a statement
|
// reset the placeholders hashtable internal in case the user reexecutes a statement
|
||||||
// Normally it's not a good idea to alter the internal pointer in a hashed array
|
// Normally it's not a good idea to alter the internal pointer in a hashed array
|
||||||
// (see pull request 634 on GitHub) but in this case this is for internal use only
|
// (see pull request 634 on GitHub) but in this case this is for internal use only
|
||||||
|
|
||||||
zend_hash_internal_pointer_reset(driver_stmt->placeholders);
|
zend_hash_internal_pointer_reset(driver_stmt->placeholders);
|
||||||
|
@ -567,10 +567,10 @@ int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt )
|
||||||
}
|
}
|
||||||
|
|
||||||
// The query timeout setting is inherited from the corresponding connection attribute, but
|
// The query timeout setting is inherited from the corresponding connection attribute, but
|
||||||
// the user may have changed the query timeout setting again before this via
|
// the user may have changed the query timeout setting again before this via
|
||||||
// PDOStatement::setAttribute()
|
// PDOStatement::setAttribute()
|
||||||
driver_stmt->set_query_timeout();
|
driver_stmt->set_query_timeout();
|
||||||
|
|
||||||
SQLRETURN execReturn = core_sqlsrv_execute( driver_stmt, query, query_len );
|
SQLRETURN execReturn = core_sqlsrv_execute( driver_stmt, query, query_len );
|
||||||
|
|
||||||
if ( execReturn == SQL_NO_DATA ) {
|
if ( execReturn == SQL_NO_DATA ) {
|
||||||
|
@ -598,13 +598,13 @@ int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// workaround for a bug in the PDO driver manager. It is fairly simple to crash the PDO driver manager with
|
// workaround for a bug in the PDO driver manager. It is fairly simple to crash the PDO driver manager with
|
||||||
// the following sequence:
|
// the following sequence:
|
||||||
// 1) Prepare and execute a statement (that has some results with it)
|
// 1) Prepare and execute a statement (that has some results with it)
|
||||||
// 2) call PDOStatement::nextRowset until there are no more results
|
// 2) call PDOStatement::nextRowset until there are no more results
|
||||||
// 3) execute the statement again
|
// 3) execute the statement again
|
||||||
// 4) call PDOStatement::getColumnMeta
|
// 4) call PDOStatement::getColumnMeta
|
||||||
// It crashes from what I can tell because there is no metadata because there was no call to
|
// It crashes from what I can tell because there is no metadata because there was no call to
|
||||||
// pdo_stmt_sqlsrv_describe_col and stmt->columns is NULL on the second call to
|
// pdo_stmt_sqlsrv_describe_col and stmt->columns is NULL on the second call to
|
||||||
// PDO::execute. My guess is that because stmt->executed is true, it optimizes away a necessary call to
|
// PDO::execute. My guess is that because stmt->executed is true, it optimizes away a necessary call to
|
||||||
// pdo_sqlsrv_stmt_describe_col. By setting the stmt->executed flag to 0, this call is not optimized away
|
// pdo_sqlsrv_stmt_describe_col. By setting the stmt->executed flag to 0, this call is not optimized away
|
||||||
|
@ -632,8 +632,8 @@ int pdo_sqlsrv_stmt_execute( _Inout_ pdo_stmt_t *stmt )
|
||||||
|
|
||||||
// pdo_sqlsrv_stmt_fetch
|
// pdo_sqlsrv_stmt_fetch
|
||||||
// Maps to PDOStatement::fetch
|
// Maps to PDOStatement::fetch
|
||||||
// Move the cursor to the record indicated. If the cursor is moved off the end,
|
// Move the cursor to the record indicated. If the cursor is moved off the end,
|
||||||
// or before the beginning if a scrollable cursor is created, then FAILURE is returned.
|
// or before the beginning if a scrollable cursor is created, then FAILURE is returned.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// *stmt - pointer to current statement for which the cursor should be moved.
|
// *stmt - pointer to current statement for which the cursor should be moved.
|
||||||
// ori - cursor orientation. Maps to the list of PDO::FETCH_ORI_* constants
|
// ori - cursor orientation. Maps to the list of PDO::FETCH_ORI_* constants
|
||||||
|
@ -648,7 +648,7 @@ int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orienta
|
||||||
PDO_LOG_STMT_ENTRY;
|
PDO_LOG_STMT_ENTRY;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
SQLSRV_ASSERT( stmt != NULL, "pdo_sqlsrv_stmt_fetch: pdo_stmt object was null" );
|
SQLSRV_ASSERT( stmt != NULL, "pdo_sqlsrv_stmt_fetch: 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 );
|
||||||
|
@ -678,7 +678,7 @@ int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orienta
|
||||||
}
|
}
|
||||||
|
|
||||||
for( long i = 0; i < stmt->column_count; ++i ) {
|
for( long i = 0; i < stmt->column_count; ++i ) {
|
||||||
|
|
||||||
#if PHP_VERSION_ID < 80100
|
#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))))) {
|
||||||
|
@ -709,8 +709,8 @@ int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orienta
|
||||||
|
|
||||||
// support for the PDO rowCount method. Since rowCount doesn't call a
|
// support for the PDO rowCount method. Since rowCount doesn't call a
|
||||||
// method, PDO relies on us to fill the pdo_stmt_t::row_count member
|
// method, PDO relies on us to fill the pdo_stmt_t::row_count member
|
||||||
// The if condition was changed from
|
// The if condition was changed from
|
||||||
// `driver_stmt->past_fetch_end || driver_stmt->cursor_type != SQL_CURSOR_FORWARD_ONLY`
|
// `driver_stmt->past_fetch_end || driver_stmt->cursor_type != SQL_CURSOR_FORWARD_ONLY`
|
||||||
// because it caused SQLRowCount to be called at each fetch if using a non-forward cursor
|
// because it caused SQLRowCount to be called at each fetch if using a non-forward cursor
|
||||||
// which is unnecessary and a performance hit
|
// which is unnecessary and a performance hit
|
||||||
if( driver_stmt->past_fetch_end || driver_stmt->cursor_type == SQL_CURSOR_DYNAMIC) {
|
if( driver_stmt->past_fetch_end || driver_stmt->cursor_type == SQL_CURSOR_DYNAMIC) {
|
||||||
|
@ -738,7 +738,7 @@ int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orienta
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch( ... ) {
|
catch( ... ) {
|
||||||
|
|
||||||
DIE ("pdo_sqlsrv_stmt_fetch: Unexpected exception occurred.");
|
DIE ("pdo_sqlsrv_stmt_fetch: Unexpected 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
|
||||||
|
@ -747,9 +747,9 @@ int pdo_sqlsrv_stmt_fetch( _Inout_ pdo_stmt_t *stmt, _In_ enum pdo_fetch_orienta
|
||||||
|
|
||||||
// pdo_sqlsrv_stmt_get_col_data
|
// pdo_sqlsrv_stmt_get_col_data
|
||||||
// Called by the set of PDO Fetch functions.
|
// Called by the set of PDO Fetch functions.
|
||||||
// Retrieves a single column. PDO driver manager is responsible for freeing the
|
// Retrieves a single column. PDO driver manager is responsible for freeing the
|
||||||
// returned buffer. Because PDO can request fields out of order and ODBC does not
|
// returned buffer. Because PDO can request fields out of order and ODBC does not
|
||||||
// support out of order field requests, this function should also cache fields.
|
// support out of order field requests, this function should also cache fields.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// stmt - Statement to retrive the column for.
|
// stmt - Statement to retrive the column for.
|
||||||
// colno - Index of the column that needs to be retrieved. Starts with 0.
|
// colno - Index of the column that needs to be retrieved. Starts with 0.
|
||||||
|
@ -770,7 +770,7 @@ int pdo_sqlsrv_stmt_get_col_data(_Inout_ pdo_stmt_t *stmt, _In_ int colno, _Inou
|
||||||
PDO_RESET_STMT_ERROR;
|
PDO_RESET_STMT_ERROR;
|
||||||
PDO_VALIDATE_STMT;
|
PDO_VALIDATE_STMT;
|
||||||
PDO_LOG_STMT_ENTRY;
|
PDO_LOG_STMT_ENTRY;
|
||||||
|
|
||||||
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");
|
||||||
|
@ -784,7 +784,7 @@ int pdo_sqlsrv_stmt_get_col_data(_Inout_ pdo_stmt_t *stmt, _In_ int colno, _Inou
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PHP_VERSION_ID < 80100
|
#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
|
#endif
|
||||||
|
|
||||||
|
@ -801,7 +801,7 @@ int pdo_sqlsrv_stmt_get_col_data(_Inout_ pdo_stmt_t *stmt, _In_ int colno, _Inou
|
||||||
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 PHP_VERSION_ID < 80100
|
#if PHP_VERSION_ID < 80100
|
||||||
if (stmt->bound_columns && driver_stmt->bound_column_param_types[colno] != PDO_PARAM_ZVAL) {
|
if (stmt->bound_columns && driver_stmt->bound_column_param_types[colno] != PDO_PARAM_ZVAL) {
|
||||||
|
@ -822,13 +822,13 @@ int pdo_sqlsrv_stmt_get_col_data(_Inout_ pdo_stmt_t *stmt, _In_ int colno, _Inou
|
||||||
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, NULL) {
|
||||||
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, NULL) {
|
||||||
|
|
||||||
throw pdo::PDOException();
|
throw pdo::PDOException();
|
||||||
}
|
}
|
||||||
|
@ -841,7 +841,7 @@ int pdo_sqlsrv_stmt_get_col_data(_Inout_ pdo_stmt_t *stmt, _In_ int colno, _Inou
|
||||||
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, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -870,7 +870,7 @@ int pdo_sqlsrv_stmt_get_col_data(_Inout_ pdo_stmt_t *stmt, _In_ int colno, _Inou
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
catch ( core::CoreException& ) {
|
catch ( core::CoreException& ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -909,11 +909,11 @@ int pdo_sqlsrv_stmt_set_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _In
|
||||||
case SQLSRV_ATTR_ENCODING:
|
case SQLSRV_ATTR_ENCODING:
|
||||||
set_stmt_encoding( driver_stmt, val );
|
set_stmt_encoding( driver_stmt, val );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PDO_ATTR_CURSOR:
|
case PDO_ATTR_CURSOR:
|
||||||
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_CURSOR_ATTR_AT_PREPARE_ONLY );
|
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_CURSOR_ATTR_AT_PREPARE_ONLY );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQLSRV_ATTR_QUERY_TIMEOUT:
|
case SQLSRV_ATTR_QUERY_TIMEOUT:
|
||||||
core_sqlsrv_set_query_timeout( driver_stmt, val );
|
core_sqlsrv_set_query_timeout( driver_stmt, val );
|
||||||
break;
|
break;
|
||||||
|
@ -976,7 +976,7 @@ int pdo_sqlsrv_stmt_get_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _In
|
||||||
PDO_RESET_STMT_ERROR;
|
PDO_RESET_STMT_ERROR;
|
||||||
PDO_VALIDATE_STMT;
|
PDO_VALIDATE_STMT;
|
||||||
PDO_LOG_STMT_ENTRY;
|
PDO_LOG_STMT_ENTRY;
|
||||||
|
|
||||||
pdo_sqlsrv_stmt* driver_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
|
pdo_sqlsrv_stmt* driver_stmt = static_cast<pdo_sqlsrv_stmt*>( stmt->driver_data );
|
||||||
SQLSRV_ASSERT(( driver_stmt != NULL ), "pdo_sqlsrv_stmt_get_attr: stmt->driver_data was null" );
|
SQLSRV_ASSERT(( driver_stmt != NULL ), "pdo_sqlsrv_stmt_get_attr: stmt->driver_data was null" );
|
||||||
|
|
||||||
|
@ -991,27 +991,27 @@ int pdo_sqlsrv_stmt_get_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _In
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQLSRV_ATTR_ENCODING:
|
case SQLSRV_ATTR_ENCODING:
|
||||||
{
|
{
|
||||||
ZVAL_LONG( return_value, driver_stmt->encoding() );
|
ZVAL_LONG( return_value, driver_stmt->encoding() );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PDO_ATTR_CURSOR:
|
case PDO_ATTR_CURSOR:
|
||||||
{
|
{
|
||||||
ZVAL_LONG( return_value, ( driver_stmt->cursor_type != SQL_CURSOR_FORWARD_ONLY ?
|
ZVAL_LONG( return_value, ( driver_stmt->cursor_type != SQL_CURSOR_FORWARD_ONLY ?
|
||||||
PDO_CURSOR_SCROLL : PDO_CURSOR_FWDONLY ));
|
PDO_CURSOR_SCROLL : PDO_CURSOR_FWDONLY ));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
|
case SQLSRV_ATTR_CURSOR_SCROLL_TYPE:
|
||||||
{
|
{
|
||||||
ZVAL_LONG( return_value, driver_stmt->cursor_type );
|
ZVAL_LONG( return_value, driver_stmt->cursor_type );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
|
case SQLSRV_ATTR_CLIENT_BUFFER_MAX_KB_SIZE:
|
||||||
{
|
{
|
||||||
ZVAL_LONG( return_value, driver_stmt->buffered_query_limit );
|
ZVAL_LONG( return_value, driver_stmt->buffered_query_limit );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1041,7 +1041,7 @@ int pdo_sqlsrv_stmt_get_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _In
|
||||||
|
|
||||||
case SQLSRV_ATTR_DECIMAL_PLACES:
|
case SQLSRV_ATTR_DECIMAL_PLACES:
|
||||||
{
|
{
|
||||||
ZVAL_LONG( return_value, driver_stmt->decimal_places );
|
ZVAL_LONG( return_value, driver_stmt->decimal_places );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1069,9 +1069,9 @@ int pdo_sqlsrv_stmt_get_attr( _Inout_ pdo_stmt_t *stmt, _In_ zend_long attr, _In
|
||||||
}
|
}
|
||||||
|
|
||||||
// pdo_sqlsrv_stmt_get_col_meta
|
// pdo_sqlsrv_stmt_get_col_meta
|
||||||
// Maps to PDOStatement::getColumnMeta. Return extra metadata.
|
// Maps to PDOStatement::getColumnMeta. Return extra metadata.
|
||||||
// Though we don't return any extra metadata, PDO relies on us to
|
// Though we don't return any extra metadata, PDO relies on us to
|
||||||
// create the associative array that holds the standard information,
|
// create the associative array that holds the standard information,
|
||||||
// so we create one and return it for PDO's use.
|
// so we create one and return it for PDO's use.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
// stmt - Current statement.
|
// stmt - Current statement.
|
||||||
|
@ -1092,9 +1092,9 @@ int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno
|
||||||
sqlsrv_stmt* driver_stmt = static_cast<sqlsrv_stmt*>( stmt->driver_data );
|
sqlsrv_stmt* driver_stmt = static_cast<sqlsrv_stmt*>( stmt->driver_data );
|
||||||
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_get_col_meta: stmt->driver_data was null");
|
SQLSRV_ASSERT( driver_stmt != NULL, "pdo_sqlsrv_stmt_get_col_meta: stmt->driver_data was null");
|
||||||
|
|
||||||
// Based on PDOStatement::getColumnMeta API, this should return FALSE
|
// Based on PDOStatement::getColumnMeta API, this should return FALSE
|
||||||
// if the requested column does not exist in the result set, or if
|
// if the requested column does not exist in the result set, or if
|
||||||
// no result set exists. Thus, do not use SQLSRV_ASSERT, which causes
|
// no result set exists. Thus, do not use SQLSRV_ASSERT, which causes
|
||||||
// the script to fail right away. Instead, log this warning if logging
|
// the script to fail right away. Instead, log this warning if logging
|
||||||
// is enabled
|
// is enabled
|
||||||
if (colno < 0 || colno >= stmt->column_count || stmt->columns == NULL) {
|
if (colno < 0 || colno >= stmt->column_count || stmt->columns == NULL) {
|
||||||
|
@ -1110,12 +1110,12 @@ int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno
|
||||||
// metadata should have been saved earlier
|
// metadata should have been saved earlier
|
||||||
SQLSRV_ASSERT(colno < driver_stmt->current_meta_data.size(), "pdo_sqlsrv_stmt_get_col_meta: Metadata vector out of sync with column numbers");
|
SQLSRV_ASSERT(colno < driver_stmt->current_meta_data.size(), "pdo_sqlsrv_stmt_get_col_meta: Metadata vector out of sync with column numbers");
|
||||||
core_meta_data = driver_stmt->current_meta_data[colno];
|
core_meta_data = driver_stmt->current_meta_data[colno];
|
||||||
|
|
||||||
// add the following fields: flags, native_type, driver:decl_type, table
|
// add the following fields: flags, native_type, driver:decl_type, table
|
||||||
if (driver_stmt->data_classification) {
|
if (driver_stmt->data_classification) {
|
||||||
core_sqlsrv_sensitivity_metadata(driver_stmt);
|
core_sqlsrv_sensitivity_metadata(driver_stmt);
|
||||||
|
|
||||||
// initialize the column data classification array
|
// initialize the column data classification array
|
||||||
zval data_classification;
|
zval data_classification;
|
||||||
ZVAL_UNDEF(&data_classification);
|
ZVAL_UNDEF(&data_classification);
|
||||||
array_init(&data_classification);
|
array_init(&data_classification);
|
||||||
|
@ -1136,7 +1136,7 @@ int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno
|
||||||
sizeof( field_type_name ), &out_buff_len, ¬_used );
|
sizeof( field_type_name ), &out_buff_len, ¬_used );
|
||||||
add_assoc_string( return_value, "sqlsrv:decl_type", field_type_name );
|
add_assoc_string( return_value, "sqlsrv:decl_type", field_type_name );
|
||||||
|
|
||||||
// get the PHP type of the column. The types returned here mirror the types returned by debug_zval_dump when
|
// get the PHP type of the column. The types returned here mirror the types returned by debug_zval_dump when
|
||||||
// given a variable of the same type. However, debug_zval_dump also gives the length of a string, and we only
|
// given a variable of the same type. However, debug_zval_dump also gives the length of a string, and we only
|
||||||
// say string, since the length is given in another field of the metadata array.
|
// say string, since the length is given in another field of the metadata array.
|
||||||
long pdo_type = sql_type_to_pdo_type( core_meta_data->field_type );
|
long pdo_type = sql_type_to_pdo_type( core_meta_data->field_type );
|
||||||
|
@ -1179,7 +1179,7 @@ int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno
|
||||||
zval_ptr_dtor(return_value);
|
zval_ptr_dtor(return_value);
|
||||||
DIE( "pdo_sqlsrv_stmt_get_col_meta: Unknown exception occurred while retrieving metadata." );
|
DIE( "pdo_sqlsrv_stmt_get_col_meta: Unknown exception occurred while retrieving metadata." );
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1187,7 +1187,7 @@ int pdo_sqlsrv_stmt_get_col_meta( _Inout_ pdo_stmt_t *stmt, _In_ zend_long colno
|
||||||
// pdo_sqlsrv_stmt_next_rowset
|
// pdo_sqlsrv_stmt_next_rowset
|
||||||
// Maps to PDOStatement::nextRowset.
|
// Maps to PDOStatement::nextRowset.
|
||||||
// Move the cursor to the beginning of the next rowset in a multi-rowset result.
|
// Move the cursor to the beginning of the next rowset in a multi-rowset result.
|
||||||
// Clears the field cache from the last row retrieved using pdo_sqlsrv_stmt_get_col_data.
|
// Clears the field cache from the last row retrieved using pdo_sqlsrv_stmt_get_col_data.
|
||||||
// Calls core_sqlsrv_next_result using the core_stmt found within stmt->driver_data.
|
// Calls core_sqlsrv_next_result using the core_stmt found within stmt->driver_data.
|
||||||
// If another result set is available, this function returns 1. Otherwise it returns 0.
|
// If another result set is available, this function returns 1. Otherwise it returns 0.
|
||||||
// Parameters:
|
// Parameters:
|
||||||
|
@ -1222,7 +1222,7 @@ int pdo_sqlsrv_stmt_next_rowset( _Inout_ pdo_stmt_t *stmt )
|
||||||
|
|
||||||
// return the row count regardless if there are any rows or not
|
// return the row count regardless if there are any rows or not
|
||||||
stmt->row_count = core::SQLRowCount( driver_stmt );
|
stmt->row_count = core::SQLRowCount( driver_stmt );
|
||||||
|
|
||||||
driver_stmt->column_count = stmt->column_count;
|
driver_stmt->column_count = stmt->column_count;
|
||||||
driver_stmt->row_count = stmt->row_count;
|
driver_stmt->row_count = stmt->row_count;
|
||||||
}
|
}
|
||||||
|
@ -1240,16 +1240,16 @@ int pdo_sqlsrv_stmt_next_rowset( _Inout_ pdo_stmt_t *stmt )
|
||||||
|
|
||||||
// pdo_sqlsrv_stmt_param_hook
|
// pdo_sqlsrv_stmt_param_hook
|
||||||
// Maps to PDOStatement::bindColumn.
|
// Maps to PDOStatement::bindColumn.
|
||||||
// Called by PDO driver manager to bind a parameter or column.
|
// Called by PDO driver manager to bind a parameter or column.
|
||||||
// This function pulls several duties for binding parameters and columns.
|
// This function pulls several duties for binding parameters and columns.
|
||||||
// It takes an event as a parameter that explains what the function should do on
|
// It takes an event as a parameter that explains what the function should do on
|
||||||
// behalf of a parameter or column. We only use one of these events,
|
// behalf of a parameter or column. We only use one of these events,
|
||||||
// PDO_PARAM_EVT_EXEC_PRE, the remainder simply return.
|
// PDO_PARAM_EVT_EXEC_PRE, the remainder simply return.
|
||||||
// Paramters:
|
// Paramters:
|
||||||
// stmt - PDO Statement object to bind a parameter.
|
// stmt - PDO Statement object to bind a parameter.
|
||||||
// param - paramter to bind.
|
// param - paramter to bind.
|
||||||
// event_type - Event to bind a parameter
|
// event_type - Event to bind a parameter
|
||||||
// Return:
|
// Return:
|
||||||
// Returns 0 for failure, 1 for success.
|
// Returns 0 for failure, 1 for success.
|
||||||
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)
|
||||||
|
@ -1310,7 +1310,7 @@ int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
|
||||||
// that means they want output, and if they include the flag, then it's input/output.
|
// that means they want output, and if they include the flag, then it's input/output.
|
||||||
// It's invalid to specify the input/output flag but not specify a length
|
// It's invalid to specify the input/output flag but not specify a length
|
||||||
CHECK_CUSTOM_ERROR( (param->param_type & PDO_PARAM_INPUT_OUTPUT) && (param->max_value_len == 0),
|
CHECK_CUSTOM_ERROR( (param->param_type & PDO_PARAM_INPUT_OUTPUT) && (param->max_value_len == 0),
|
||||||
driver_stmt, PDO_SQLSRV_ERROR_INVALID_PARAM_DIRECTION, param->paramno + 1 ) {
|
driver_stmt, PDO_SQLSRV_ERROR_INVALID_PARAM_DIRECTION, param->paramno + 1, NULL) {
|
||||||
throw pdo::PDOException();
|
throw pdo::PDOException();
|
||||||
}
|
}
|
||||||
// if the parameter is output or input/output, translate the type between the PDO::PARAM_* constant
|
// if the parameter is output or input/output, translate the type between the PDO::PARAM_* constant
|
||||||
|
@ -1328,7 +1328,7 @@ int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the user has specified the character set to use, take it off but ignore
|
// check if the user has specified the character set to use, take it off but ignore
|
||||||
#if PHP_VERSION_ID >= 70200
|
#if PHP_VERSION_ID >= 70200
|
||||||
if ((pdo_type & PDO_PARAM_STR_NATL) == PDO_PARAM_STR_NATL) {
|
if ((pdo_type & PDO_PARAM_STR_NATL) == PDO_PARAM_STR_NATL) {
|
||||||
pdo_type = pdo_type & ~PDO_PARAM_STR_NATL;
|
pdo_type = pdo_type & ~PDO_PARAM_STR_NATL;
|
||||||
|
@ -1357,7 +1357,7 @@ int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
|
||||||
{
|
{
|
||||||
zval null_zval;
|
zval null_zval;
|
||||||
php_out_type = SQLSRV_PHPTYPE_NULL;
|
php_out_type = SQLSRV_PHPTYPE_NULL;
|
||||||
|
|
||||||
ZVAL_NULL( &null_zval );
|
ZVAL_NULL( &null_zval );
|
||||||
zval_ptr_dtor( ¶m->parameter );
|
zval_ptr_dtor( ¶m->parameter );
|
||||||
param->parameter = null_zval;
|
param->parameter = null_zval;
|
||||||
|
@ -1396,8 +1396,8 @@ int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
|
||||||
break;
|
break;
|
||||||
case SQLSRV_PHPTYPE_STRING:
|
case SQLSRV_PHPTYPE_STRING:
|
||||||
{
|
{
|
||||||
CHECK_CUSTOM_ERROR( param->max_value_len <= 0, driver_stmt,
|
CHECK_CUSTOM_ERROR( param->max_value_len <= 0, driver_stmt,
|
||||||
PDO_SQLSRV_ERROR_INVALID_OUTPUT_STRING_SIZE, param->paramno + 1 ) {
|
PDO_SQLSRV_ERROR_INVALID_OUTPUT_STRING_SIZE, param->paramno + 1, NULL) {
|
||||||
throw pdo::PDOException();
|
throw pdo::PDOException();
|
||||||
}
|
}
|
||||||
column_size = param->max_value_len;
|
column_size = param->max_value_len;
|
||||||
|
@ -1409,14 +1409,14 @@ int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// block all objects from being bound as input or input/output parameters since there is a
|
// block all objects from being bound as input or input/output parameters since there is a
|
||||||
// weird case:
|
// weird case:
|
||||||
// $obj = date_create();
|
// $obj = date_create();
|
||||||
// $s->bindParam( n, $obj, PDO::PARAM_INT ); // anything different than PDO::PARAM_STR
|
// $s->bindParam( n, $obj, PDO::PARAM_INT ); // anything different than PDO::PARAM_STR
|
||||||
// that succeeds since the core layer implements DateTime object handling for the sqlsrv
|
// that succeeds since the core layer implements DateTime object handling for the sqlsrv
|
||||||
// 2.0 driver. To be consistent and avoid surprises of one object type working and others
|
// 2.0 driver. To be consistent and avoid surprises of one object type working and others
|
||||||
// not, we block all objects here.
|
// not, we block all objects here.
|
||||||
CHECK_CUSTOM_ERROR( direction != SQL_PARAM_OUTPUT && Z_TYPE( param->parameter ) == IS_OBJECT,
|
CHECK_CUSTOM_ERROR( direction != SQL_PARAM_OUTPUT && Z_TYPE( param->parameter ) == IS_OBJECT,
|
||||||
driver_stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param->paramno + 1 ) {
|
driver_stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param->paramno + 1, NULL) {
|
||||||
throw pdo::PDOException();
|
throw pdo::PDOException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1428,15 +1428,15 @@ int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Beginning with PHP7.2 the user can specify whether to use PDO_PARAM_STR_CHAR or PDO_PARAM_STR_NATL
|
// Beginning with PHP7.2 the user can specify whether to use PDO_PARAM_STR_CHAR or PDO_PARAM_STR_NATL
|
||||||
// But this extended type will be ignored in real prepared statements, so the encoding deliberately
|
// But this extended type will be ignored in real prepared statements, so the encoding deliberately
|
||||||
// set in the statement or driver options will still take precedence
|
// set in the statement or driver options will still take precedence
|
||||||
if( !Z_ISUNDEF(param->driver_params) ) {
|
if( !Z_ISUNDEF(param->driver_params) ) {
|
||||||
CHECK_CUSTOM_ERROR( Z_TYPE( param->driver_params ) != IS_LONG, driver_stmt,
|
CHECK_CUSTOM_ERROR( Z_TYPE( param->driver_params ) != IS_LONG, driver_stmt,
|
||||||
PDO_SQLSRV_ERROR_INVALID_DRIVER_PARAM ) {
|
PDO_SQLSRV_ERROR_INVALID_DRIVER_PARAM ) {
|
||||||
throw pdo::PDOException();
|
throw pdo::PDOException();
|
||||||
}
|
}
|
||||||
CHECK_CUSTOM_ERROR( pdo_type != PDO_PARAM_STR && pdo_type != PDO_PARAM_LOB, driver_stmt,
|
CHECK_CUSTOM_ERROR( pdo_type != PDO_PARAM_STR && pdo_type != PDO_PARAM_LOB, driver_stmt,
|
||||||
PDO_SQLSRV_ERROR_INVALID_DRIVER_PARAM_TYPE, param->paramno + 1 ) {
|
PDO_SQLSRV_ERROR_INVALID_DRIVER_PARAM_TYPE, param->paramno + 1, NULL) {
|
||||||
throw pdo::PDOException();
|
throw pdo::PDOException();
|
||||||
}
|
}
|
||||||
encoding = static_cast<SQLSRV_ENCODING>( Z_LVAL( param->driver_params ));
|
encoding = static_cast<SQLSRV_ENCODING>( Z_LVAL( param->driver_params ));
|
||||||
|
@ -1448,7 +1448,7 @@ int pdo_sqlsrv_stmt_param_hook( _Inout_ pdo_stmt_t *stmt,
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_DRIVER_PARAM_ENCODING,
|
THROW_PDO_ERROR( driver_stmt, PDO_SQLSRV_ERROR_INVALID_DRIVER_PARAM_ENCODING,
|
||||||
param->paramno + 1 );
|
param->paramno + 1, NULL );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1500,7 +1500,7 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type,
|
||||||
local_encoding = conn->encoding();
|
local_encoding = conn->encoding();
|
||||||
SQLSRV_ASSERT( conn->encoding() != SQLSRV_ENCODING_DEFAULT || conn->encoding() == SQLSRV_ENCODING_INVALID,
|
SQLSRV_ASSERT( conn->encoding() != SQLSRV_ENCODING_DEFAULT || conn->encoding() == SQLSRV_ENCODING_INVALID,
|
||||||
"Invalid encoding on the connection. Must not be invalid or default." );
|
"Invalid encoding on the connection. Must not be invalid or default." );
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlsrv_phptype.typeinfo.encoding = local_encoding;
|
sqlsrv_phptype.typeinfo.encoding = local_encoding;
|
||||||
|
|
||||||
|
@ -1514,7 +1514,7 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
|
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
|
||||||
sqlsrv_phptype.typeinfo.encoding = SQLSRV_ENCODING_CHAR;
|
sqlsrv_phptype.typeinfo.encoding = SQLSRV_ENCODING_CHAR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SQL_FLOAT:
|
case SQL_FLOAT:
|
||||||
|
@ -1524,7 +1524,7 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type,
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
|
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
|
||||||
sqlsrv_phptype.typeinfo.encoding = SQLSRV_ENCODING_CHAR;
|
sqlsrv_phptype.typeinfo.encoding = SQLSRV_ENCODING_CHAR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SQL_TYPE_DATE:
|
case SQL_TYPE_DATE:
|
||||||
|
@ -1542,7 +1542,7 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type,
|
||||||
case SQL_DECIMAL:
|
case SQL_DECIMAL:
|
||||||
case SQL_NUMERIC:
|
case SQL_NUMERIC:
|
||||||
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
|
sqlsrv_phptype.typeinfo.type = SQLSRV_PHPTYPE_STRING;
|
||||||
sqlsrv_phptype.typeinfo.encoding = SQLSRV_ENCODING_CHAR;
|
sqlsrv_phptype.typeinfo.encoding = SQLSRV_ENCODING_CHAR;
|
||||||
break;
|
break;
|
||||||
case SQL_CHAR:
|
case SQL_CHAR:
|
||||||
case SQL_GUID:
|
case SQL_GUID:
|
||||||
|
@ -1567,6 +1567,6 @@ sqlsrv_phptype pdo_sqlsrv_stmt::sql_type_to_php_type( _In_ SQLINTEGER sql_type,
|
||||||
sqlsrv_phptype.typeinfo.encoding = SQLSRV_ENCODING_INVALID;
|
sqlsrv_phptype.typeinfo.encoding = SQLSRV_ENCODING_INVALID;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sqlsrv_phptype;
|
return sqlsrv_phptype;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Utility functions used by both connection or statement functions
|
// Contents: Utility functions used by both connection or statement functions
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Declarations for the extension
|
// Contents: Declarations for the extension
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Internal declarations for the extension
|
// Contents: Internal declarations for the extension
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Version resource
|
// Contents: Version resource
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
// Contents: Contains functions for handling Windows format strings
|
// Contents: Contains functions for handling Windows format strings
|
||||||
// and UTF-16 on non-Windows platforms
|
// and UTF-16 on non-Windows platforms
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Contents: Contains functions for handling Windows format strings
|
// Contents: Contains functions for handling Windows format strings
|
||||||
// and UTF-16 on non-Windows platforms
|
// and UTF-16 on non-Windows platforms
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
|
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
|
// Contents: Contains functions for handling UTF-16 on non-Windows platforms
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Core routines that use connection handles shared between sqlsrv and pdo_sqlsrv
|
// Contents: Core routines that use connection handles shared between sqlsrv and pdo_sqlsrv
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
@ -160,7 +160,7 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
// In Windows, we try to connect with ODBC driver first and rely on the returned error code to try connecting with other supported ODBC drivers
|
// In Windows, we try to connect with ODBC driver first and rely on the returned error code to try connecting with other supported ODBC drivers
|
||||||
if (conn->driver_version != ODBC_DRIVER::VER_UNKNOWN) {
|
if (conn->driver_version != ODBC_DRIVER::VER_UNKNOWN) {
|
||||||
// if column encryption is enabled, must use ODBC driver 17 or above
|
// if column encryption is enabled, must use ODBC driver 17 or above
|
||||||
CHECK_CUSTOM_ERROR(conn->ce_option.enabled && conn->driver_version == ODBC_DRIVER::VER_13, conn, SQLSRV_ERROR_CE_DRIVER_REQUIRED, get_processor_arch()) {
|
CHECK_CUSTOM_ERROR(conn->ce_option.enabled && conn->driver_version == ODBC_DRIVER::VER_13, conn, SQLSRV_ERROR_CE_DRIVER_REQUIRED, get_processor_arch(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// ODBC driver not specified, so check ODBC 17 first then ODBC 18 and/or ODBC 13
|
// ODBC driver not specified, so check ODBC 17 first then ODBC 18 and/or ODBC 13
|
||||||
// If column encryption is enabled, check up to ODBC 18
|
// If column encryption is enabled, check up to ODBC 18
|
||||||
ODBC_DRIVER drivers[] = { ODBC_DRIVER::VER_17, ODBC_DRIVER::VER_18, ODBC_DRIVER::VER_13 };
|
ODBC_DRIVER drivers[] = { ODBC_DRIVER::VER_17, ODBC_DRIVER::VER_18, ODBC_DRIVER::VER_13 };
|
||||||
ODBC_DRIVER last_version = (conn->ce_option.enabled) ? ODBC_DRIVER::VER_18 : ODBC_DRIVER::VER_13;
|
ODBC_DRIVER last_version = (conn->ce_option.enabled) ? ODBC_DRIVER::VER_18 : ODBC_DRIVER::VER_13;
|
||||||
|
@ -208,12 +208,12 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
#endif
|
#endif
|
||||||
else if (d == last_version) {
|
else if (d == last_version) {
|
||||||
// if column encryption is enabled, throw the exception related to column encryption
|
// if column encryption is enabled, throw the exception related to column encryption
|
||||||
CHECK_CUSTOM_ERROR(conn->ce_option.enabled, conn, SQLSRV_ERROR_CE_DRIVER_REQUIRED, get_processor_arch()) {
|
CHECK_CUSTOM_ERROR(conn->ce_option.enabled, conn, SQLSRV_ERROR_CE_DRIVER_REQUIRED, get_processor_arch(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// here it means that none of the supported ODBC drivers is found
|
// here it means that none of the supported ODBC drivers is found
|
||||||
CHECK_CUSTOM_ERROR(true, conn, SQLSRV_ERROR_DRIVER_NOT_INSTALLED, get_processor_arch()) {
|
CHECK_CUSTOM_ERROR(true, conn, SQLSRV_ERROR_DRIVER_NOT_INSTALLED, get_processor_arch(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_SQL_WARNING_AS_ERROR( r, conn ) {
|
CHECK_SQL_WARNING_AS_ERROR( r, conn, NULL ) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ SQLRETURN core_odbc_connect( _Inout_ sqlsrv_conn* conn, _Inout_ std::string& con
|
||||||
// Convert our UTF-8 connection string to UTF-16 before connecting with SQLDriverConnnectW
|
// Convert our UTF-8 connection string to UTF-16 before connecting with SQLDriverConnnectW
|
||||||
wconn_string = utf16_string_from_mbcs_string( SQLSRV_ENCODING_UTF8, conn_str.c_str(), static_cast<unsigned int>( conn_str.length() ), &wconn_len, true );
|
wconn_string = utf16_string_from_mbcs_string( SQLSRV_ENCODING_UTF8, conn_str.c_str(), static_cast<unsigned int>( conn_str.length() ), &wconn_len, true );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR( wconn_string == 0, conn, SQLSRV_ERROR_CONNECT_STRING_ENCODING_TRANSLATE, get_last_error_message())
|
CHECK_CUSTOM_ERROR( wconn_string == 0, conn, SQLSRV_ERROR_CONNECT_STRING_ENCODING_TRANSLATE, get_last_error_message(), NULL)
|
||||||
{
|
{
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
@ -487,7 +487,7 @@ void core_sqlsrv_prepare( _Inout_ sqlsrv_stmt* stmt, _In_reads_bytes_(sql_len) c
|
||||||
|
|
||||||
SQLSRV_ENCODING encoding = (( stmt->encoding() == SQLSRV_ENCODING_DEFAULT ) ? stmt->conn->encoding() : stmt->encoding() );
|
SQLSRV_ENCODING encoding = (( stmt->encoding() == SQLSRV_ENCODING_DEFAULT ) ? stmt->conn->encoding() : stmt->encoding() );
|
||||||
wsql_string = utf16_string_from_mbcs_string( encoding, reinterpret_cast<const char*>( sql ), static_cast<int>( sql_len ), &wsql_len );
|
wsql_string = utf16_string_from_mbcs_string( encoding, reinterpret_cast<const char*>( sql ), static_cast<int>( sql_len ), &wsql_len );
|
||||||
CHECK_CUSTOM_ERROR( wsql_string == 0, stmt, SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE, get_last_error_message() ) {
|
CHECK_CUSTOM_ERROR( wsql_string == 0, stmt, SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE, get_last_error_message(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -796,7 +796,7 @@ void build_connection_string_and_set_conn_attr( _Inout_ sqlsrv_conn* conn, _Inou
|
||||||
DEBUG_SQLSRV_ASSERT(( type == HASH_KEY_IS_LONG ), "build_connection_string_and_set_conn_attr: invalid connection option key type." );
|
DEBUG_SQLSRV_ASSERT(( type == HASH_KEY_IS_LONG ), "build_connection_string_and_set_conn_attr: invalid connection option key type." );
|
||||||
|
|
||||||
conn_opt = get_connection_option( conn, index, valid_conn_opts );
|
conn_opt = get_connection_option( conn, index, valid_conn_opts );
|
||||||
|
if (conn_opt == NULL) throw;
|
||||||
if( index == SQLSRV_CONN_OPTION_MARS ) {
|
if( index == SQLSRV_CONN_OPTION_MARS ) {
|
||||||
mars_mentioned = true;
|
mars_mentioned = true;
|
||||||
}
|
}
|
||||||
|
@ -1051,7 +1051,7 @@ void driver_set_func::func(_In_ connection_option const* option, _In_ zval* valu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(conn->driver_version == ODBC_DRIVER::VER_UNKNOWN, conn, SQLSRV_ERROR_CONNECT_INVALID_DRIVER, Z_STRVAL_P(value)) {
|
CHECK_CUSTOM_ERROR(conn->driver_version == ODBC_DRIVER::VER_UNKNOWN, conn, SQLSRV_ERROR_CONNECT_INVALID_DRIVER, Z_STRVAL_P(value), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: common initialization routines shared by PDO and sqlsrv
|
// Contents: common initialization routines shared by PDO and sqlsrv
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,17 +3,17 @@
|
||||||
//
|
//
|
||||||
// Contents: Result sets
|
// Contents: Result sets
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
|
// 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,
|
// 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 :
|
// 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 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,
|
// 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
|
// 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
|
// 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.
|
// IN THE SOFTWARE.
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ const int INITIAL_LOB_FIELD_LEN = 2048; // base allocation size when retrie
|
||||||
template <int align, typename T>
|
template <int align, typename T>
|
||||||
T align_to( _In_ T number )
|
T align_to( _In_ T number )
|
||||||
{
|
{
|
||||||
DEBUG_SQLSRV_ASSERT( (number + align) > number, "Number to align overflowed" );
|
DEBUG_SQLSRV_ASSERT( (number + align) > number, "Number to align overflowed" );
|
||||||
return ((number % align) == 0) ? number : (number + align - (number % align));
|
return ((number % align) == 0) ? number : (number + align - (number % align));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ size_t get_float_precision( _In_ SQLLEN buffer_length, _In_ size_t unitsize)
|
||||||
|
|
||||||
// use the display size to determine the sql type. And if it is a double, set the precision accordingly
|
// use the display size to determine the sql type. And if it is a double, set the precision accordingly
|
||||||
// the display sizes are set by the ODBC driver based on the precision of the sql type
|
// the display sizes are set by the ODBC driver based on the precision of the sql type
|
||||||
// otherwise we can just use the default precision
|
// otherwise we can just use the default precision
|
||||||
size_t real_display_size = 14;
|
size_t real_display_size = 14;
|
||||||
size_t float_display_size = 24;
|
size_t float_display_size = 24;
|
||||||
size_t real_precision = 7;
|
size_t real_precision = 7;
|
||||||
|
@ -206,14 +206,14 @@ SQLRETURN number_to_string( _In_ Number* number_data, _Out_writes_bytes_to_opt_(
|
||||||
{
|
{
|
||||||
|
|
||||||
std::basic_string<char16_t> str;
|
std::basic_string<char16_t> str;
|
||||||
|
|
||||||
for (const auto &mb : str_num )
|
for (const auto &mb : str_num )
|
||||||
{
|
{
|
||||||
size_t cch = SystemLocale::NextChar( CP_ACP, &mb ) - &mb;
|
size_t cch = SystemLocale::NextChar( CP_ACP, &mb ) - &mb;
|
||||||
if ( cch > 0 )
|
if ( cch > 0 )
|
||||||
{
|
{
|
||||||
WCHAR ch16;
|
WCHAR ch16;
|
||||||
DWORD rc;
|
DWORD rc;
|
||||||
size_t cchActual = SystemLocale::ToUtf16( CP_ACP, &mb, cch, &ch16, 1, &rc);
|
size_t cchActual = SystemLocale::ToUtf16( CP_ACP, &mb, cch, &ch16, 1, &rc);
|
||||||
if (cchActual > 0)
|
if (cchActual > 0)
|
||||||
{
|
{
|
||||||
|
@ -242,8 +242,8 @@ std::string getUTF8StringFromString( _In_z_ const SQLWCHAR* source )
|
||||||
SQLLEN i = 0;
|
SQLLEN i = 0;
|
||||||
std::string str;
|
std::string str;
|
||||||
while ( source[i] )
|
while ( source[i] )
|
||||||
{
|
{
|
||||||
memset( c_str, 0, sizeof( c_str ) );
|
memset( c_str, 0, sizeof( c_str ) );
|
||||||
int cch = 0;
|
int cch = 0;
|
||||||
errno_t err = mplat_wctomb_s( &cch, c_str, sizeof( c_str ), source[i++] );
|
errno_t err = mplat_wctomb_s( &cch, c_str, sizeof( c_str ), source[i++] );
|
||||||
if ( cch > 0 && err == ERROR_SUCCESS )
|
if ( cch > 0 && err == ERROR_SUCCESS )
|
||||||
|
@ -271,7 +271,7 @@ struct row_dtor_closure {
|
||||||
row_dtor_closure( _In_ sqlsrv_buffered_result_set* st, _In_ BYTE* row ) :
|
row_dtor_closure( _In_ sqlsrv_buffered_result_set* st, _In_ BYTE* row ) :
|
||||||
results( st ), row_data( row )
|
results( st ), row_data( row )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
sqlsrv_error* odbc_get_diag_rec( _In_ sqlsrv_stmt* odbc, _In_ SQLSMALLINT record_number )
|
sqlsrv_error* odbc_get_diag_rec( _In_ sqlsrv_stmt* odbc, _In_ SQLSMALLINT record_number )
|
||||||
|
@ -280,9 +280,9 @@ sqlsrv_error* odbc_get_diag_rec( _In_ sqlsrv_stmt* odbc, _In_ SQLSMALLINT record
|
||||||
SQLWCHAR wnative_message[SQL_MAX_ERROR_MESSAGE_LENGTH + 1] = {L'\0'};
|
SQLWCHAR wnative_message[SQL_MAX_ERROR_MESSAGE_LENGTH + 1] = {L'\0'};
|
||||||
SQLINTEGER native_code;
|
SQLINTEGER native_code;
|
||||||
SQLSMALLINT wnative_message_len = 0;
|
SQLSMALLINT wnative_message_len = 0;
|
||||||
|
|
||||||
SQLSRV_ASSERT(odbc != NULL, "odbc_get_diag_rec: sqlsrv_stmt* odbc was null.");
|
SQLSRV_ASSERT(odbc != NULL, "odbc_get_diag_rec: sqlsrv_stmt* odbc was null.");
|
||||||
SQLRETURN r = SQLGetDiagRecW( SQL_HANDLE_STMT, odbc->handle(), record_number, wsql_state, &native_code, wnative_message,
|
SQLRETURN r = SQLGetDiagRecW( SQL_HANDLE_STMT, odbc->handle(), record_number, wsql_state, &native_code, wnative_message,
|
||||||
SQL_MAX_ERROR_MESSAGE_LENGTH + 1, &wnative_message_len );
|
SQL_MAX_ERROR_MESSAGE_LENGTH + 1, &wnative_message_len );
|
||||||
if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
|
if( !SQL_SUCCEEDED( r ) || r == SQL_NO_DATA ) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -300,14 +300,14 @@ sqlsrv_error* odbc_get_diag_rec( _In_ sqlsrv_stmt* odbc, _In_ SQLSMALLINT record
|
||||||
if ( !convert_string_from_utf16( enc, wsql_state, SQL_SQLSTATE_BUFSIZE, (char**)&sql_state, sql_state_len )) {
|
if ( !convert_string_from_utf16( enc, wsql_state, SQL_SQLSTATE_BUFSIZE, (char**)&sql_state, sql_state_len )) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlsrv_malloc_auto_ptr<SQLCHAR> native_message;
|
sqlsrv_malloc_auto_ptr<SQLCHAR> native_message;
|
||||||
SQLLEN native_message_len = 0;
|
SQLLEN native_message_len = 0;
|
||||||
if (!convert_string_from_utf16( enc, wnative_message, wnative_message_len, (char**)&native_message, native_message_len )) {
|
if (!convert_string_from_utf16( enc, wnative_message, wnative_message_len, (char**)&native_message, native_message_len )) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) sql_state, (SQLCHAR*) native_message,
|
return new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) sql_state, (SQLCHAR*) native_message,
|
||||||
native_code );
|
native_code );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,7 +324,7 @@ sqlsrv_result_set::sqlsrv_result_set( _In_ sqlsrv_stmt* stmt ) :
|
||||||
// ODBC result set
|
// ODBC result set
|
||||||
// This object simply wraps ODBC function calls
|
// This object simply wraps ODBC function calls
|
||||||
|
|
||||||
sqlsrv_odbc_result_set::sqlsrv_odbc_result_set( _In_ sqlsrv_stmt* stmt ) :
|
sqlsrv_odbc_result_set::sqlsrv_odbc_result_set( _In_ sqlsrv_stmt* stmt ) :
|
||||||
sqlsrv_result_set( stmt )
|
sqlsrv_result_set( stmt )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -347,12 +347,12 @@ SQLRETURN sqlsrv_odbc_result_set::get_data( _In_ SQLUSMALLINT field_index, _In_
|
||||||
return core::SQLGetData( odbc, field_index, target_type, buffer, buffer_length, out_buffer_length, handle_warning );
|
return core::SQLGetData( odbc, field_index, target_type, buffer, buffer_length, out_buffer_length, handle_warning );
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLRETURN sqlsrv_odbc_result_set::get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
|
SQLRETURN sqlsrv_odbc_result_set::get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
|
||||||
_Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
|
_Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
|
||||||
_Inout_ SQLSMALLINT* out_buffer_length )
|
_Inout_ SQLSMALLINT* out_buffer_length )
|
||||||
{
|
{
|
||||||
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
|
SQLSRV_ASSERT( odbc != NULL, "Invalid statement handle" );
|
||||||
return core::SQLGetDiagField( odbc, record_number, diag_identifier, diag_info_buffer, buffer_length,
|
return core::SQLGetDiagField( odbc, record_number, diag_identifier, diag_info_buffer, buffer_length,
|
||||||
out_buffer_length );
|
out_buffer_length );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLULEN null_bytes = ( col_count / 8 ) + 1; // number of bits to reserve at the beginning of each row for NULL flags
|
SQLULEN null_bytes = ( col_count / 8 ) + 1; // number of bits to reserve at the beginning of each row for NULL flags
|
||||||
meta = static_cast<sqlsrv_buffered_result_set::meta_data*>( sqlsrv_malloc( col_count *
|
meta = static_cast<sqlsrv_buffered_result_set::meta_data*>( sqlsrv_malloc( col_count *
|
||||||
sizeof( sqlsrv_buffered_result_set::meta_data )));
|
sizeof( sqlsrv_buffered_result_set::meta_data )));
|
||||||
|
|
||||||
SQLSRV_ENCODING encoding = (( stmt->encoding() == SQLSRV_ENCODING_DEFAULT ) ? stmt->conn->encoding() :
|
SQLSRV_ENCODING encoding = (( stmt->encoding() == SQLSRV_ENCODING_DEFAULT ) ? stmt->conn->encoding() :
|
||||||
|
@ -397,7 +397,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
// get the meta data and calculate the size of a row buffer
|
// get the meta data and calculate the size of a row buffer
|
||||||
SQLULEN offset = null_bytes;
|
SQLULEN offset = null_bytes;
|
||||||
for( SQLSMALLINT i = 0; i < col_count; ++i ) {
|
for( SQLSMALLINT i = 0; i < col_count; ++i ) {
|
||||||
|
|
||||||
core::SQLDescribeColW( stmt, i + 1, NULL, 0, NULL, &meta[i].type, &meta[i].length, &meta[i].scale, NULL );
|
core::SQLDescribeColW( stmt, i + 1, NULL, 0, NULL, &meta[i].type, &meta[i].length, &meta[i].scale, NULL );
|
||||||
|
|
||||||
offset = align_to<sizeof(SQLPOINTER)>( offset );
|
offset = align_to<sizeof(SQLPOINTER)>( offset );
|
||||||
|
@ -423,7 +423,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// If encoding is set to UTF-8, the following types are not necessarily column size.
|
// If encoding is set to UTF-8, the following types are not necessarily column size.
|
||||||
// We need to call SQLGetData with c_type SQL_C_WCHAR and set the size accordingly.
|
// We need to call SQLGetData with c_type SQL_C_WCHAR and set the size accordingly.
|
||||||
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
|
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
|
||||||
meta[i].length *= sizeof( WCHAR );
|
meta[i].length *= sizeof( WCHAR );
|
||||||
meta[i].length += sizeof( SQLULEN ) + sizeof( WCHAR ); // length plus null terminator space
|
meta[i].length += sizeof( SQLULEN ) + sizeof( WCHAR ); // length plus null terminator space
|
||||||
|
@ -477,7 +477,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
case SQL_SS_TIME2:
|
case SQL_SS_TIME2:
|
||||||
case SQL_SS_TIMESTAMPOFFSET:
|
case SQL_SS_TIMESTAMPOFFSET:
|
||||||
case SQL_TYPE_TIMESTAMP:
|
case SQL_TYPE_TIMESTAMP:
|
||||||
core::SQLColAttributeW( stmt, i + 1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL,
|
core::SQLColAttributeW( stmt, i + 1, SQL_DESC_DISPLAY_SIZE, NULL, 0, NULL,
|
||||||
reinterpret_cast<SQLLEN*>( &meta[i].length ) );
|
reinterpret_cast<SQLLEN*>( &meta[i].length ) );
|
||||||
meta[i].length += sizeof(char) + sizeof( SQLULEN ); // null terminator space
|
meta[i].length += sizeof(char) + sizeof( SQLULEN ); // null terminator space
|
||||||
offset += meta[i].length;
|
offset += meta[i].length;
|
||||||
|
@ -517,13 +517,13 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
case SQL_TYPE_TIMESTAMP:
|
case SQL_TYPE_TIMESTAMP:
|
||||||
meta[i].c_type = SQL_C_CHAR;
|
meta[i].c_type = SQL_C_CHAR;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_CHAR:
|
case SQL_CHAR:
|
||||||
case SQL_VARCHAR:
|
case SQL_VARCHAR:
|
||||||
case SQL_SS_VARIANT:
|
case SQL_SS_VARIANT:
|
||||||
case SQL_LONGVARCHAR:
|
case SQL_LONGVARCHAR:
|
||||||
// If encoding is set to UTF-8, the following types are not necessarily column size.
|
// If encoding is set to UTF-8, the following types are not necessarily column size.
|
||||||
// We need to call SQLGetData with c_type SQL_C_WCHAR and set the size accordingly.
|
// We need to call SQLGetData with c_type SQL_C_WCHAR and set the size accordingly.
|
||||||
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
|
if ( encoding == SQLSRV_ENCODING_UTF8 ) {
|
||||||
meta[i].c_type = SQL_C_WCHAR;
|
meta[i].c_type = SQL_C_WCHAR;
|
||||||
}
|
}
|
||||||
|
@ -531,7 +531,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
meta[i].c_type = SQL_C_CHAR;
|
meta[i].c_type = SQL_C_CHAR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SQL_SS_UDT:
|
case SQL_SS_UDT:
|
||||||
case SQL_LONGVARBINARY:
|
case SQL_LONGVARBINARY:
|
||||||
case SQL_BINARY:
|
case SQL_BINARY:
|
||||||
|
@ -574,7 +574,7 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while( core::SQLFetchScroll( stmt, SQL_FETCH_NEXT, 0 ) != SQL_NO_DATA ) {
|
while( core::SQLFetchScroll( stmt, SQL_FETCH_NEXT, 0 ) != SQL_NO_DATA ) {
|
||||||
|
|
||||||
// allocate the row buffer
|
// allocate the row buffer
|
||||||
sqlsrv_malloc_auto_ptr<unsigned char> rowAuto;
|
sqlsrv_malloc_auto_ptr<unsigned char> rowAuto;
|
||||||
rowAuto = static_cast<unsigned char*>( sqlsrv_malloc( offset ));
|
rowAuto = static_cast<unsigned char*>( sqlsrv_malloc( offset ));
|
||||||
|
@ -610,15 +610,15 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
else {
|
else {
|
||||||
|
|
||||||
mem_used += meta[i].length;
|
mem_used += meta[i].length;
|
||||||
CHECK_CUSTOM_ERROR( mem_used > stmt->buffered_query_limit * 1024, stmt,
|
CHECK_CUSTOM_ERROR( mem_used > stmt->buffered_query_limit * 1024, stmt,
|
||||||
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
|
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit, NULL) {
|
||||||
|
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = row + meta[i].offset + sizeof( SQLULEN );
|
buffer = row + meta[i].offset + sizeof( SQLULEN );
|
||||||
out_buffer_length = reinterpret_cast<SQLLEN*>( row + meta[i].offset );
|
out_buffer_length = reinterpret_cast<SQLLEN*>( row + meta[i].offset );
|
||||||
core::SQLGetData( stmt, i + 1, meta[i].c_type, buffer, meta[i].length, out_buffer_length,
|
core::SQLGetData( stmt, i + 1, meta[i].c_type, buffer, meta[i].length, out_buffer_length,
|
||||||
false );
|
false );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -627,17 +627,17 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
case SQL_C_DOUBLE:
|
case SQL_C_DOUBLE:
|
||||||
{
|
{
|
||||||
mem_used += meta[i].length;
|
mem_used += meta[i].length;
|
||||||
CHECK_CUSTOM_ERROR( mem_used > stmt->buffered_query_limit * 1024, stmt,
|
CHECK_CUSTOM_ERROR( mem_used > stmt->buffered_query_limit * 1024, stmt,
|
||||||
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
|
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit, NULL) {
|
||||||
|
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
buffer = row + meta[i].offset;
|
buffer = row + meta[i].offset;
|
||||||
out_buffer_length = &out_buffer_temp;
|
out_buffer_length = &out_buffer_temp;
|
||||||
core::SQLGetData( stmt, i + 1, meta[i].c_type, buffer, meta[i].length, out_buffer_length,
|
core::SQLGetData( stmt, i + 1, meta[i].c_type, buffer, meta[i].length, out_buffer_length,
|
||||||
false );
|
false );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
SQLSRV_ASSERT( false, "Unknown C type" );
|
SQLSRV_ASSERT( false, "Unknown C type" );
|
||||||
|
@ -656,8 +656,8 @@ sqlsrv_buffered_result_set::sqlsrv_buffered_result_set( _Inout_ sqlsrv_stmt* stm
|
||||||
row_dtor_closure cl( this, row );
|
row_dtor_closure cl( this, row );
|
||||||
sqlsrv_zend_hash_next_index_insert_mem( *stmt, cache, &cl, sizeof(row_dtor_closure) );
|
sqlsrv_zend_hash_next_index_insert_mem( *stmt, cache, &cl, sizeof(row_dtor_closure) );
|
||||||
rowAuto.transferred();
|
rowAuto.transferred();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
// free the rows
|
// free the rows
|
||||||
if( cache ) {
|
if( cache ) {
|
||||||
|
@ -753,7 +753,7 @@ SQLRETURN sqlsrv_buffered_result_set::get_data( _In_ SQLUSMALLINT field_index, _
|
||||||
*out_buffer_length = SQL_NULL_DATA;
|
*out_buffer_length = SQL_NULL_DATA;
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check to make sure the conversion type is valid
|
// check to make sure the conversion type is valid
|
||||||
switch (meta[field_index].c_type) {
|
switch (meta[field_index].c_type) {
|
||||||
case SQL_C_CHAR:
|
case SQL_C_CHAR:
|
||||||
|
@ -817,21 +817,21 @@ SQLRETURN sqlsrv_buffered_result_set::get_data( _In_ SQLUSMALLINT field_index, _
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLRETURN sqlsrv_buffered_result_set::get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
|
SQLRETURN sqlsrv_buffered_result_set::get_diag_field( _In_ SQLSMALLINT record_number, _In_ SQLSMALLINT diag_identifier,
|
||||||
_Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
|
_Inout_updates_(buffer_length) SQLPOINTER diag_info_buffer, _In_ SQLSMALLINT buffer_length,
|
||||||
_Inout_ SQLSMALLINT* out_buffer_length )
|
_Inout_ SQLSMALLINT* out_buffer_length )
|
||||||
{
|
{
|
||||||
SQLSRV_ASSERT( record_number == 1, "Only record number 1 can be fetched by sqlsrv_buffered_result_set::get_diag_field" );
|
SQLSRV_ASSERT( record_number == 1, "Only record number 1 can be fetched by sqlsrv_buffered_result_set::get_diag_field" );
|
||||||
SQLSRV_ASSERT( diag_identifier == SQL_DIAG_SQLSTATE,
|
SQLSRV_ASSERT( diag_identifier == SQL_DIAG_SQLSTATE,
|
||||||
"Only SQL_DIAG_SQLSTATE can be fetched by sqlsrv_buffered_result_set::get_diag_field" );
|
"Only SQL_DIAG_SQLSTATE can be fetched by sqlsrv_buffered_result_set::get_diag_field" );
|
||||||
SQLSRV_ASSERT( buffer_length >= SQL_SQLSTATE_BUFSIZE,
|
SQLSRV_ASSERT( buffer_length >= SQL_SQLSTATE_BUFSIZE,
|
||||||
"Buffer not big enough to return SQLSTATE in sqlsrv_buffered_result_set::get_diag_field" );
|
"Buffer not big enough to return SQLSTATE in sqlsrv_buffered_result_set::get_diag_field" );
|
||||||
|
|
||||||
if( last_error == 0 ) {
|
if( last_error == 0 ) {
|
||||||
return SQL_NO_DATA;
|
return SQL_NO_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLSRV_ASSERT( last_error->sqlstate != NULL,
|
SQLSRV_ASSERT( last_error->sqlstate != NULL,
|
||||||
"Must have a SQLSTATE in a valid last_error in sqlsrv_buffered_result_set::get_diag_field" );
|
"Must have a SQLSTATE in a valid last_error in sqlsrv_buffered_result_set::get_diag_field" );
|
||||||
|
|
||||||
SQLSMALLINT bufsize = ( buffer_length < SQL_SQLSTATE_BUFSIZE ) ? buffer_length : SQL_SQLSTATE_BUFSIZE;
|
SQLSMALLINT bufsize = ( buffer_length < SQL_SQLSTATE_BUFSIZE ) ? buffer_length : SQL_SQLSTATE_BUFSIZE;
|
||||||
|
@ -858,8 +858,8 @@ sqlsrv_error* sqlsrv_buffered_result_set::get_diag_rec( _In_ SQLSMALLINT record_
|
||||||
if( record_number > 1 ) {
|
if( record_number > 1 ) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new (sqlsrv_malloc( sizeof( sqlsrv_error )))
|
return new (sqlsrv_malloc( sizeof( sqlsrv_error )))
|
||||||
sqlsrv_error( last_error->sqlstate, last_error->native_message, last_error->native_code );
|
sqlsrv_error( last_error->sqlstate, last_error->native_message, last_error->native_code );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -879,7 +879,7 @@ SQLLEN sqlsrv_buffered_result_set::row_count( void )
|
||||||
// private functions
|
// private functions
|
||||||
template <typename Char>
|
template <typename Char>
|
||||||
SQLRETURN binary_to_string( _Inout_ SQLCHAR* field_data, _Inout_ SQLLEN& read_so_far, _Out_writes_z_(*out_buffer_length) void* buffer,
|
SQLRETURN binary_to_string( _Inout_ SQLCHAR* field_data, _Inout_ SQLLEN& read_so_far, _Out_writes_z_(*out_buffer_length) void* buffer,
|
||||||
_In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length,
|
_In_ SQLLEN buffer_length, _Inout_ SQLLEN* out_buffer_length,
|
||||||
_Inout_ sqlsrv_error_auto_ptr& out_error )
|
_Inout_ sqlsrv_error_auto_ptr& out_error )
|
||||||
{
|
{
|
||||||
// The hex characters for the conversion loop below
|
// The hex characters for the conversion loop below
|
||||||
|
@ -892,7 +892,7 @@ SQLRETURN binary_to_string( _Inout_ SQLCHAR* field_data, _Inout_ SQLLEN& read_so
|
||||||
// Set the amount of space necessary for null characters at the end of the data.
|
// Set the amount of space necessary for null characters at the end of the data.
|
||||||
SQLSMALLINT extra = sizeof(Char);
|
SQLSMALLINT extra = sizeof(Char);
|
||||||
|
|
||||||
// TO convert a binary to a system string or a binary to a wide string, the buffer size minus
|
// TO convert a binary to a system string or a binary to a wide string, the buffer size minus
|
||||||
// 'extra' is ideally multiples of 2 or 4 (depending on Char), but calculating to_copy_hex below
|
// 'extra' is ideally multiples of 2 or 4 (depending on Char), but calculating to_copy_hex below
|
||||||
// takes care of this.
|
// takes care of this.
|
||||||
|
|
||||||
|
@ -900,7 +900,7 @@ SQLRETURN binary_to_string( _Inout_ SQLCHAR* field_data, _Inout_ SQLLEN& read_so
|
||||||
// the entire length of the string is returned the first
|
// the entire length of the string is returned the first
|
||||||
// call in out_buffer_len. Successive calls return how much is
|
// call in out_buffer_len. Successive calls return how much is
|
||||||
// left minus how much has already been read by previous reads
|
// left minus how much has already been read by previous reads
|
||||||
// *2 is for each byte to hex conversion and * extra is for either system
|
// *2 is for each byte to hex conversion and * extra is for either system
|
||||||
// or wide string allocation
|
// or wide string allocation
|
||||||
*out_buffer_length = (*reinterpret_cast<SQLLEN*>( field_data - sizeof( SQLULEN )) - read_so_far) * 2 * extra;
|
*out_buffer_length = (*reinterpret_cast<SQLLEN*>( field_data - sizeof( SQLULEN )) - read_so_far) * 2 * extra;
|
||||||
|
|
||||||
|
@ -908,7 +908,7 @@ SQLRETURN binary_to_string( _Inout_ SQLCHAR* field_data, _Inout_ SQLLEN& read_so
|
||||||
SQLLEN to_copy;
|
SQLLEN to_copy;
|
||||||
if( buffer_length < *out_buffer_length + extra ) {
|
if( buffer_length < *out_buffer_length + extra ) {
|
||||||
to_copy = (buffer_length - extra);
|
to_copy = (buffer_length - extra);
|
||||||
out_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
|
out_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
|
||||||
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
|
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
|
||||||
r = SQL_SUCCESS_WITH_INFO;
|
r = SQL_SUCCESS_WITH_INFO;
|
||||||
}
|
}
|
||||||
|
@ -990,13 +990,13 @@ SQLRETURN sqlsrv_buffered_result_set::double_to_long( _In_ SQLSMALLINT field_ind
|
||||||
LONG* long_data = reinterpret_cast<LONG*>( buffer );
|
LONG* long_data = reinterpret_cast<LONG*>( buffer );
|
||||||
|
|
||||||
if( *double_data < double( LONG_MIN ) || *double_data > double( LONG_MAX )) {
|
if( *double_data < double( LONG_MIN ) || *double_data > double( LONG_MAX )) {
|
||||||
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) "22003",
|
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) "22003",
|
||||||
(SQLCHAR*) "Numeric value out of range", 0 );
|
(SQLCHAR*) "Numeric value out of range", 0 );
|
||||||
return SQL_ERROR;
|
return SQL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( *double_data != floor( *double_data )) {
|
if( *double_data != floor( *double_data )) {
|
||||||
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) "01S07",
|
last_error = new (sqlsrv_malloc( sizeof( sqlsrv_error ))) sqlsrv_error( (SQLCHAR*) "01S07",
|
||||||
(SQLCHAR*) "Fractional truncation", 0 );
|
(SQLCHAR*) "Fractional truncation", 0 );
|
||||||
return SQL_SUCCESS_WITH_INFO;
|
return SQL_SUCCESS_WITH_INFO;
|
||||||
}
|
}
|
||||||
|
@ -1024,7 +1024,7 @@ SQLRETURN sqlsrv_buffered_result_set::double_to_system_string( _In_ SQLSMALLINT
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLRETURN sqlsrv_buffered_result_set::long_to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
|
SQLRETURN sqlsrv_buffered_result_set::long_to_double( _In_ SQLSMALLINT field_index, _Out_writes_bytes_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
|
||||||
_Out_ SQLLEN* out_buffer_length )
|
_Out_ SQLLEN* out_buffer_length )
|
||||||
{
|
{
|
||||||
SQLSRV_ASSERT( meta[field_index].c_type == SQL_C_LONG, "Invalid conversion to long" );
|
SQLSRV_ASSERT( meta[field_index].c_type == SQL_C_LONG, "Invalid conversion to long" );
|
||||||
|
@ -1148,7 +1148,7 @@ SQLRETURN sqlsrv_buffered_result_set::wstring_to_long( _In_ SQLSMALLINT field_in
|
||||||
return SQL_SUCCESS;
|
return SQL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
|
SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( _In_ SQLSMALLINT field_index, _Out_writes_z_(*out_buffer_length) void* buffer, _In_ SQLLEN buffer_length,
|
||||||
_Out_ SQLLEN* out_buffer_length )
|
_Out_ SQLLEN* out_buffer_length )
|
||||||
{
|
{
|
||||||
SQLSRV_ASSERT( last_error == 0, "Pending error for sqlsrv_buffered_results_set::system_to_wide_string" );
|
SQLSRV_ASSERT( last_error == 0, "Pending error for sqlsrv_buffered_results_set::system_to_wide_string" );
|
||||||
|
@ -1184,7 +1184,7 @@ SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( _In_ SQLSMALLINT fi
|
||||||
if( (size_t) buffer_length < (field_len - read_so_far + sizeof(char)) * sizeof(WCHAR)) {
|
if( (size_t) buffer_length < (field_len - read_so_far + sizeof(char)) * sizeof(WCHAR)) {
|
||||||
|
|
||||||
to_copy = (buffer_length - sizeof(WCHAR)) / sizeof(WCHAR); // to_copy is the number of characters
|
to_copy = (buffer_length - sizeof(WCHAR)) / sizeof(WCHAR); // to_copy is the number of characters
|
||||||
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
|
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
|
||||||
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
|
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
|
||||||
r = SQL_SUCCESS_WITH_INFO;
|
r = SQL_SUCCESS_WITH_INFO;
|
||||||
}
|
}
|
||||||
|
@ -1204,20 +1204,20 @@ SQLRETURN sqlsrv_buffered_result_set::system_to_wide_string( _In_ SQLSMALLINT fi
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
int ch_space = SystemLocale::ToUtf16( CP_ACP, (LPCSTR) field_data, static_cast<int>(to_copy),
|
int ch_space = SystemLocale::ToUtf16( CP_ACP, (LPCSTR) field_data, static_cast<int>(to_copy),
|
||||||
static_cast<LPWSTR>(buffer), static_cast<int>(to_copy));
|
static_cast<LPWSTR>(buffer), static_cast<int>(to_copy));
|
||||||
|
|
||||||
#else
|
#else
|
||||||
int ch_space = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS, (LPCSTR) field_data, static_cast<int>(to_copy),
|
int ch_space = MultiByteToWideChar( CP_ACP, MB_ERR_INVALID_CHARS, (LPCSTR) field_data, static_cast<int>(to_copy),
|
||||||
static_cast<LPWSTR>(buffer), static_cast<int>(to_copy));
|
static_cast<LPWSTR>(buffer), static_cast<int>(to_copy));
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
|
|
||||||
if( ch_space == 0 ) {
|
if( ch_space == 0 ) {
|
||||||
|
|
||||||
switch( GetLastError() ) {
|
switch( GetLastError() ) {
|
||||||
|
|
||||||
case ERROR_NO_UNICODE_TRANSLATION:
|
case ERROR_NO_UNICODE_TRANSLATION:
|
||||||
// the theory here is the conversion failed because the end of the buffer we provided contained only
|
// the theory here is the conversion failed because the end of the buffer we provided contained only
|
||||||
// half a character at the end
|
// half a character at the end
|
||||||
if( !tried_again ) {
|
if( !tried_again ) {
|
||||||
to_copy--;
|
to_copy--;
|
||||||
|
@ -1295,7 +1295,7 @@ SQLRETURN sqlsrv_buffered_result_set::to_same_string( _In_ SQLSMALLINT field_ind
|
||||||
SQLLEN to_copy;
|
SQLLEN to_copy;
|
||||||
if( buffer_length < *out_buffer_length + extra ) {
|
if( buffer_length < *out_buffer_length + extra ) {
|
||||||
to_copy = buffer_length - extra;
|
to_copy = buffer_length - extra;
|
||||||
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
|
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
|
||||||
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
|
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
|
||||||
r = SQL_SUCCESS_WITH_INFO;
|
r = SQL_SUCCESS_WITH_INFO;
|
||||||
}
|
}
|
||||||
|
@ -1355,17 +1355,17 @@ SQLRETURN sqlsrv_buffered_result_set::wide_to_system_string( _In_ SQLSMALLINT fi
|
||||||
|
|
||||||
// allocate enough to handle WC -> DBCS conversion if it happens
|
// allocate enough to handle WC -> DBCS conversion if it happens
|
||||||
temp_string = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( field_len, sizeof(char), sizeof(char)));
|
temp_string = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( field_len, sizeof(char), sizeof(char)));
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
temp_length = SystemLocale::FromUtf16( CP_ACP, (LPCWSTR) field_data, static_cast<int>(field_len / sizeof(WCHAR)),
|
temp_length = SystemLocale::FromUtf16( CP_ACP, (LPCWSTR) field_data, static_cast<int>(field_len / sizeof(WCHAR)),
|
||||||
(LPSTR) temp_string.get(), static_cast<int>(field_len) );
|
(LPSTR) temp_string.get(), static_cast<int>(field_len) );
|
||||||
#else
|
#else
|
||||||
BOOL default_char_used = FALSE;
|
BOOL default_char_used = FALSE;
|
||||||
char default_char = '?';
|
char default_char = '?';
|
||||||
|
|
||||||
temp_length = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR) field_data, static_cast<int>(field_len / sizeof(WCHAR)),
|
temp_length = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR) field_data, static_cast<int>(field_len / sizeof(WCHAR)),
|
||||||
(LPSTR) temp_string.get(), static_cast<int>(field_len), &default_char, &default_char_used );
|
(LPSTR) temp_string.get(), static_cast<int>(field_len), &default_char, &default_char_used );
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
if( temp_length == 0 ) {
|
if( temp_length == 0 ) {
|
||||||
|
|
||||||
switch( GetLastError() ) {
|
switch( GetLastError() ) {
|
||||||
|
@ -1390,7 +1390,7 @@ SQLRETURN sqlsrv_buffered_result_set::wide_to_system_string( _In_ SQLSMALLINT fi
|
||||||
if( (size_t) buffer_length < (temp_length - read_so_far + sizeof(char))) {
|
if( (size_t) buffer_length < (temp_length - read_so_far + sizeof(char))) {
|
||||||
|
|
||||||
to_copy = buffer_length - sizeof(char);
|
to_copy = buffer_length - sizeof(char);
|
||||||
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
|
last_error = new ( sqlsrv_malloc( sizeof( sqlsrv_error )))
|
||||||
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
|
sqlsrv_error( (SQLCHAR*) "01004", (SQLCHAR*) "String data, right truncated", -1 );
|
||||||
r = SQL_SUCCESS_WITH_INFO;
|
r = SQL_SUCCESS_WITH_INFO;
|
||||||
}
|
}
|
||||||
|
@ -1469,7 +1469,7 @@ void cache_row_dtor( _In_ zval* data )
|
||||||
sqlsrv_free( cl );
|
sqlsrv_free( cl );
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLPOINTER read_lob_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ sqlsrv_buffered_result_set::meta_data& meta,
|
SQLPOINTER read_lob_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ sqlsrv_buffered_result_set::meta_data& meta,
|
||||||
_In_ zend_long mem_used )
|
_In_ zend_long mem_used )
|
||||||
{
|
{
|
||||||
SQLSMALLINT extra = 0;
|
SQLSMALLINT extra = 0;
|
||||||
|
@ -1515,8 +1515,8 @@ SQLPOINTER read_lob_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_in
|
||||||
// if the last read was successful, we're done
|
// if the last read was successful, we're done
|
||||||
if( r == SQL_SUCCESS ) {
|
if( r == SQL_SUCCESS ) {
|
||||||
// check to make sure we haven't overflown our memory limit
|
// check to make sure we haven't overflown our memory limit
|
||||||
CHECK_CUSTOM_ERROR( mem_used + last_field_len > stmt->buffered_query_limit * 1024, stmt,
|
CHECK_CUSTOM_ERROR( mem_used + last_field_len > stmt->buffered_query_limit * 1024, stmt,
|
||||||
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
|
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit, NULL) {
|
||||||
|
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
@ -1525,7 +1525,7 @@ SQLPOINTER read_lob_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_in
|
||||||
// else if it wasn't the truncated warning (01004) then we're done
|
// else if it wasn't the truncated warning (01004) then we're done
|
||||||
else if( r == SQL_SUCCESS_WITH_INFO ) {
|
else if( r == SQL_SUCCESS_WITH_INFO ) {
|
||||||
SQLSMALLINT len;
|
SQLSMALLINT len;
|
||||||
core::SQLGetDiagField( stmt, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len
|
core::SQLGetDiagField( stmt, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len
|
||||||
);
|
);
|
||||||
|
|
||||||
if( !is_truncated_warning( state )) {
|
if( !is_truncated_warning( state )) {
|
||||||
|
@ -1539,8 +1539,8 @@ SQLPOINTER read_lob_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_in
|
||||||
// if the type of the field returns the total to be read, we use that and preallocate the buffer
|
// if the type of the field returns the total to be read, we use that and preallocate the buffer
|
||||||
if( last_field_len != SQL_NO_TOTAL ) {
|
if( last_field_len != SQL_NO_TOTAL ) {
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR( mem_used + last_field_len > stmt->buffered_query_limit * 1024, stmt,
|
CHECK_CUSTOM_ERROR( mem_used + last_field_len > stmt->buffered_query_limit * 1024, stmt,
|
||||||
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
|
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit, NULL) {
|
||||||
|
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
@ -1554,8 +1554,8 @@ SQLPOINTER read_lob_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_in
|
||||||
// otherwise allocate another chunk of memory to read in
|
// otherwise allocate another chunk of memory to read in
|
||||||
else {
|
else {
|
||||||
to_read *= 2;
|
to_read *= 2;
|
||||||
CHECK_CUSTOM_ERROR( mem_used + to_read > stmt->buffered_query_limit * 1024, stmt,
|
CHECK_CUSTOM_ERROR( mem_used + to_read > stmt->buffered_query_limit * 1024, stmt,
|
||||||
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit ) {
|
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED, stmt->buffered_query_limit, NULL) {
|
||||||
|
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Core routines and constants shared by the Microsoft Drivers for PHP for SQL Server
|
// Contents: Core routines and constants shared by the Microsoft Drivers for PHP for SQL Server
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
@ -375,7 +375,7 @@ inline void sqlsrv_free_trace( _Inout_ void* ptr, _In_ const char* file, _In_ in
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Unlike their C standard library's counterparts the Zend Engine's memory management functions
|
// Unlike their C standard library's counterparts the Zend Engine's memory management functions
|
||||||
// emalloc or erealloc won't return NULL in case of an problem while allocating the requested
|
// emalloc or erealloc won't return NULL in case of an problem while allocating the requested
|
||||||
// memory but bail out and terminate the current request.
|
// memory but bail out and terminate the current request.
|
||||||
// Check www.phpinternalsbook.com/php7/memory_management/zend_memory_manager.html for details
|
// Check www.phpinternalsbook.com/php7/memory_management/zend_memory_manager.html for details
|
||||||
inline void* sqlsrv_malloc( _In_ size_t size )
|
inline void* sqlsrv_malloc( _In_ size_t size )
|
||||||
|
@ -1060,7 +1060,7 @@ enum SERVER_VERSION {
|
||||||
// supported driver versions.
|
// supported driver versions.
|
||||||
// ODBC 17 is the default
|
// ODBC 17 is the default
|
||||||
enum class ODBC_DRIVER : int
|
enum class ODBC_DRIVER : int
|
||||||
{
|
{
|
||||||
VER_17 = 17,
|
VER_17 = 17,
|
||||||
VER_18 = 18,
|
VER_18 = 18,
|
||||||
VER_13 = 13,
|
VER_13 = 13,
|
||||||
|
@ -1416,7 +1416,7 @@ struct sqlsrv_param
|
||||||
zval* param_ptr_z; // NULL by default - points to the original parameter or its reference
|
zval* param_ptr_z; // NULL by default - points to the original parameter or its reference
|
||||||
std::size_t num_bytes_read; // 0 by default - number of bytes processed so far (for an empty PHP stream, an empty string is sent to the server)
|
std::size_t num_bytes_read; // 0 by default - number of bytes processed so far (for an empty PHP stream, an empty string is sent to the server)
|
||||||
php_stream* param_stream; // NULL by default - used to send stream data from an input parameter to the server
|
php_stream* param_stream; // NULL by default - used to send stream data from an input parameter to the server
|
||||||
|
|
||||||
sqlsrv_param(_In_ SQLUSMALLINT param_num, _In_ SQLSMALLINT dir, _In_ SQLSRV_ENCODING enc, _In_ SQLSMALLINT sql_type, _In_ SQLULEN col_size, _In_ SQLSMALLINT dec_digits) :
|
sqlsrv_param(_In_ SQLUSMALLINT param_num, _In_ SQLSMALLINT dir, _In_ SQLSRV_ENCODING enc, _In_ SQLSMALLINT sql_type, _In_ SQLULEN col_size, _In_ SQLSMALLINT dec_digits) :
|
||||||
c_data_type(0), buffer(NULL), buffer_length(0), strlen_or_indptr(0), param_pos(param_num), direction(dir), encoding(enc), sql_data_type(sql_type),
|
c_data_type(0), buffer(NULL), buffer_length(0), strlen_or_indptr(0), param_pos(param_num), direction(dir), encoding(enc), sql_data_type(sql_type),
|
||||||
column_size(col_size), decimal_digits(dec_digits), param_php_type(0), was_null(false), param_ptr_z(NULL), num_bytes_read(0), param_stream(NULL)
|
column_size(col_size), decimal_digits(dec_digits), param_php_type(0), was_null(false), param_ptr_z(NULL), num_bytes_read(0), param_stream(NULL)
|
||||||
|
@ -1445,7 +1445,7 @@ struct sqlsrv_param
|
||||||
virtual void process_string_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z);
|
virtual void process_string_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z);
|
||||||
virtual void process_resource_param(_Inout_ zval* param_z);
|
virtual void process_resource_param(_Inout_ zval* param_z);
|
||||||
virtual void process_object_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z);
|
virtual void process_object_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z);
|
||||||
|
|
||||||
virtual void bind_param(_Inout_ sqlsrv_stmt* stmt);
|
virtual void bind_param(_Inout_ sqlsrv_stmt* stmt);
|
||||||
|
|
||||||
// The following methods are used to supply data to the server via SQLPutData
|
// The following methods are used to supply data to the server via SQLPutData
|
||||||
|
@ -1479,7 +1479,7 @@ struct sqlsrv_param_inout : public sqlsrv_param
|
||||||
|
|
||||||
// Resize the output string buffer based on its properties and whether it is a numeric type
|
// Resize the output string buffer based on its properties and whether it is a numeric type
|
||||||
void resize_output_string_buffer(_Inout_ zval* param_z, _In_ bool is_numeric_type);
|
void resize_output_string_buffer(_Inout_ zval* param_z, _In_ bool is_numeric_type);
|
||||||
|
|
||||||
// A helper method called by finalize_output_value() to finalize output string parameters
|
// A helper method called by finalize_output_value() to finalize output string parameters
|
||||||
void finalize_output_string();
|
void finalize_output_string();
|
||||||
};
|
};
|
||||||
|
@ -1493,7 +1493,7 @@ struct sqlsrv_param_inout : public sqlsrv_param
|
||||||
struct sqlsrv_param_tvp : public sqlsrv_param
|
struct sqlsrv_param_tvp : public sqlsrv_param
|
||||||
{
|
{
|
||||||
std::map<SQLUSMALLINT, sqlsrv_param_tvp*> tvp_columns; // The constituent columns of the table-valued parameter
|
std::map<SQLUSMALLINT, sqlsrv_param_tvp*> tvp_columns; // The constituent columns of the table-valued parameter
|
||||||
|
|
||||||
sqlsrv_param_tvp* parent_tvp; // For a TVP column to reference to the table-valued parameter. NULL if this is the TVP itself.
|
sqlsrv_param_tvp* parent_tvp; // For a TVP column to reference to the table-valued parameter. NULL if this is the TVP itself.
|
||||||
int num_rows; // The total number of rows
|
int num_rows; // The total number of rows
|
||||||
int current_row; // A counter to keep track of which row is to be processed
|
int current_row; // A counter to keep track of which row is to be processed
|
||||||
|
@ -1514,7 +1514,7 @@ struct sqlsrv_param_tvp : public sqlsrv_param
|
||||||
|
|
||||||
// Change the column encoding based on the sql data type
|
// Change the column encoding based on the sql data type
|
||||||
static void sql_type_to_encoding(_In_ SQLSMALLINT sql_type, _Inout_ SQLSRV_ENCODING* encoding);
|
static void sql_type_to_encoding(_In_ SQLSMALLINT sql_type, _Inout_ SQLSRV_ENCODING* encoding);
|
||||||
|
|
||||||
// The following methods are only applicable to a table-valued parameter or its individual columns
|
// The following methods are only applicable to a table-valued parameter or its individual columns
|
||||||
int parse_tv_param_arrays(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z);
|
int parse_tv_param_arrays(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z);
|
||||||
void get_tvp_metadata(_In_ sqlsrv_stmt* stmt, _In_ zend_string* table_type_name, _In_ zend_string* schema_name);
|
void get_tvp_metadata(_In_ sqlsrv_stmt* stmt, _In_ zend_string* table_type_name, _In_ zend_string* schema_name);
|
||||||
|
@ -2208,7 +2208,7 @@ namespace core {
|
||||||
// regular error handling
|
// regular error handling
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
CHECK_SQL_ERROR_OR_WARNING( rtemp, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( rtemp, stmt, NULL ) {
|
||||||
|
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
|
@ -2239,7 +2239,7 @@ namespace core {
|
||||||
SQLRETURN r = ::SQLGetDiagField( ctx->handle_type(), ctx->handle(), record_number, diag_identifier,
|
SQLRETURN r = ::SQLGetDiagField( ctx->handle_type(), ctx->handle(), record_number, diag_identifier,
|
||||||
diag_info_buffer, buffer_length, out_buffer_length );
|
diag_info_buffer, buffer_length, out_buffer_length );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, ctx ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, ctx, NULL) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2251,7 +2251,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLAllocHandle( HandleType, InputHandle.handle(), OutputHandlePtr );
|
r = ::SQLAllocHandle( HandleType, InputHandle.handle(), OutputHandlePtr );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, InputHandle ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, InputHandle, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2272,7 +2272,7 @@ namespace core {
|
||||||
r = ::SQLBindParameter( stmt->handle(), ParameterNumber, InputOutputType, ValueType, ParameterType, ColumnSize,
|
r = ::SQLBindParameter( stmt->handle(), ParameterNumber, InputOutputType, ValueType, ParameterType, ColumnSize,
|
||||||
DecimalDigits, ParameterValuePtr, BufferLength, StrLen_Or_IndPtr );
|
DecimalDigits, ParameterValuePtr, BufferLength, StrLen_Or_IndPtr );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2281,7 +2281,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r = ::SQLCloseCursor( stmt->handle() );
|
SQLRETURN r = ::SQLCloseCursor( stmt->handle() );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2293,7 +2293,7 @@ namespace core {
|
||||||
SQLRETURN r = ::SQLColAttribute( stmt->handle(), field_index, field_identifier, field_type_char,
|
SQLRETURN r = ::SQLColAttribute( stmt->handle(), field_index, field_identifier, field_type_char,
|
||||||
buffer_length, out_buffer_length, field_type_num );
|
buffer_length, out_buffer_length, field_type_num );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2305,7 +2305,7 @@ namespace core {
|
||||||
SQLRETURN r = ::SQLColAttributeW( stmt->handle(), field_index, field_identifier, field_type_char,
|
SQLRETURN r = ::SQLColAttributeW( stmt->handle(), field_index, field_identifier, field_type_char,
|
||||||
buffer_length, out_buffer_length, field_type_num );
|
buffer_length, out_buffer_length, field_type_num );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2318,7 +2318,7 @@ namespace core {
|
||||||
r = ::SQLDescribeCol( stmt->handle(), colno, col_name, col_name_length, col_name_length_out,
|
r = ::SQLDescribeCol( stmt->handle(), colno, col_name, col_name_length, col_name_length_out,
|
||||||
data_type, col_size, decimal_digits, nullable);
|
data_type, col_size, decimal_digits, nullable);
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2331,7 +2331,7 @@ namespace core {
|
||||||
r = ::SQLDescribeColW( stmt->handle(), colno, col_name, col_name_length, col_name_length_out,
|
r = ::SQLDescribeColW( stmt->handle(), colno, col_name, col_name_length, col_name_length_out,
|
||||||
data_type, col_size, decimal_digits, nullable );
|
data_type, col_size, decimal_digits, nullable );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2342,7 +2342,7 @@ namespace core {
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLDescribeParam( stmt->handle(), paramno, data_type, col_size, decimal_digits, nullable );
|
r = ::SQLDescribeParam( stmt->handle(), paramno, data_type, col_size, decimal_digits, nullable );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2352,7 +2352,7 @@ namespace core {
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLNumParams( stmt->handle(), num_params );
|
r = ::SQLNumParams( stmt->handle(), num_params );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2361,7 +2361,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r = ::SQLEndTran( handleType, conn->handle(), completionType );
|
SQLRETURN r = ::SQLEndTran( handleType, conn->handle(), completionType );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, conn ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, conn, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2373,7 +2373,7 @@ namespace core {
|
||||||
|
|
||||||
check_for_mars_error( stmt, r );
|
check_for_mars_error( stmt, r );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
|
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
|
@ -2387,7 +2387,7 @@ namespace core {
|
||||||
|
|
||||||
check_for_mars_error( stmt, r );
|
check_for_mars_error( stmt, r );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -2401,7 +2401,7 @@ namespace core {
|
||||||
|
|
||||||
check_for_mars_error( stmt, r );
|
check_for_mars_error( stmt, r );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2412,7 +2412,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r = ::SQLFetchScroll( stmt->handle(), fetch_orientation, fetch_offset );
|
SQLRETURN r = ::SQLFetchScroll( stmt->handle(), fetch_orientation, fetch_offset );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -2424,14 +2424,14 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLFreeHandle( ctx.handle_type(), ctx.handle() );
|
r = ::SQLFreeHandle( ctx.handle_type(), ctx.handle() );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, ctx ) {}
|
CHECK_SQL_ERROR_OR_WARNING( r, ctx, NULL ) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void SQLGetStmtAttr( _Inout_ sqlsrv_stmt* stmt, _In_ SQLINTEGER attr, _Out_writes_opt_(buf_len) void* value_ptr, _In_ SQLINTEGER buf_len, _Out_opt_ SQLINTEGER* str_len)
|
inline void SQLGetStmtAttr( _Inout_ sqlsrv_stmt* stmt, _In_ SQLINTEGER attr, _Out_writes_opt_(buf_len) void* value_ptr, _In_ SQLINTEGER buf_len, _Out_opt_ SQLINTEGER* str_len)
|
||||||
{
|
{
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLGetStmtAttr( stmt->handle(), attr, value_ptr, buf_len, str_len );
|
r = ::SQLGetStmtAttr( stmt->handle(), attr, value_ptr, buf_len, str_len );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2450,7 +2450,7 @@ namespace core {
|
||||||
}
|
}
|
||||||
|
|
||||||
if( handle_warning ) {
|
if( handle_warning ) {
|
||||||
CHECK_SQL_WARNING_AS_ERROR( r, stmt ) {
|
CHECK_SQL_WARNING_AS_ERROR( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2465,7 +2465,7 @@ namespace core {
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLGetInfo( conn->handle(), info_type, info_value, buffer_len, str_len );
|
r = ::SQLGetInfo( conn->handle(), info_type, info_value, buffer_len, str_len );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, conn ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, conn, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2476,7 +2476,7 @@ namespace core {
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLGetTypeInfo( stmt->handle(), data_type );
|
r = ::SQLGetTypeInfo( stmt->handle(), data_type );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2487,7 +2487,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r = ::SQLMoreResults( stmt->handle() );
|
SQLRETURN r = ::SQLMoreResults( stmt->handle() );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2500,7 +2500,7 @@ namespace core {
|
||||||
SQLSMALLINT num_cols;
|
SQLSMALLINT num_cols;
|
||||||
r = ::SQLNumResultCols( stmt->handle(), &num_cols );
|
r = ::SQLNumResultCols( stmt->handle(), &num_cols );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2513,7 +2513,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLParamData( stmt->handle(), value_ptr_ptr );
|
r = ::SQLParamData( stmt->handle(), value_ptr_ptr );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -2523,7 +2523,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLPrepareW( stmt->handle(), sql, sql_len );
|
r = ::SQLPrepareW( stmt->handle(), sql, sql_len );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2533,7 +2533,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLPutData( stmt->handle(), data_ptr, strlen_or_ind );
|
r = ::SQLPutData( stmt->handle(), data_ptr, strlen_or_ind );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2558,7 +2558,7 @@ namespace core {
|
||||||
return 0;
|
return 0;
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2571,7 +2571,7 @@ namespace core {
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLSetConnectAttr( ctx.handle(), attr, value_ptr, str_len );
|
r = ::SQLSetConnectAttr( ctx.handle(), attr, value_ptr, str_len );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, ctx ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, ctx, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2583,7 +2583,7 @@ namespace core {
|
||||||
core::SQLGetStmtAttr( stmt, SQL_ATTR_IMP_PARAM_DESC, &hIpd, 0, 0 );
|
core::SQLGetStmtAttr( stmt, SQL_ATTR_IMP_PARAM_DESC, &hIpd, 0, 0 );
|
||||||
if( value_ptr ) {
|
if( value_ptr ) {
|
||||||
r = ::SQLSetDescField( hIpd, rec_num, fld_id, value_ptr, str_len );
|
r = ::SQLSetDescField( hIpd, rec_num, fld_id, value_ptr, str_len );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2593,7 +2593,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLSetEnvAttr( ctx.handle(), attr, value_ptr, str_len );
|
r = ::SQLSetEnvAttr( ctx.handle(), attr, value_ptr, str_len );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, ctx ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, ctx, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2602,7 +2602,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r = ::SQLSetConnectAttr( conn->handle(), attribute, value_ptr, value_len );
|
SQLRETURN r = ::SQLSetConnectAttr( conn->handle(), attribute, value_ptr, value_len );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, conn ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, conn, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2611,7 +2611,7 @@ namespace core {
|
||||||
{
|
{
|
||||||
SQLRETURN r;
|
SQLRETURN r;
|
||||||
r = ::SQLSetStmtAttr( stmt->handle(), attr, value_ptr, str_len );
|
r = ::SQLSetStmtAttr( stmt->handle(), attr, value_ptr, str_len );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw CoreException();
|
throw CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Core routines that use statement handles shared between sqlsrv and pdo_sqlsrv
|
// Contents: Core routines that use statement handles shared between sqlsrv and pdo_sqlsrv
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
@ -162,7 +162,7 @@ sqlsrv_stmt::~sqlsrv_stmt( void )
|
||||||
// delete sensivity data
|
// delete sensivity data
|
||||||
clean_up_sensitivity_metadata();
|
clean_up_sensitivity_metadata();
|
||||||
|
|
||||||
// clean up metadata
|
// clean up metadata
|
||||||
clean_up_results_metadata();
|
clean_up_results_metadata();
|
||||||
|
|
||||||
invalidate();
|
invalidate();
|
||||||
|
@ -366,7 +366,7 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
|
||||||
_Inout_ SQLSMALLINT decimal_digits)
|
_Inout_ SQLSMALLINT decimal_digits)
|
||||||
{
|
{
|
||||||
// check is only < because params are 0 based
|
// check is only < because params are 0 based
|
||||||
CHECK_CUSTOM_ERROR(param_num >= SQL_SERVER_MAX_PARAMS, stmt, SQLSRV_ERROR_MAX_PARAMS_EXCEEDED, param_num + 1) {
|
CHECK_CUSTOM_ERROR(param_num >= SQL_SERVER_MAX_PARAMS, stmt, SQLSRV_ERROR_MAX_PARAMS_EXCEEDED, param_num + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
|
||||||
stmt->params_container.insert_param(param_num, new_param);
|
stmt->params_container.insert_param(param_num, new_param);
|
||||||
param_ptr = new_param;
|
param_ptr = new_param;
|
||||||
new_param.transferred();
|
new_param.transferred();
|
||||||
} else if (direction == SQL_PARAM_INPUT
|
} else if (direction == SQL_PARAM_INPUT
|
||||||
&& param_ptr->sql_data_type != SQL_SS_TABLE
|
&& param_ptr->sql_data_type != SQL_SS_TABLE
|
||||||
&& param_ptr->strlen_or_indptr == SQL_NULL_DATA) {
|
&& param_ptr->strlen_or_indptr == SQL_NULL_DATA) {
|
||||||
// reset the followings for regular input parameters if it was bound as a null param before
|
// reset the followings for regular input parameters if it was bound as a null param before
|
||||||
|
@ -408,16 +408,29 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
|
||||||
|
|
||||||
bool result = param_ptr->prepare_param(param_ref, param_z);
|
bool result = param_ptr->prepare_param(param_ref, param_z);
|
||||||
if (!result && direction == SQL_PARAM_INPUT_OUTPUT) {
|
if (!result && direction == SQL_PARAM_INPUT_OUTPUT) {
|
||||||
CHECK_CUSTOM_ERROR(!result, stmt, SQLSRV_ERROR_INPUT_OUTPUT_PARAM_TYPE_MATCH, param_num + 1) {
|
CHECK_CUSTOM_ERROR(!result, stmt, SQLSRV_ERROR_INPUT_OUTPUT_PARAM_TYPE_MATCH, param_num + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If Always Encrypted is enabled, transfer the known param meta data if applicable, which might alter param_z for decimal types
|
// If Always Encrypted is enabled, transfer the known param meta data if applicable, which might alter param_z for decimal types
|
||||||
if (stmt->conn->ce_option.enabled) {
|
if (stmt->conn->ce_option.enabled
|
||||||
if (param_ptr->sql_data_type == SQL_UNKNOWN_TYPE || param_ptr->column_size == SQLSRV_UNKNOWN_SIZE) {
|
&& (param_ptr->sql_data_type == SQL_UNKNOWN_TYPE || param_ptr->column_size == SQLSRV_UNKNOWN_SIZE)) {
|
||||||
// meta data parameters are always sorted based on parameter number
|
// meta data parameters are always sorted based on parameter number
|
||||||
param_ptr->copy_param_meta_ae(param_z, stmt->params_container.params_meta_ae[param_num]);
|
param_ptr->copy_param_meta_ae(param_z, stmt->params_container.params_meta_ae[param_num]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (Z_TYPE_P(param_z) == IS_STRING && column_size == SQLSRV_UNKNOWN_SIZE) {
|
||||||
|
size_t char_size = (encoding == SQLSRV_ENCODING_UTF8) ? sizeof(SQLWCHAR) : sizeof(char);
|
||||||
|
SQLULEN byte_len = Z_STRLEN_P(param_z) * char_size;
|
||||||
|
if (byte_len > SQL_SERVER_MAX_FIELD_SIZE) {
|
||||||
|
param_ptr->column_size = SQL_SERVER_MAX_TYPE_SIZE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (param_ptr->column_size == SQLSRV_UNKNOWN_SIZE) {
|
||||||
|
param_ptr->column_size = SQL_SERVER_MAX_FIELD_SIZE / char_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +442,7 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
|
||||||
// For a parameter targeting a SmallDatetime column, the return values are SQL_TYPE_TIMESTAMP, 16, and 0. Inputting these values into SQLBindParameter() results in Operand type clash error.
|
// For a parameter targeting a SmallDatetime column, the return values are SQL_TYPE_TIMESTAMP, 16, and 0. Inputting these values into SQLBindParameter() results in Operand type clash error.
|
||||||
// This is because SQL_TYPE_TIMESTAMP corresponds to Datetime2 by default, and conversion of Datetime2 to Datetime and conversion of Datetime2 to SmallDatatime is not allowed with encrypted columns.
|
// This is because SQL_TYPE_TIMESTAMP corresponds to Datetime2 by default, and conversion of Datetime2 to Datetime and conversion of Datetime2 to SmallDatatime is not allowed with encrypted columns.
|
||||||
// To fix the conversion problem, set the SQL_CA_SS_SERVER_TYPE field of the parameter to SQL_SS_TYPE_DATETIME and SQL_SS_TYPE_SMALLDATETIME respectively for a Datetime and Smalldatetime column.
|
// To fix the conversion problem, set the SQL_CA_SS_SERVER_TYPE field of the parameter to SQL_SS_TYPE_DATETIME and SQL_SS_TYPE_SMALLDATETIME respectively for a Datetime and Smalldatetime column.
|
||||||
// Note this must be called after SQLBindParameter() or SQLSetDescField() may fail.
|
// Note this must be called after SQLBindParameter() or SQLSetDescField() may fail.
|
||||||
// VSO BUG 2693: how to correctly distinguish datetime from datetime2(3)? Both have the same decimal_digits and column_size
|
// VSO BUG 2693: how to correctly distinguish datetime from datetime2(3)? Both have the same decimal_digits and column_size
|
||||||
if (stmt->conn->ce_option.enabled && param_ptr->sql_data_type == SQL_TYPE_TIMESTAMP) {
|
if (stmt->conn->ce_option.enabled && param_ptr->sql_data_type == SQL_TYPE_TIMESTAMP) {
|
||||||
if (param_ptr->decimal_digits == 3) {
|
if (param_ptr->decimal_digits == 3) {
|
||||||
|
@ -476,7 +489,7 @@ SQLRETURN core_sqlsrv_execute( _Inout_ sqlsrv_stmt* stmt, _In_reads_bytes_(sql_l
|
||||||
wsql_string = utf16_string_from_mbcs_string( encoding, reinterpret_cast<const char*>( sql ),
|
wsql_string = utf16_string_from_mbcs_string( encoding, reinterpret_cast<const char*>( sql ),
|
||||||
sql_len, &wsql_len );
|
sql_len, &wsql_len );
|
||||||
CHECK_CUSTOM_ERROR( wsql_string == 0, stmt, SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE,
|
CHECK_CUSTOM_ERROR( wsql_string == 0, stmt, SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE,
|
||||||
get_last_error_message() ) {
|
get_last_error_message(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -633,7 +646,7 @@ field_meta_data* core_sqlsrv_field_metadata( _Inout_ sqlsrv_stmt* stmt, _In_ SQL
|
||||||
|
|
||||||
bool converted = convert_string_from_utf16( encoding, field_name_temp, field_len_temp, ( char** ) &( meta_data->field_name ), field_name_len );
|
bool converted = convert_string_from_utf16( encoding, field_name_temp, field_len_temp, ( char** ) &( meta_data->field_name ), field_name_len );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR( !converted, stmt, SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE, get_last_error_message() ) {
|
CHECK_CUSTOM_ERROR( !converted, stmt, SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE, get_last_error_message(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,7 +724,7 @@ void core_sqlsrv_sensitivity_metadata( _Inout_ sqlsrv_stmt* stmt )
|
||||||
// To retrieve sensitivity classfication data, the first step is to retrieve the IRD(Implementation Row Descriptor) handle by
|
// To retrieve sensitivity classfication data, the first step is to retrieve the IRD(Implementation Row Descriptor) handle by
|
||||||
// calling SQLGetStmtAttr with SQL_ATTR_IMP_ROW_DESC statement attribute
|
// calling SQLGetStmtAttr with SQL_ATTR_IMP_ROW_DESC statement attribute
|
||||||
r = ::SQLGetStmtAttr(stmt->handle(), SQL_ATTR_IMP_ROW_DESC, reinterpret_cast<SQLPOINTER*>(&ird), SQL_IS_POINTER, 0);
|
r = ::SQLGetStmtAttr(stmt->handle(), SQL_ATTR_IMP_ROW_DESC, reinterpret_cast<SQLPOINTER*>(&ird), SQL_IS_POINTER, 0);
|
||||||
CHECK_SQL_ERROR_OR_WARNING(r, stmt) {
|
CHECK_SQL_ERROR_OR_WARNING(r, stmt, NULL) {
|
||||||
LOG(SEV_ERROR, "core_sqlsrv_sensitivity_metadata: failed in getting Implementation Row Descriptor handle." );
|
LOG(SEV_ERROR, "core_sqlsrv_sensitivity_metadata: failed in getting Implementation Row Descriptor handle." );
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
@ -728,7 +741,7 @@ void core_sqlsrv_sensitivity_metadata( _Inout_ sqlsrv_stmt* stmt )
|
||||||
SQLSMALLINT len;
|
SQLSMALLINT len;
|
||||||
rc = ::SQLGetDiagField(SQL_HANDLE_DESC, ird, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len);
|
rc = ::SQLGetDiagField(SQL_HANDLE_DESC, ird, 1, SQL_DIAG_SQLSTATE, state, SQL_SQLSTATE_BUFSIZE, &len);
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING(rc, stmt) {
|
CHECK_SQL_ERROR_OR_WARNING(rc, stmt, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,7 +749,7 @@ void core_sqlsrv_sensitivity_metadata( _Inout_ sqlsrv_stmt* stmt )
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(true, stmt, SQLSRV_ERROR_DATA_CLASSIFICATION_FAILED, "Check if ODBC driver or the server supports the Data Classification feature.") {
|
CHECK_CUSTOM_ERROR(true, stmt, SQLSRV_ERROR_DATA_CLASSIFICATION_FAILED, "Check if ODBC driver or the server supports the Data Classification feature.", NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -748,7 +761,7 @@ void core_sqlsrv_sensitivity_metadata( _Inout_ sqlsrv_stmt* stmt )
|
||||||
if (r != SQL_SUCCESS) {
|
if (r != SQL_SUCCESS) {
|
||||||
LOG(SEV_ERROR, "core_sqlsrv_sensitivity_metadata: failed in calling SQLGetDescFieldW again." );
|
LOG(SEV_ERROR, "core_sqlsrv_sensitivity_metadata: failed in calling SQLGetDescFieldW again." );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(true, stmt, SQLSRV_ERROR_DATA_CLASSIFICATION_FAILED, "SQLGetDescFieldW failed unexpectedly") {
|
CHECK_CUSTOM_ERROR(true, stmt, SQLSRV_ERROR_DATA_CLASSIFICATION_FAILED, "SQLGetDescFieldW failed unexpectedly", NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -756,7 +769,7 @@ void core_sqlsrv_sensitivity_metadata( _Inout_ sqlsrv_stmt* stmt )
|
||||||
// Start parsing the data (blob)
|
// Start parsing the data (blob)
|
||||||
using namespace data_classification;
|
using namespace data_classification;
|
||||||
|
|
||||||
// If make it this far, must be using ODBC 17.2 or above. Prior to ODBC 17.4, checking Data Classification version will fail.
|
// If make it this far, must be using ODBC 17.2 or above. Prior to ODBC 17.4, checking Data Classification version will fail.
|
||||||
// When the function is successful and the version is right, rank info is available for retrieval
|
// When the function is successful and the version is right, rank info is available for retrieval
|
||||||
bool getRankInfo = false;
|
bool getRankInfo = false;
|
||||||
r = ::SQLGetDescFieldW(ird, 0, SQL_CA_SS_DATA_CLASSIFICATION_VERSION, reinterpret_cast<SQLPOINTER>(&dcVersion), SQL_IS_INTEGER, &dcIRD);
|
r = ::SQLGetDescFieldW(ird, 0, SQL_CA_SS_DATA_CLASSIFICATION_VERSION, reinterpret_cast<SQLPOINTER>(&dcVersion), SQL_IS_INTEGER, &dcIRD);
|
||||||
|
@ -780,7 +793,7 @@ void core_sqlsrv_sensitivity_metadata( _Inout_ sqlsrv_stmt* stmt )
|
||||||
unsigned char *dcend = dcbuf;
|
unsigned char *dcend = dcbuf;
|
||||||
dcend += dclen;
|
dcend += dclen;
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(dcptr != dcend, stmt, SQLSRV_ERROR_DATA_CLASSIFICATION_FAILED, "Metadata parsing ends unexpectedly") {
|
CHECK_CUSTOM_ERROR(dcptr != dcend, stmt, SQLSRV_ERROR_DATA_CLASSIFICATION_FAILED, "Metadata parsing ends unexpectedly", NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1071,7 +1084,7 @@ void core_sqlsrv_set_query_timeout( _Inout_ sqlsrv_stmt* stmt, _Inout_ zval* val
|
||||||
if( Z_TYPE_P( value_z ) != IS_LONG || Z_LVAL_P( value_z ) < 0 ) {
|
if( Z_TYPE_P( value_z ) != IS_LONG || Z_LVAL_P( value_z ) < 0 ) {
|
||||||
|
|
||||||
convert_to_string( value_z );
|
convert_to_string( value_z );
|
||||||
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE, Z_STRVAL_P( value_z ) );
|
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE, Z_STRVAL_P( value_z ), NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the query timeout setting for processing later
|
// Save the query timeout setting for processing later
|
||||||
|
@ -1354,7 +1367,7 @@ size_t calc_utf8_missing( _Inout_ sqlsrv_stmt* stmt, _In_reads_(buffer_end) cons
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INPUT_STREAM_ENCODING_TRANSLATE,
|
THROW_CORE_ERROR( stmt, SQLSRV_ERROR_INPUT_STREAM_ENCODING_TRANSLATE,
|
||||||
get_last_error_message( ERROR_NO_UNICODE_TRANSLATION ));
|
get_last_error_message( ERROR_NO_UNICODE_TRANSLATION ), NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1379,7 +1392,7 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
|
||||||
|
|
||||||
// make sure that fields are not retrieved incorrectly.
|
// make sure that fields are not retrieved incorrectly.
|
||||||
CHECK_CUSTOM_ERROR( stmt->last_field_index > field_index, stmt, SQLSRV_ERROR_FIELD_INDEX_ERROR, field_index,
|
CHECK_CUSTOM_ERROR( stmt->last_field_index > field_index, stmt, SQLSRV_ERROR_FIELD_INDEX_ERROR, field_index,
|
||||||
stmt->last_field_index ) {
|
stmt->last_field_index, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1394,11 +1407,11 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
|
||||||
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_LONG, field_value_temp, sizeof( SQLLEN ),
|
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_LONG, field_value_temp, sizeof( SQLLEN ),
|
||||||
field_len, true /*handle_warning*/ );
|
field_len, true /*handle_warning*/ );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( r == SQL_NO_DATA ), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
|
CHECK_CUSTOM_ERROR(( r == SQL_NO_DATA ), stmt, SQLSRV_ERROR_NO_DATA, field_index, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1421,11 +1434,11 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
|
||||||
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_DOUBLE, field_value_temp, sizeof( double ),
|
SQLRETURN r = stmt->current_results->get_data( field_index + 1, SQL_C_DOUBLE, field_value_temp, sizeof( double ),
|
||||||
field_len, true /*handle_warning*/ );
|
field_len, true /*handle_warning*/ );
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( r == SQL_NO_DATA ), stmt, SQLSRV_ERROR_NO_DATA, field_index ) {
|
CHECK_CUSTOM_ERROR(( r == SQL_NO_DATA ), stmt, SQLSRV_ERROR_NO_DATA, field_index, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1464,7 +1477,7 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
|
||||||
field_len_temp = 0;
|
field_len_temp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR((r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index) {
|
CHECK_CUSTOM_ERROR((r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1491,7 +1504,7 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// For a sqlsrv stream, only REPORT_ERRORS may be used. For "mode", the 'b' option
|
// For a sqlsrv stream, only REPORT_ERRORS may be used. For "mode", the 'b' option
|
||||||
// is ignored on POSIX systems, which treat text and binary files the same. Yet, the
|
// is ignored on POSIX systems, which treat text and binary files the same. Yet, the
|
||||||
// 'b' option might be important in other systems.
|
// 'b' option might be important in other systems.
|
||||||
// For details check https://www.php.net/manual/en/internals2.ze1.streams.php
|
// For details check https://www.php.net/manual/en/internals2.ze1.streams.php
|
||||||
|
@ -1609,7 +1622,7 @@ void format_decimal_numbers(_In_ SQLSMALLINT decimals_places, _In_ SQLSMALLINT f
|
||||||
if (num_decimals > scale) {
|
if (num_decimals > scale) {
|
||||||
last_pos = round_up_decimal_numbers(buffer, (pt - src) + offset, scale, offset, last_pos);
|
last_pos = round_up_decimal_numbers(buffer, (pt - src) + offset, scale, offset, last_pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the extra white space if not used. For a negative number,
|
// Remove the extra white space if not used. For a negative number,
|
||||||
// the first pos is always a space
|
// the first pos is always a space
|
||||||
|
@ -1621,7 +1634,7 @@ void format_decimal_numbers(_In_ SQLSMALLINT decimals_places, _In_ SQLSMALLINT f
|
||||||
if (is_negative) {
|
if (is_negative) {
|
||||||
buffer[--offset] = '-';
|
buffer[--offset] = '-';
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = last_pos - offset;
|
int len = last_pos - offset;
|
||||||
memcpy_s(field_value, len, buffer + offset, len);
|
memcpy_s(field_value, len, buffer + offset, len);
|
||||||
field_value[len] = '\0';
|
field_value[len] = '\0';
|
||||||
|
@ -1672,7 +1685,7 @@ void get_field_as_string(_Inout_ sqlsrv_stmt *stmt, _In_ SQLUSMALLINT field_inde
|
||||||
} else {
|
} else {
|
||||||
c_type = SQL_C_CHAR;
|
c_type = SQL_C_CHAR;
|
||||||
extra = sizeof(SQLCHAR);
|
extra = sizeof(SQLCHAR);
|
||||||
|
|
||||||
// For numbers, no need to convert
|
// For numbers, no need to convert
|
||||||
if (sqlsrv_php_type.typeinfo.encoding == CP_UTF8 && !is_a_numeric_type(sql_field_type)) {
|
if (sqlsrv_php_type.typeinfo.encoding == CP_UTF8 && !is_a_numeric_type(sql_field_type)) {
|
||||||
c_type = SQL_C_WCHAR;
|
c_type = SQL_C_WCHAR;
|
||||||
|
@ -1683,8 +1696,8 @@ void get_field_as_string(_Inout_ sqlsrv_stmt *stmt, _In_ SQLUSMALLINT field_inde
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a large type, then read the first chunk to get the actual length from SQLGetData
|
// If this is a large type, then read the first chunk to get the actual length from SQLGetData
|
||||||
// The user may use "SET TEXTSIZE" to specify the size of varchar(max), nvarchar(max),
|
// The user may use "SET TEXTSIZE" to specify the size of varchar(max), nvarchar(max),
|
||||||
// varbinary(max), text, ntext, and image data returned by a SELECT statement.
|
// varbinary(max), text, ntext, and image data returned by a SELECT statement.
|
||||||
// For varbinary(max), varchar(max) and nvarchar(max), sql_display_size will be 0, regardless
|
// For varbinary(max), varchar(max) and nvarchar(max), sql_display_size will be 0, regardless
|
||||||
if (sql_display_size == 0 ||
|
if (sql_display_size == 0 ||
|
||||||
(sql_field_type == SQL_WLONGVARCHAR || sql_field_type == SQL_LONGVARCHAR || sql_field_type == SQL_LONGVARBINARY)) {
|
(sql_field_type == SQL_WLONGVARCHAR || sql_field_type == SQL_LONGVARCHAR || sql_field_type == SQL_LONGVARBINARY)) {
|
||||||
|
@ -1700,7 +1713,7 @@ void get_field_as_string(_Inout_ sqlsrv_stmt *stmt, _In_ SQLUSMALLINT field_inde
|
||||||
r = stmt->current_results->get_data(field_index + 1, c_type, field_value_temp, sql_display_size + extra, &field_len_temp, false /*handle_warning*/);
|
r = stmt->current_results->get_data(field_index + 1, c_type, field_value_temp, sql_display_size + extra, &field_len_temp, false /*handle_warning*/);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR((r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index) {
|
CHECK_CUSTOM_ERROR((r == SQL_NO_DATA), stmt, SQLSRV_ERROR_NO_DATA, field_index, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1750,7 +1763,7 @@ void get_field_as_string(_Inout_ sqlsrv_stmt *stmt, _In_ SQLUSMALLINT field_inde
|
||||||
} while (r == SQL_SUCCESS_WITH_INFO && is_truncated_warning(state));
|
} while (r == SQL_SUCCESS_WITH_INFO && is_truncated_warning(state));
|
||||||
} // if (field_len_temp == SQL_NO_TOTAL)
|
} // if (field_len_temp == SQL_NO_TOTAL)
|
||||||
else {
|
else {
|
||||||
// The field length (or its estimate) is returned, thus no need to double the allocation size.
|
// The field length (or its estimate) is returned, thus no need to double the allocation size.
|
||||||
// Allocate field_len_temp (which is the field length retrieved from the first SQLGetData) but with some padding
|
// Allocate field_len_temp (which is the field length retrieved from the first SQLGetData) but with some padding
|
||||||
// because there is a chance that the estimated field_len_temp is not accurate enough
|
// because there is a chance that the estimated field_len_temp is not accurate enough
|
||||||
SQLLEN buffer_len = 50;
|
SQLLEN buffer_len = 50;
|
||||||
|
@ -1762,7 +1775,7 @@ void get_field_as_string(_Inout_ sqlsrv_stmt *stmt, _In_ SQLUSMALLINT field_inde
|
||||||
field_len_temp + buffer_len, &chunk_field_len, false /*handle_warning*/);
|
field_len_temp + buffer_len, &chunk_field_len, false /*handle_warning*/);
|
||||||
field_len_temp = initial_field_len + chunk_field_len;
|
field_len_temp = initial_field_len + chunk_field_len;
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING(r, stmt) {
|
CHECK_SQL_ERROR_OR_WARNING(r, stmt, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1772,7 +1785,7 @@ void get_field_as_string(_Inout_ sqlsrv_stmt *stmt, _In_ SQLUSMALLINT field_inde
|
||||||
} // if (is_truncated_warning(state))
|
} // if (is_truncated_warning(state))
|
||||||
} // if (r == SQL_SUCCESS_WITH_INFO)
|
} // if (r == SQL_SUCCESS_WITH_INFO)
|
||||||
|
|
||||||
CHECK_SQL_ERROR_OR_WARNING(r, stmt) {
|
CHECK_SQL_ERROR_OR_WARNING(r, stmt, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1780,7 +1793,7 @@ void get_field_as_string(_Inout_ sqlsrv_stmt *stmt, _In_ SQLUSMALLINT field_inde
|
||||||
bool converted = convert_string_from_utf16_inplace(static_cast<SQLSRV_ENCODING>(sqlsrv_php_type.typeinfo.encoding),
|
bool converted = convert_string_from_utf16_inplace(static_cast<SQLSRV_ENCODING>(sqlsrv_php_type.typeinfo.encoding),
|
||||||
&field_value_temp, field_len_temp);
|
&field_value_temp, field_len_temp);
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(!converted, stmt, SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE, get_last_error_message()) {
|
CHECK_CUSTOM_ERROR(!converted, stmt, SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE, get_last_error_message(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1879,11 +1892,11 @@ bool is_valid_sqlsrv_phptype( _In_ sqlsrv_phptype type )
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void adjustDecimalPrecision(_Inout_ zval* param_z, _In_ SQLSMALLINT decimal_digits)
|
void adjustDecimalPrecision(_Inout_ zval* param_z, _In_ SQLSMALLINT decimal_digits)
|
||||||
{
|
{
|
||||||
char* value = Z_STRVAL_P(param_z);
|
char* value = Z_STRVAL_P(param_z);
|
||||||
int value_len = Z_STRLEN_P(param_z);
|
int value_len = Z_STRLEN_P(param_z);
|
||||||
|
|
||||||
// If the length is greater than maxDecimalStrLen, do not convert the string
|
// If the length is greater than maxDecimalStrLen, do not convert the string
|
||||||
// 6 is derived from: 1 for the decimal point; 1 for sign of the number; 1 for 'e' or 'E' (scientific notation);
|
// 6 is derived from: 1 for the decimal point; 1 for sign of the number; 1 for 'e' or 'E' (scientific notation);
|
||||||
// 1 for sign of scientific exponent; 2 for length of scientific exponent
|
// 1 for sign of scientific exponent; 2 for length of scientific exponent
|
||||||
|
@ -1902,7 +1915,7 @@ void adjustDecimalPrecision(_Inout_ zval* param_z, _In_ SQLSMALLINT decimal_digi
|
||||||
return; // invalid input caused the conversion to throw an exception
|
return; // invalid input caused the conversion to throw an exception
|
||||||
}
|
}
|
||||||
if (index < value_len) {
|
if (index < value_len) {
|
||||||
return; // the input contains something else apart from the numerical value
|
return; // the input contains something else apart from the numerical value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigate to the first digit or the decimal point
|
// Navigate to the first digit or the decimal point
|
||||||
|
@ -1956,7 +1969,7 @@ void adjustDecimalPrecision(_Inout_ zval* param_z, _In_ SQLSMALLINT decimal_digi
|
||||||
if (num_decimals > decimal_digits) {
|
if (num_decimals > decimal_digits) {
|
||||||
round_up_decimal_numbers(buffer, (pt - src) + offset, decimal_digits, offset, length + offset);
|
round_up_decimal_numbers(buffer, (pt - src) + offset, decimal_digits, offset, length + offset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int oldpos = 0;
|
int oldpos = 0;
|
||||||
if (pt == NULL) {
|
if (pt == NULL) {
|
||||||
|
@ -1998,7 +2011,7 @@ void adjustDecimalPrecision(_Inout_ zval* param_z, _In_ SQLSMALLINT decimal_digi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start copying the content to the buffer until the exp sign or one more digit after decimal_digits
|
// Start copying the content to the buffer until the exp sign or one more digit after decimal_digits
|
||||||
char *p = src;
|
char *p = src;
|
||||||
int idx = offset;
|
int idx = offset;
|
||||||
int lastpos = newpos + decimal_digits + 1;
|
int lastpos = newpos + decimal_digits + 1;
|
||||||
|
@ -2018,7 +2031,7 @@ void adjustDecimalPrecision(_Inout_ zval* param_z, _In_ SQLSMALLINT decimal_digi
|
||||||
if (num_decimals > decimal_digits) {
|
if (num_decimals > decimal_digits) {
|
||||||
round_up_decimal_numbers(buffer, newpos, decimal_digits, offset, idx);
|
round_up_decimal_numbers(buffer, newpos, decimal_digits, offset, idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the minus sign if negative
|
// Set the minus sign if negative
|
||||||
|
@ -2067,7 +2080,7 @@ int round_up_decimal_numbers(_Inout_ char* buffer, _In_ int decimal_pos, _In_ in
|
||||||
buffer[pos] = '\0';
|
buffer[pos] = '\0';
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do nothing and just return
|
// Do nothing and just return
|
||||||
return lastpos;
|
return lastpos;
|
||||||
|
@ -2117,9 +2130,9 @@ bool sqlsrv_param::prepare_param(_In_ zval* param_ref, _Inout_ zval* param_z)
|
||||||
// If SQL type or column size is unknown, derives the appropriate values as well using the provided param zval and encoding
|
// If SQL type or column size is unknown, derives the appropriate values as well using the provided param zval and encoding
|
||||||
void sqlsrv_param::process_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z)
|
void sqlsrv_param::process_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_z)
|
||||||
{
|
{
|
||||||
// Get param php type
|
// Get param php type
|
||||||
param_php_type = Z_TYPE_P(param_z);
|
param_php_type = Z_TYPE_P(param_z);
|
||||||
|
|
||||||
switch (param_php_type) {
|
switch (param_php_type) {
|
||||||
case IS_NULL:
|
case IS_NULL:
|
||||||
process_null_param(param_z);
|
process_null_param(param_z);
|
||||||
|
@ -2145,7 +2158,7 @@ void sqlsrv_param::process_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* param_
|
||||||
break;
|
break;
|
||||||
case IS_ARRAY:
|
case IS_ARRAY:
|
||||||
default:
|
default:
|
||||||
THROW_CORE_ERROR(stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_pos + 1);
|
THROW_CORE_ERROR(stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_pos + 1, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2203,8 +2216,8 @@ void sqlsrv_param::process_long_param(_Inout_ zval* param_z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When binding any integer, the zend_long value and its length are used as the buffer
|
// When binding any integer, the zend_long value and its length are used as the buffer
|
||||||
// and buffer length. When the buffer is 8 bytes use the corresponding C type for
|
// and buffer length. When the buffer is 8 bytes use the corresponding C type for
|
||||||
// 8-byte integers
|
// 8-byte integers
|
||||||
#ifdef ZEND_ENABLE_ZVAL_LONG64
|
#ifdef ZEND_ENABLE_ZVAL_LONG64
|
||||||
c_data_type = SQL_C_SBIGINT;
|
c_data_type = SQL_C_SBIGINT;
|
||||||
|
@ -2272,18 +2285,6 @@ bool sqlsrv_param::derive_string_types_sizes(_In_ zval* param_z)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Derive the column size also only if it is unknown
|
|
||||||
if (column_size == SQLSRV_UNKNOWN_SIZE) {
|
|
||||||
size_t char_size = (encoding == SQLSRV_ENCODING_UTF8) ? sizeof(SQLWCHAR) : sizeof(char);
|
|
||||||
SQLULEN byte_len = Z_STRLEN_P(param_z) * char_size;
|
|
||||||
|
|
||||||
if (byte_len > SQL_SERVER_MAX_FIELD_SIZE) {
|
|
||||||
column_size = SQL_SERVER_MAX_TYPE_SIZE;
|
|
||||||
} else {
|
|
||||||
column_size = SQL_SERVER_MAX_FIELD_SIZE / char_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return is_numeric;
|
return is_numeric;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2316,7 +2317,7 @@ void sqlsrv_param::process_string_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval*
|
||||||
bool is_numeric = derive_string_types_sizes(param_z);
|
bool is_numeric = derive_string_types_sizes(param_z);
|
||||||
|
|
||||||
// With AE, the precision of the decimal or numeric inputs have to match exactly as defined in the columns.
|
// With AE, the precision of the decimal or numeric inputs have to match exactly as defined in the columns.
|
||||||
// Without AE, the derived default sql types will not be this specific. Thus, if sql_type is SQL_DECIMAL
|
// Without AE, the derived default sql types will not be this specific. Thus, if sql_type is SQL_DECIMAL
|
||||||
// or SQL_NUMERIC, the user must have clearly specified it (using the SQLSRV driver) as SQL_DECIMAL or SQL_NUMERIC.
|
// or SQL_NUMERIC, the user must have clearly specified it (using the SQLSRV driver) as SQL_DECIMAL or SQL_NUMERIC.
|
||||||
// In either case, the input passed into SQLBindParam requires matching scale (i.e., number of decimal digits).
|
// In either case, the input passed into SQLBindParam requires matching scale (i.e., number of decimal digits).
|
||||||
if (sql_data_type == SQL_DECIMAL || sql_data_type == SQL_NUMERIC) {
|
if (sql_data_type == SQL_DECIMAL || sql_data_type == SQL_NUMERIC) {
|
||||||
|
@ -2331,7 +2332,7 @@ void sqlsrv_param::process_string_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval*
|
||||||
}
|
}
|
||||||
// This changes the member placeholder_z to hold the wide string
|
// This changes the member placeholder_z to hold the wide string
|
||||||
bool converted = convert_input_str_to_utf16(stmt, param_z);
|
bool converted = convert_input_str_to_utf16(stmt, param_z);
|
||||||
CHECK_CUSTOM_ERROR(!converted, stmt, SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE, param_pos + 1, get_last_error_message()) {
|
CHECK_CUSTOM_ERROR(!converted, stmt, SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE, param_pos + 1, get_last_error_message(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2491,7 +2492,7 @@ void sqlsrv_param::process_object_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval*
|
||||||
if (succeeded) {
|
if (succeeded) {
|
||||||
succeeded = convert_datetime_to_string(stmt, param_z);
|
succeeded = convert_datetime_to_string(stmt, param_z);
|
||||||
}
|
}
|
||||||
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2560,7 +2561,7 @@ bool sqlsrv_param::send_data_packet(_Inout_ sqlsrv_stmt* stmt)
|
||||||
SQLWCHAR wbuffer[PHP_STREAM_BUFFER_SIZE + 1] = { L'\0' };
|
SQLWCHAR wbuffer[PHP_STREAM_BUFFER_SIZE + 1] = { L'\0' };
|
||||||
int wbuffer_size = static_cast<int>(sizeof(wbuffer) / sizeof(SQLWCHAR));
|
int wbuffer_size = static_cast<int>(sizeof(wbuffer) / sizeof(SQLWCHAR));
|
||||||
DWORD last_error_code = ERROR_SUCCESS;
|
DWORD last_error_code = ERROR_SUCCESS;
|
||||||
|
|
||||||
// The buffer_size is the # of wchars. Set to buffer_size / 2
|
// The buffer_size is the # of wchars. Set to buffer_size / 2
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
int wsize = SystemLocale::ToUtf16Strict(encoding, buffer, static_cast<int>(read), wbuffer, wbuffer_size, &last_error_code);
|
int wsize = SystemLocale::ToUtf16Strict(encoding, buffer, static_cast<int>(read), wbuffer, wbuffer_size, &last_error_code);
|
||||||
|
@ -2576,7 +2577,7 @@ bool sqlsrv_param::send_data_packet(_Inout_ sqlsrv_stmt* stmt)
|
||||||
// read the missing bytes
|
// read the missing bytes
|
||||||
size_t new_read = php_stream_read(param_stream, static_cast<char*>(buffer) + read, need_to_read);
|
size_t new_read = php_stream_read(param_stream, static_cast<char*>(buffer) + read, need_to_read);
|
||||||
// if the bytes couldn't be read, then we return an error
|
// if the bytes couldn't be read, then we return an error
|
||||||
CHECK_CUSTOM_ERROR(new_read != need_to_read, stmt, SQLSRV_ERROR_INPUT_STREAM_ENCODING_TRANSLATE, get_last_error_message(ERROR_NO_UNICODE_TRANSLATION)) {
|
CHECK_CUSTOM_ERROR(new_read != need_to_read, stmt, SQLSRV_ERROR_INPUT_STREAM_ENCODING_TRANSLATE, get_last_error_message(ERROR_NO_UNICODE_TRANSLATION), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2587,7 +2588,7 @@ bool sqlsrv_param::send_data_packet(_Inout_ sqlsrv_stmt* stmt)
|
||||||
wsize = MultiByteToWideChar(encoding, MB_ERR_INVALID_CHARS, buffer, static_cast<int>(read + new_read), wbuffer, static_cast<int>(sizeof(wbuffer) / sizeof(wchar_t)));
|
wsize = MultiByteToWideChar(encoding, MB_ERR_INVALID_CHARS, buffer, static_cast<int>(read + new_read), wbuffer, static_cast<int>(sizeof(wbuffer) / sizeof(wchar_t)));
|
||||||
#endif //!_WIN32
|
#endif //!_WIN32
|
||||||
// something else must be wrong if it failed
|
// something else must be wrong if it failed
|
||||||
CHECK_CUSTOM_ERROR(wsize == 0, stmt, SQLSRV_ERROR_INPUT_STREAM_ENCODING_TRANSLATE, get_last_error_message(ERROR_NO_UNICODE_TRANSLATION)) {
|
CHECK_CUSTOM_ERROR(wsize == 0, stmt, SQLSRV_ERROR_INPUT_STREAM_ENCODING_TRANSLATE, get_last_error_message(ERROR_NO_UNICODE_TRANSLATION), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2605,7 +2606,7 @@ bool sqlsrv_param_inout::prepare_param(_In_ zval* param_ref, _Inout_ zval* param
|
||||||
{
|
{
|
||||||
// Save the output param reference now
|
// Save the output param reference now
|
||||||
param_ptr_z = param_ref;
|
param_ptr_z = param_ref;
|
||||||
|
|
||||||
int type = Z_TYPE_P(param_z);
|
int type = Z_TYPE_P(param_z);
|
||||||
was_null = (type == IS_NULL);
|
was_null = (type == IS_NULL);
|
||||||
was_bool = (type == IS_TRUE || type == IS_FALSE);
|
was_bool = (type == IS_TRUE || type == IS_FALSE);
|
||||||
|
@ -2676,7 +2677,7 @@ bool sqlsrv_param_inout::prepare_param(_In_ zval* param_ref, _Inout_ zval* param
|
||||||
// If SQL type or column size is unknown, derives the appropriate values as well using the provided param zval and encoding
|
// If SQL type or column size is unknown, derives the appropriate values as well using the provided param zval and encoding
|
||||||
void sqlsrv_param_inout::process_param(_Inout_ sqlsrv_stmt* stmt, zval* param_z)
|
void sqlsrv_param_inout::process_param(_Inout_ sqlsrv_stmt* stmt, zval* param_z)
|
||||||
{
|
{
|
||||||
// Get param php type NOW because the original parameter might have been converted beforehand
|
// Get param php type NOW because the original parameter might have been converted beforehand
|
||||||
param_php_type = Z_TYPE_P(param_z);
|
param_php_type = Z_TYPE_P(param_z);
|
||||||
|
|
||||||
switch (param_php_type) {
|
switch (param_php_type) {
|
||||||
|
@ -2690,7 +2691,7 @@ void sqlsrv_param_inout::process_param(_Inout_ sqlsrv_stmt* stmt, zval* param_z)
|
||||||
process_string_param(stmt, param_z);
|
process_string_param(stmt, param_z);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
THROW_CORE_ERROR(stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_pos + 1);
|
THROW_CORE_ERROR(stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, param_pos + 1, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2728,7 +2729,7 @@ void sqlsrv_param_inout::process_string_param(_Inout_ sqlsrv_stmt* stmt, _Inout_
|
||||||
unsigned int wchar_size = 0;
|
unsigned int wchar_size = 0;
|
||||||
|
|
||||||
wide_buffer = utf16_string_from_mbcs_string(SQLSRV_ENCODING_UTF8, reinterpret_cast<const char*>(buffer), static_cast<int>(buffer_length), &wchar_size);
|
wide_buffer = utf16_string_from_mbcs_string(SQLSRV_ENCODING_UTF8, reinterpret_cast<const char*>(buffer), static_cast<int>(buffer_length), &wchar_size);
|
||||||
CHECK_CUSTOM_ERROR(wide_buffer == 0, stmt, SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE, param_pos + 1, get_last_error_message()) {
|
CHECK_CUSTOM_ERROR(wide_buffer == 0, stmt, SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE, param_pos + 1, get_last_error_message(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
wide_buffer[wchar_size] = L'\0';
|
wide_buffer[wchar_size] = L'\0';
|
||||||
|
@ -2736,7 +2737,7 @@ void sqlsrv_param_inout::process_string_param(_Inout_ sqlsrv_stmt* stmt, _Inout_
|
||||||
buffer = Z_STRVAL_P(param_z);
|
buffer = Z_STRVAL_P(param_z);
|
||||||
buffer_length = Z_STRLEN_P(param_z);
|
buffer_length = Z_STRLEN_P(param_z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
strlen_or_indptr = buffer_length;
|
strlen_or_indptr = buffer_length;
|
||||||
|
|
||||||
|
@ -2804,7 +2805,7 @@ void sqlsrv_param_inout::finalize_output_value()
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Even if the output param is a boolean, still convert to a long
|
// Even if the output param is a boolean, still convert to a long
|
||||||
// integer first to take care of rounding
|
// integer first to take care of rounding
|
||||||
convert_to_long(value_z);
|
convert_to_long(value_z);
|
||||||
if (was_bool) {
|
if (was_bool) {
|
||||||
|
@ -2857,7 +2858,7 @@ void sqlsrv_param_inout::finalize_output_string()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(str_len > (buffer_length - null_size), stmt, SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(str_len > (buffer_length - null_size), stmt, SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2884,7 +2885,7 @@ void sqlsrv_param_inout::finalize_output_string()
|
||||||
SQLLEN outLen = 0;
|
SQLLEN outLen = 0;
|
||||||
|
|
||||||
bool result = convert_string_from_utf16(encoding, reinterpret_cast<const SQLWCHAR*>(str), int(str_len / sizeof(SQLWCHAR)), &outString, outLen);
|
bool result = convert_string_from_utf16(encoding, reinterpret_cast<const SQLWCHAR*>(str), int(str_len / sizeof(SQLWCHAR)), &outString, outLen);
|
||||||
CHECK_CUSTOM_ERROR(!result, stmt, SQLSRV_ERROR_OUTPUT_PARAM_ENCODING_TRANSLATE, get_last_error_message()) {
|
CHECK_CUSTOM_ERROR(!result, stmt, SQLSRV_ERROR_OUTPUT_PARAM_ENCODING_TRANSLATE, get_last_error_message(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2909,20 +2910,20 @@ void sqlsrv_param_inout::finalize_output_string()
|
||||||
|
|
||||||
void sqlsrv_param_inout::resize_output_string_buffer(_Inout_ zval* param_z, _In_ bool is_numeric_type)
|
void sqlsrv_param_inout::resize_output_string_buffer(_Inout_ zval* param_z, _In_ bool is_numeric_type)
|
||||||
{
|
{
|
||||||
// Prerequisites: buffer, buffer_length, column_size, and strlen_or_indptr have been set to a known value
|
// Prerequisites: buffer, buffer_length, column_size, and strlen_or_indptr have been set to a known value
|
||||||
// Purpose:
|
// Purpose:
|
||||||
// Verify there is enough space to hold the output string parameter, and allocate if necessary. The param_z
|
// Verify there is enough space to hold the output string parameter, and allocate if necessary. The param_z
|
||||||
// is updated to contain the new buffer with the correct size and its reference is incremented, and all required
|
// is updated to contain the new buffer with the correct size and its reference is incremented, and all required
|
||||||
// values for SQLBindParameter will also be updated.
|
// values for SQLBindParameter will also be updated.
|
||||||
SQLLEN original_len = buffer_length;
|
SQLLEN original_len = buffer_length;
|
||||||
SQLLEN expected_len;
|
SQLLEN expected_len;
|
||||||
SQLLEN buffer_null_extra;
|
SQLLEN buffer_null_extra;
|
||||||
SQLLEN elem_size;
|
SQLLEN elem_size;
|
||||||
|
|
||||||
// Calculate the size of each 'element' represented by column_size. WCHAR is the size of a wide char (2), and so is
|
// Calculate the size of each 'element' represented by column_size. WCHAR is the size of a wide char (2), and so is
|
||||||
// a N(VAR)CHAR/NTEXT field being returned as a binary field.
|
// a N(VAR)CHAR/NTEXT field being returned as a binary field.
|
||||||
elem_size = (c_data_type == SQL_C_WCHAR ||
|
elem_size = (c_data_type == SQL_C_WCHAR ||
|
||||||
(c_data_type == SQL_C_BINARY &&
|
(c_data_type == SQL_C_BINARY &&
|
||||||
(sql_data_type == SQL_WCHAR || sql_data_type == SQL_WVARCHAR || sql_data_type == SQL_WLONGVARCHAR))) ? sizeof(SQLWCHAR) : sizeof(SQLCHAR);
|
(sql_data_type == SQL_WCHAR || sql_data_type == SQL_WVARCHAR || sql_data_type == SQL_WLONGVARCHAR))) ? sizeof(SQLWCHAR) : sizeof(SQLCHAR);
|
||||||
|
|
||||||
// account for the NULL terminator returned by ODBC and needed by Zend to avoid a "String not null terminated" debug warning
|
// account for the NULL terminator returned by ODBC and needed by Zend to avoid a "String not null terminated" debug warning
|
||||||
|
@ -3028,7 +3029,7 @@ void sqlsrv_param_tvp::get_tvp_metadata(_In_ sqlsrv_stmt* stmt, _In_ zend_string
|
||||||
core::SQLAllocHandle(SQL_HANDLE_STMT, *(stmt->conn), &chstmt);
|
core::SQLAllocHandle(SQL_HANDLE_STMT, *(stmt->conn), &chstmt);
|
||||||
|
|
||||||
rc = SQLSetStmtAttr(chstmt, SQL_SOPT_SS_NAME_SCOPE, (SQLPOINTER)SQL_SS_NAME_SCOPE_TABLE_TYPE, SQL_IS_UINTEGER);
|
rc = SQLSetStmtAttr(chstmt, SQL_SOPT_SS_NAME_SCOPE, (SQLPOINTER)SQL_SS_NAME_SCOPE_TABLE_TYPE, SQL_IS_UINTEGER);
|
||||||
CHECK_CUSTOM_ERROR(!SQL_SUCCEEDED(rc), stmt, SQLSRV_ERROR_TVP_FETCH_METADATA, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(!SQL_SUCCEEDED(rc), stmt, SQLSRV_ERROR_TVP_FETCH_METADATA, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3040,7 +3041,7 @@ void sqlsrv_param_tvp::get_tvp_metadata(_In_ sqlsrv_stmt* stmt, _In_ zend_string
|
||||||
rc = SQLColumns(chstmt, NULL, 0, NULL, SQL_NTS, reinterpret_cast<SQLCHAR*>(table_type), SQL_NTS, NULL, 0);
|
rc = SQLColumns(chstmt, NULL, 0, NULL, SQL_NTS, reinterpret_cast<SQLCHAR*>(table_type), SQL_NTS, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(!SQL_SUCCEEDED(rc), stmt, SQLSRV_ERROR_TVP_FETCH_METADATA, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(!SQL_SUCCEEDED(rc), stmt, SQLSRV_ERROR_TVP_FETCH_METADATA, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3055,7 +3056,7 @@ void sqlsrv_param_tvp::get_tvp_metadata(_In_ sqlsrv_stmt* stmt, _In_ zend_string
|
||||||
while (SQL_SUCCESS == rc) {
|
while (SQL_SUCCESS == rc) {
|
||||||
rc = SQLFetch(chstmt);
|
rc = SQLFetch(chstmt);
|
||||||
if (rc == SQL_NO_DATA) {
|
if (rc == SQL_NO_DATA) {
|
||||||
CHECK_CUSTOM_ERROR(tvp_columns.size() == 0, stmt, SQLSRV_ERROR_TVP_FETCH_METADATA, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(tvp_columns.size() == 0, stmt, SQLSRV_ERROR_TVP_FETCH_METADATA, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -3076,7 +3077,7 @@ void sqlsrv_param_tvp::get_tvp_metadata(_In_ sqlsrv_stmt* stmt, _In_ zend_string
|
||||||
pos++;
|
pos++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
THROW_CORE_ERROR(stmt, SQLSRV_ERROR_TVP_FETCH_METADATA, param_pos + 1);
|
THROW_CORE_ERROR(stmt, SQLSRV_ERROR_TVP_FETCH_METADATA, param_pos + 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLCloseCursor(chstmt);
|
SQLCloseCursor(chstmt);
|
||||||
|
@ -3114,7 +3115,7 @@ void sqlsrv_param_tvp::process_param(_Inout_ sqlsrv_stmt* stmt, _Inout_ zval* pa
|
||||||
this->num_rows = 0;
|
this->num_rows = 0;
|
||||||
int num_columns = parse_tv_param_arrays(stmt, param_z);
|
int num_columns = parse_tv_param_arrays(stmt, param_z);
|
||||||
column_size = num_rows;
|
column_size = num_rows;
|
||||||
|
|
||||||
strlen_or_indptr = (num_columns == 0)? SQL_DEFAULT_PARAM : SQL_DATA_AT_EXEC;
|
strlen_or_indptr = (num_columns == 0)? SQL_DEFAULT_PARAM : SQL_DATA_AT_EXEC;
|
||||||
} else {
|
} else {
|
||||||
// This is one of the constituent columns of the table-valued parameter
|
// This is one of the constituent columns of the table-valued parameter
|
||||||
|
@ -3137,7 +3138,7 @@ int sqlsrv_param_tvp::parse_tv_param_arrays(_Inout_ sqlsrv_stmt* stmt, _Inout_ z
|
||||||
zend_string *schema_name = NULL;
|
zend_string *schema_name = NULL;
|
||||||
zval *tvp_data_z = NULL;
|
zval *tvp_data_z = NULL;
|
||||||
HashPosition pos;
|
HashPosition pos;
|
||||||
|
|
||||||
zend_hash_internal_pointer_reset_ex(inputs_ht, &pos);
|
zend_hash_internal_pointer_reset_ex(inputs_ht, &pos);
|
||||||
if (zend_hash_has_more_elements_ex(inputs_ht, &pos) == SUCCESS) {
|
if (zend_hash_has_more_elements_ex(inputs_ht, &pos) == SUCCESS) {
|
||||||
|
|
||||||
|
@ -3148,22 +3149,22 @@ int sqlsrv_param_tvp::parse_tv_param_arrays(_Inout_ sqlsrv_stmt* stmt, _Inout_ z
|
||||||
if (key_type == HASH_KEY_IS_STRING) {
|
if (key_type == HASH_KEY_IS_STRING) {
|
||||||
key_len = ZSTR_LEN(tvp_name);
|
key_len = ZSTR_LEN(tvp_name);
|
||||||
tvp_data_z = zend_hash_get_current_data_ex(inputs_ht, &pos);
|
tvp_data_z = zend_hash_get_current_data_ex(inputs_ht, &pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR((key_type == HASH_KEY_IS_LONG || key_len == 0), stmt, SQLSRV_ERROR_TVP_INVALID_TABLE_TYPE_NAME, param_pos + 1) {
|
CHECK_CUSTOM_ERROR((key_type == HASH_KEY_IS_LONG || key_len == 0), stmt, SQLSRV_ERROR_TVP_INVALID_TABLE_TYPE_NAME, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Find the docs page somewhere that says a TVP can not be null but it may have null columns??
|
// TODO: Find the docs page somewhere that says a TVP can not be null but it may have null columns??
|
||||||
CHECK_CUSTOM_ERROR(tvp_data_z == NULL || Z_TYPE_P(tvp_data_z) == IS_NULL || Z_TYPE_P(tvp_data_z) != IS_ARRAY, stmt, SQLSRV_ERROR_TVP_INVALID_INPUTS, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(tvp_data_z == NULL || Z_TYPE_P(tvp_data_z) == IS_NULL || Z_TYPE_P(tvp_data_z) != IS_ARRAY, stmt, SQLSRV_ERROR_TVP_INVALID_INPUTS, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the TVP type name for SQLSetDescField later
|
// Save the TVP type name for SQLSetDescField later
|
||||||
buffer = ZSTR_VAL(tvp_name);
|
buffer = ZSTR_VAL(tvp_name);
|
||||||
buffer_length = SQL_NTS;
|
buffer_length = SQL_NTS;
|
||||||
|
|
||||||
// Check if schema is provided by the user
|
// Check if schema is provided by the user
|
||||||
if (zend_hash_move_forward_ex(inputs_ht, &pos) == SUCCESS) {
|
if (zend_hash_move_forward_ex(inputs_ht, &pos) == SUCCESS) {
|
||||||
zval *schema_z = zend_hash_get_current_data_ex(inputs_ht, &pos);
|
zval *schema_z = zend_hash_get_current_data_ex(inputs_ht, &pos);
|
||||||
|
@ -3174,7 +3175,7 @@ int sqlsrv_param_tvp::parse_tv_param_arrays(_Inout_ sqlsrv_stmt* stmt, _Inout_ z
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the TVP multi-dim array data, which should be something like this
|
// Save the TVP multi-dim array data, which should be something like this
|
||||||
// [
|
// [
|
||||||
// [r1c1, r1c2, r1c3],
|
// [r1c1, r1c2, r1c3],
|
||||||
// [r2c1, r2c2, r2c3],
|
// [r2c1, r2c2, r2c3],
|
||||||
// [r3c1, r3c2, r3c3]
|
// [r3c1, r3c2, r3c3]
|
||||||
|
@ -3203,7 +3204,7 @@ int sqlsrv_param_tvp::parse_tv_param_arrays(_Inout_ sqlsrv_stmt* stmt, _Inout_ z
|
||||||
// Loop through the rows to check the number of columns
|
// Loop through the rows to check the number of columns
|
||||||
ZEND_HASH_FOREACH_KEY_VAL(rows_ht, id, key, row_z) {
|
ZEND_HASH_FOREACH_KEY_VAL(rows_ht, id, key, row_z) {
|
||||||
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
|
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
|
||||||
CHECK_CUSTOM_ERROR(type == HASH_KEY_IS_STRING, stmt, SQLSRV_ERROR_TVP_STRING_KEYS, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(type == HASH_KEY_IS_STRING, stmt, SQLSRV_ERROR_TVP_STRING_KEYS, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3212,13 +3213,13 @@ int sqlsrv_param_tvp::parse_tv_param_arrays(_Inout_ sqlsrv_stmt* stmt, _Inout_ z
|
||||||
}
|
}
|
||||||
|
|
||||||
// Individual row must be an array
|
// Individual row must be an array
|
||||||
CHECK_CUSTOM_ERROR(Z_TYPE_P(row_z) != IS_ARRAY, stmt, SQLSRV_ERROR_TVP_ROW_NOT_ARRAY, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(Z_TYPE_P(row_z) != IS_ARRAY, stmt, SQLSRV_ERROR_TVP_ROW_NOT_ARRAY, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Are all the TVP's rows the same size
|
// Are all the TVP's rows the same size
|
||||||
num_columns = zend_hash_num_elements(Z_ARRVAL_P(row_z));
|
num_columns = zend_hash_num_elements(Z_ARRVAL_P(row_z));
|
||||||
CHECK_CUSTOM_ERROR(num_columns != total_num_columns, stmt, SQLSRV_ERROR_TVP_ROWS_UNEXPECTED_SIZE, param_pos + 1, total_num_columns) {
|
CHECK_CUSTOM_ERROR(num_columns != total_num_columns, stmt, SQLSRV_ERROR_TVP_ROWS_UNEXPECTED_SIZE, param_pos + 1, total_num_columns, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
@ -3230,7 +3231,7 @@ int sqlsrv_param_tvp::parse_tv_param_arrays(_Inout_ sqlsrv_stmt* stmt, _Inout_ z
|
||||||
void sqlsrv_param_tvp::process_param_column_value(_Inout_ sqlsrv_stmt* stmt)
|
void sqlsrv_param_tvp::process_param_column_value(_Inout_ sqlsrv_stmt* stmt)
|
||||||
{
|
{
|
||||||
// This is one of the constituent columns of the table-valued parameter
|
// This is one of the constituent columns of the table-valued parameter
|
||||||
// The corresponding column value of the TVP's first row is already saved in
|
// The corresponding column value of the TVP's first row is already saved in
|
||||||
// the member variable param_ptr_z, which may be a NULL value
|
// the member variable param_ptr_z, which may be a NULL value
|
||||||
zval *data_z = param_ptr_z;
|
zval *data_z = param_ptr_z;
|
||||||
param_php_type = is_a_string_type(sql_data_type) ? IS_STRING : Z_TYPE_P(data_z);
|
param_php_type = is_a_string_type(sql_data_type) ? IS_STRING : Z_TYPE_P(data_z);
|
||||||
|
@ -3253,7 +3254,7 @@ void sqlsrv_param_tvp::process_param_column_value(_Inout_ sqlsrv_stmt* stmt)
|
||||||
} else {
|
} else {
|
||||||
// If preprocessing a datetime object fails, throw an error of invalid php type
|
// If preprocessing a datetime object fails, throw an error of invalid php type
|
||||||
bool succeeded = preprocess_datetime_object(stmt, data_z);
|
bool succeeded = preprocess_datetime_object(stmt, data_z);
|
||||||
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_TVP_INVALID_COLUMN_PHPTYPE, parent_tvp->param_pos + 1, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_TVP_INVALID_COLUMN_PHPTYPE, parent_tvp->param_pos + 1, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3265,7 +3266,7 @@ void sqlsrv_param_tvp::process_param_column_value(_Inout_ sqlsrv_stmt* stmt)
|
||||||
process_null_param_value(stmt);
|
process_null_param_value(stmt);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
THROW_CORE_ERROR(stmt, SQLSRV_ERROR_TVP_INVALID_COLUMN_PHPTYPE, parent_tvp->param_pos + 1, param_pos + 1);
|
THROW_CORE_ERROR(stmt, SQLSRV_ERROR_TVP_INVALID_COLUMN_PHPTYPE, parent_tvp->param_pos + 1, param_pos + 1, NULL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3324,22 +3325,22 @@ void sqlsrv_param_tvp::bind_param(_Inout_ sqlsrv_stmt* stmt)
|
||||||
core::SQLGetStmtAttr(stmt, SQL_ATTR_IMP_PARAM_DESC, &hIpd, 0, 0);
|
core::SQLGetStmtAttr(stmt, SQL_ATTR_IMP_PARAM_DESC, &hIpd, 0, 0);
|
||||||
|
|
||||||
if (buffer != NULL) {
|
if (buffer != NULL) {
|
||||||
// SQL_CA_SS_TYPE_NAME is optional for stored procedure calls, but it must be
|
// SQL_CA_SS_TYPE_NAME is optional for stored procedure calls, but it must be
|
||||||
// specified for SQL statements that are not procedure calls to enable the
|
// specified for SQL statements that are not procedure calls to enable the
|
||||||
// server to determine the type of the table-valued parameter.
|
// server to determine the type of the table-valued parameter.
|
||||||
char *tvp_name = reinterpret_cast<char *>(buffer);
|
char *tvp_name = reinterpret_cast<char *>(buffer);
|
||||||
SQLRETURN r = ::SQLSetDescField(hIpd, param_pos + 1, SQL_CA_SS_TYPE_NAME, reinterpret_cast<SQLCHAR*>(tvp_name), SQL_NTS);
|
SQLRETURN r = ::SQLSetDescField(hIpd, param_pos + 1, SQL_CA_SS_TYPE_NAME, reinterpret_cast<SQLCHAR*>(tvp_name), SQL_NTS);
|
||||||
CHECK_SQL_ERROR_OR_WARNING(r, stmt) {
|
CHECK_SQL_ERROR_OR_WARNING(r, stmt, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Z_TYPE(placeholder_z) == IS_STRING) {
|
if (Z_TYPE(placeholder_z) == IS_STRING) {
|
||||||
// If the table type for the table-valued parameter is defined in a different
|
// If the table type for the table-valued parameter is defined in a different
|
||||||
// schema than the default, SQL_CA_SS_SCHEMA_NAME must be specified. If not,
|
// schema than the default, SQL_CA_SS_SCHEMA_NAME must be specified. If not,
|
||||||
// the server will not be able to determine the type of the table-valued parameter.
|
// the server will not be able to determine the type of the table-valued parameter.
|
||||||
char * schema_name = Z_STRVAL(placeholder_z);
|
char * schema_name = Z_STRVAL(placeholder_z);
|
||||||
SQLRETURN r = ::SQLSetDescField(hIpd, param_pos + 1, SQL_CA_SS_SCHEMA_NAME, reinterpret_cast<SQLCHAR*>(schema_name), SQL_NTS);
|
SQLRETURN r = ::SQLSetDescField(hIpd, param_pos + 1, SQL_CA_SS_SCHEMA_NAME, reinterpret_cast<SQLCHAR*>(schema_name), SQL_NTS);
|
||||||
CHECK_SQL_ERROR_OR_WARNING(r, stmt) {
|
CHECK_SQL_ERROR_OR_WARNING(r, stmt, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
// Free and reset the placeholder_z
|
// Free and reset the placeholder_z
|
||||||
|
@ -3352,7 +3353,7 @@ void sqlsrv_param_tvp::bind_param(_Inout_ sqlsrv_stmt* stmt)
|
||||||
SQLHDESC desc;
|
SQLHDESC desc;
|
||||||
core::SQLGetStmtAttr(stmt, SQL_ATTR_APP_PARAM_DESC, &desc, 0, 0);
|
core::SQLGetStmtAttr(stmt, SQL_ATTR_APP_PARAM_DESC, &desc, 0, 0);
|
||||||
SQLRETURN r = ::SQLSetDescField(desc, param_pos + 1, SQL_DESC_DATA_PTR, reinterpret_cast<SQLPOINTER>(this), 0);
|
SQLRETURN r = ::SQLSetDescField(desc, param_pos + 1, SQL_DESC_DATA_PTR, reinterpret_cast<SQLPOINTER>(this), 0);
|
||||||
CHECK_SQL_ERROR_OR_WARNING(r, stmt) {
|
CHECK_SQL_ERROR_OR_WARNING(r, stmt, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3374,11 +3375,11 @@ void sqlsrv_param_tvp::bind_param(_Inout_ sqlsrv_stmt* stmt)
|
||||||
zval* data_z = NULL;
|
zval* data_z = NULL;
|
||||||
int num_columns = 0;
|
int num_columns = 0;
|
||||||
|
|
||||||
// In case there are null values in the first row, have to loop
|
// In case there are null values in the first row, have to loop
|
||||||
// through the entire first row of column values using the Zend macros.
|
// through the entire first row of column values using the Zend macros.
|
||||||
ZEND_HASH_FOREACH_KEY_VAL(cols_ht, id, key, data_z) {
|
ZEND_HASH_FOREACH_KEY_VAL(cols_ht, id, key, data_z) {
|
||||||
int type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
|
int type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
|
||||||
CHECK_CUSTOM_ERROR(type == HASH_KEY_IS_STRING, stmt, SQLSRV_ERROR_TVP_STRING_KEYS, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(type == HASH_KEY_IS_STRING, stmt, SQLSRV_ERROR_TVP_STRING_KEYS, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3387,8 +3388,8 @@ void sqlsrv_param_tvp::bind_param(_Inout_ sqlsrv_stmt* stmt)
|
||||||
sqlsrv_param* column_param = tvp_columns[pos];
|
sqlsrv_param* column_param = tvp_columns[pos];
|
||||||
SQLSRV_ASSERT(column_param != NULL, "sqlsrv_param_tvp::bind_param -- column param should not be null");
|
SQLSRV_ASSERT(column_param != NULL, "sqlsrv_param_tvp::bind_param -- column param should not be null");
|
||||||
|
|
||||||
// If data_z is NULL, will need to keep looking in the subsequent rows of
|
// If data_z is NULL, will need to keep looking in the subsequent rows of
|
||||||
// the same column until a non-null value is found. Since Zend macros must be
|
// the same column until a non-null value is found. Since Zend macros must be
|
||||||
// used to traverse the array items, nesting Zend macros in different directions
|
// used to traverse the array items, nesting Zend macros in different directions
|
||||||
// does not work.
|
// does not work.
|
||||||
// Therefore, save data_z for later processing and binding.
|
// Therefore, save data_z for later processing and binding.
|
||||||
|
@ -3467,10 +3468,10 @@ void sqlsrv_param_tvp::populate_cell_placeholder(_Inout_ sqlsrv_stmt* stmt, _In_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is the table-valued parameter, loop through each parameter column
|
// If this is the table-valued parameter, loop through each parameter column
|
||||||
// and populate the cell's placeholder_z.
|
// and populate the cell's placeholder_z.
|
||||||
// If this is one of the constituent columns of the table-valued parameter,
|
// If this is one of the constituent columns of the table-valued parameter,
|
||||||
// call SQLPutData() to send the cell value to the server (based on current_row
|
// call SQLPutData() to send the cell value to the server (based on current_row
|
||||||
// and param_pos)
|
// and param_pos)
|
||||||
bool sqlsrv_param_tvp::send_data_packet(_Inout_ sqlsrv_stmt* stmt)
|
bool sqlsrv_param_tvp::send_data_packet(_Inout_ sqlsrv_stmt* stmt)
|
||||||
{
|
{
|
||||||
|
@ -3514,7 +3515,7 @@ bool sqlsrv_param_tvp::send_data_packet(_Inout_ sqlsrv_stmt* stmt)
|
||||||
bool succeeded = convert_datetime_to_string(stmt, value_z);
|
bool succeeded = convert_datetime_to_string(stmt, value_z);
|
||||||
|
|
||||||
// Conversion failed so assume the input was an invalid PHP type
|
// Conversion failed so assume the input was an invalid PHP type
|
||||||
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_TVP_INVALID_COLUMN_PHPTYPE, parent_tvp->param_pos + 1, param_pos + 1) {
|
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_TVP_INVALID_COLUMN_PHPTYPE, parent_tvp->param_pos + 1, param_pos + 1, NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3540,7 +3541,7 @@ bool sqlsrv_param_tvp::send_data_packet(_Inout_ sqlsrv_stmt* stmt)
|
||||||
}
|
}
|
||||||
// This method would change the member placeholder_z
|
// This method would change the member placeholder_z
|
||||||
bool succeeded = convert_input_str_to_utf16(stmt, value_z);
|
bool succeeded = convert_input_str_to_utf16(stmt, value_z);
|
||||||
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_TVP_STRING_ENCODING_TRANSLATE, parent_tvp->param_pos + 1, param_pos + 1, get_last_error_message()) {
|
CHECK_CUSTOM_ERROR(!succeeded, stmt, SQLSRV_ERROR_TVP_STRING_ENCODING_TRANSLATE, parent_tvp->param_pos + 1, param_pos + 1, get_last_error_message(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3642,7 +3643,7 @@ bool sqlsrv_params_container::get_next_parameter(_Inout_ sqlsrv_stmt* stmt)
|
||||||
|
|
||||||
// If no more data, all the bound parameters have been exhausted, so return false (done)
|
// If no more data, all the bound parameters have been exhausted, so return false (done)
|
||||||
if (SQL_SUCCEEDED(r) || r == SQL_NO_DATA) {
|
if (SQL_SUCCEEDED(r) || r == SQL_NO_DATA) {
|
||||||
// Done now, reset current_param
|
// Done now, reset current_param
|
||||||
current_param = NULL;
|
current_param = NULL;
|
||||||
return false;
|
return false;
|
||||||
} else if (r == SQL_NEED_DATA) {
|
} else if (r == SQL_NEED_DATA) {
|
||||||
|
@ -3651,7 +3652,7 @@ bool sqlsrv_params_container::get_next_parameter(_Inout_ sqlsrv_stmt* stmt)
|
||||||
SQLSRV_ASSERT(current_param != NULL, "sqlsrv_params_container::get_next_parameter - The parameter requested is missing!");
|
SQLSRV_ASSERT(current_param != NULL, "sqlsrv_params_container::get_next_parameter - The parameter requested is missing!");
|
||||||
current_param->init_data_from_zval(stmt);
|
current_param->init_data_from_zval(stmt);
|
||||||
} else {
|
} else {
|
||||||
// Do not reset current_param when param is NULL, because
|
// Do not reset current_param when param is NULL, because
|
||||||
// it means that data is expected from the existing current_param
|
// it means that data is expected from the existing current_param
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3674,7 +3675,7 @@ bool sqlsrv_params_container::send_next_packet(_Inout_ sqlsrv_stmt* stmt)
|
||||||
|
|
||||||
// The helper method send_stream_packet() returns false when EOF is reached
|
// The helper method send_stream_packet() returns false when EOF is reached
|
||||||
if (current_param && current_param->send_data_packet(stmt) == false) {
|
if (current_param && current_param->send_data_packet(stmt) == false) {
|
||||||
// Now that EOF has been reached, reset current_param for next round
|
// Now that EOF has been reached, reset current_param for next round
|
||||||
// Bear in mind that SQLParamData might request the same stream resource again
|
// Bear in mind that SQLParamData might request the same stream resource again
|
||||||
current_param = NULL;
|
current_param = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,17 @@
|
||||||
//
|
//
|
||||||
// Contents: Implementation of PHP streams for reading SQL Server data
|
// Contents: Implementation of PHP streams for reading SQL Server data
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
|
// 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,
|
// 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 :
|
// 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 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,
|
// 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
|
// 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
|
// 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.
|
// IN THE SOFTWARE.
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ int sqlsrv_stream_close( _Inout_ php_stream* stream, int /*close_handle*/ )
|
||||||
{
|
{
|
||||||
sqlsrv_stream* ss = static_cast<sqlsrv_stream*>( stream->abstract );
|
sqlsrv_stream* ss = static_cast<sqlsrv_stream*>( stream->abstract );
|
||||||
SQLSRV_ASSERT( ss != NULL && ss->stmt != NULL, "sqlsrv_stream_close: sqlsrv_stream* ss was null." );
|
SQLSRV_ASSERT( ss != NULL && ss->stmt != NULL, "sqlsrv_stream_close: sqlsrv_stream* ss was null." );
|
||||||
|
|
||||||
// free the stream resources in the Zend engine
|
// free the stream resources in the Zend engine
|
||||||
php_stream_free( stream, PHP_STREAM_FREE_RELEASE_STREAM );
|
php_stream_free( stream, PHP_STREAM_FREE_RELEASE_STREAM );
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ int sqlsrv_stream_close( _Inout_ php_stream* stream, int /*close_handle*/ )
|
||||||
// read from a sqlsrv stream into the buffer provided by Zend. The parameters for binary vs. char are
|
// read from a sqlsrv stream into the buffer provided by Zend. The parameters for binary vs. char are
|
||||||
// set when sqlsrv_get_field is called by the user specifying which field type they want.
|
// set when sqlsrv_get_field is called by the user specifying which field type they want.
|
||||||
|
|
||||||
#if PHP_VERSION_ID >= 70400
|
#if PHP_VERSION_ID >= 70400
|
||||||
ssize_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count) char* buf, _Inout_ size_t count)
|
ssize_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count) char* buf, _Inout_ size_t count)
|
||||||
#else
|
#else
|
||||||
size_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count) char* buf, _Inout_ size_t count)
|
size_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count) char* buf, _Inout_ size_t count)
|
||||||
|
@ -97,7 +97,7 @@ size_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count)
|
||||||
SQLRETURN r = ss->stmt->current_results->get_data(ss->field_index + 1, c_type, get_data_buffer, count /*BufferLength*/, &read, false /*handle_warning*/);
|
SQLRETURN r = ss->stmt->current_results->get_data(ss->field_index + 1, c_type, get_data_buffer, count /*BufferLength*/, &read, false /*handle_warning*/);
|
||||||
|
|
||||||
CHECK_SQL_ERROR( r, ss->stmt ) {
|
CHECK_SQL_ERROR( r, ss->stmt ) {
|
||||||
stream->eof = 1;
|
stream->eof = 1;
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ size_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count)
|
||||||
"did not occur." );
|
"did not occur." );
|
||||||
}
|
}
|
||||||
|
|
||||||
// As per SQLGetData documentation, if the length of character data exceeds the BufferLength,
|
// As per SQLGetData documentation, if the length of character data exceeds the BufferLength,
|
||||||
// SQLGetData truncates the data to BufferLength less the length of null-termination character.
|
// SQLGetData truncates the data to BufferLength less the length of null-termination character.
|
||||||
// But when fetching binary fields as chars (wide chars), each byte is represented as 2 hex characters,
|
// But when fetching binary fields as chars (wide chars), each byte is represented as 2 hex characters,
|
||||||
// each takes the size of a char (wide char). Note that BufferLength may not be multiples of 2 or 4.
|
// each takes the size of a char (wide char). Note that BufferLength may not be multiples of 2 or 4.
|
||||||
|
@ -138,7 +138,7 @@ size_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count)
|
||||||
if( is_truncated_warning( state ) || count < read) {
|
if( is_truncated_warning( state ) || count < read) {
|
||||||
#else
|
#else
|
||||||
if( is_truncated_warning( state ) ) {
|
if( is_truncated_warning( state ) ) {
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
size_t char_size = sizeof(SQLCHAR);
|
size_t char_size = sizeof(SQLCHAR);
|
||||||
|
|
||||||
switch( c_type ) {
|
switch( c_type ) {
|
||||||
|
@ -168,13 +168,13 @@ size_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CHECK_SQL_WARNING( r, ss->stmt );
|
CHECK_SQL_WARNING( r, ss->stmt, NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the encoding is UTF-8
|
// If the encoding is UTF-8
|
||||||
if( c_type == SQL_C_WCHAR ) {
|
if( c_type == SQL_C_WCHAR ) {
|
||||||
count *= 2;
|
count *= 2;
|
||||||
// Undo the shift to use the full buffer
|
// Undo the shift to use the full buffer
|
||||||
// flags set to 0 by default, which means that any invalid characters are dropped rather than causing
|
// flags set to 0 by default, which means that any invalid characters are dropped rather than causing
|
||||||
// an error. This happens only on XP.
|
// an error. This happens only on XP.
|
||||||
|
@ -199,18 +199,18 @@ size_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count)
|
||||||
static_cast<int>(read >> 1), buf, static_cast<int>(count), NULL, NULL );
|
static_cast<int>(read >> 1), buf, static_cast<int>(count), NULL, NULL );
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
if( enc_len == 0 ) {
|
if( enc_len == 0 ) {
|
||||||
|
|
||||||
stream->eof = 1;
|
stream->eof = 1;
|
||||||
THROW_CORE_ERROR( ss->stmt, SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE, get_last_error_message() );
|
THROW_CORE_ERROR( ss->stmt, SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE, get_last_error_message(), NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
read = enc_len;
|
read = enc_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<size_t>( read );
|
return static_cast<size_t>( read );
|
||||||
}
|
}
|
||||||
catch (core::CoreException&) {
|
catch (core::CoreException&) {
|
||||||
#if PHP_VERSION_ID >= 70400
|
#if PHP_VERSION_ID >= 70400
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -218,7 +218,7 @@ size_t sqlsrv_stream_read(_Inout_ php_stream* stream, _Out_writes_bytes_(count)
|
||||||
}
|
}
|
||||||
catch (...) {
|
catch (...) {
|
||||||
LOG(SEV_ERROR, "sqlsrv_stream_read: Unknown exception caught.");
|
LOG(SEV_ERROR, "sqlsrv_stream_read: Unknown exception caught.");
|
||||||
#if PHP_VERSION_ID >= 70400
|
#if PHP_VERSION_ID >= 70400
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -242,7 +242,7 @@ php_stream_ops sqlsrv_stream_ops = {
|
||||||
// open a stream and return the sqlsrv_stream_ops function table as part of the
|
// open a stream and return the sqlsrv_stream_ops function table as part of the
|
||||||
// return value. There is only one valid way to open a stream, using sqlsrv_get_field on
|
// return value. There is only one valid way to open a stream, using sqlsrv_get_field on
|
||||||
// certain field types. A sqlsrv stream may only be opened in read mode.
|
// certain field types. A sqlsrv stream may only be opened in read mode.
|
||||||
static php_stream* sqlsrv_stream_opener( _In_opt_ php_stream_wrapper* wrapper, _In_ const char*, _In_ const char* mode,
|
static php_stream* sqlsrv_stream_opener( _In_opt_ php_stream_wrapper* wrapper, _In_ const char*, _In_ const char* mode,
|
||||||
_In_opt_ int options, _In_ zend_string **, php_stream_context* STREAMS_DC )
|
_In_opt_ int options, _In_ zend_string **, php_stream_context* STREAMS_DC )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -259,8 +259,8 @@ static php_stream* sqlsrv_stream_opener( _In_opt_ php_stream_wrapper* wrapper, _
|
||||||
ss = static_cast<sqlsrv_stream*>( sqlsrv_malloc( sizeof( sqlsrv_stream )));
|
ss = static_cast<sqlsrv_stream*>( sqlsrv_malloc( sizeof( sqlsrv_stream )));
|
||||||
memset( ss, 0, sizeof( sqlsrv_stream ));
|
memset( ss, 0, sizeof( sqlsrv_stream ));
|
||||||
|
|
||||||
// The function core_get_field_common() is changed to pass REPORT_ERRORS for
|
// The function core_get_field_common() is changed to pass REPORT_ERRORS for
|
||||||
// php_stream_open_wrapper(). Whether the error flag is toggled or cleared,
|
// php_stream_open_wrapper(). Whether the error flag is toggled or cleared,
|
||||||
// the argument "options" will be zero.
|
// the argument "options" will be zero.
|
||||||
// For details check this pull request: https://github.com/php/php-src/pull/6190
|
// For details check this pull request: https://github.com/php/php-src/pull/6190
|
||||||
if (options != 0) {
|
if (options != 0) {
|
||||||
|
|
|
@ -2,20 +2,20 @@
|
||||||
// File: core_util.cpp
|
// File: core_util.cpp
|
||||||
//
|
//
|
||||||
// Contents: Utility functions used by both connection or statement functions for both the PDO and sqlsrv drivers
|
// Contents: Utility functions used by both connection or statement functions for both the PDO and sqlsrv drivers
|
||||||
//
|
//
|
||||||
// Comments: Mostly error handling and some type handling
|
// Comments: Mostly error handling and some type handling
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
|
// 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,
|
// 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 :
|
// 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 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,
|
// 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
|
// 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
|
// 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.
|
// IN THE SOFTWARE.
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ char last_err_msg[2048] = {'\0'}; // 2k to hold the error messages
|
||||||
|
|
||||||
// routine used by utf16_string_from_mbcs_string
|
// routine used by utf16_string_from_mbcs_string
|
||||||
unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
|
unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encoding, _In_reads_bytes_(mbcs_len) char const* mbcs_in_string,
|
||||||
_In_ unsigned int mbcs_len,
|
_In_ unsigned int mbcs_len,
|
||||||
_Out_writes_(utf16_len) __transfer( mbcs_in_string ) SQLWCHAR* utf16_out_string,
|
_Out_writes_(utf16_len) __transfer( mbcs_in_string ) SQLWCHAR* utf16_out_string,
|
||||||
_In_ unsigned int utf16_len, bool use_strict_conversion = false );
|
_In_ unsigned int utf16_len, bool use_strict_conversion = false );
|
||||||
|
|
||||||
|
@ -62,13 +62,13 @@ void log_activity(_In_opt_ const char* msg, _In_opt_ va_list* print_args)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SQLSTATE for all internal errors
|
// SQLSTATE for all internal errors
|
||||||
SQLCHAR IMSSP[] = "IMSSP";
|
SQLCHAR IMSSP[] = "IMSSP";
|
||||||
|
|
||||||
// SQLSTATE for all internal warnings
|
// SQLSTATE for all internal warnings
|
||||||
SQLCHAR SSPWARN[] = "01SSP";
|
SQLCHAR SSPWARN[] = "01SSP";
|
||||||
|
|
||||||
// write to the php log if the severity and subsystem match the filters currently set in the INI or
|
// write to the php log if the severity and subsystem match the filters currently set in the INI or
|
||||||
// the script (sqlsrv_configure).
|
// the script (sqlsrv_configure).
|
||||||
void write_to_log( _In_ unsigned int severity, _In_ const char* msg, ...)
|
void write_to_log( _In_ unsigned int severity, _In_ const char* msg, ...)
|
||||||
{
|
{
|
||||||
|
@ -150,7 +150,7 @@ bool convert_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _In_reads_bytes_(
|
||||||
// Allocate enough space to hold the largest possible number of bytes for UTF-8 conversion
|
// Allocate enough space to hold the largest possible number of bytes for UTF-8 conversion
|
||||||
// instead of calling FromUtf16, for performance reasons
|
// instead of calling FromUtf16, for performance reasons
|
||||||
cchOutLen = 4 * cchInLen;
|
cchOutLen = 4 * cchInLen;
|
||||||
#else
|
#else
|
||||||
// flags set to 0 by default, which means that any invalid characters are dropped rather than causing
|
// flags set to 0 by default, which means that any invalid characters are dropped rather than causing
|
||||||
// an error. This happens only on XP.
|
// an error. This happens only on XP.
|
||||||
DWORD flags = 0;
|
DWORD flags = 0;
|
||||||
|
@ -162,10 +162,10 @@ bool convert_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _In_reads_bytes_(
|
||||||
// Calculate the number of output bytes required - no performance hit here because
|
// Calculate the number of output bytes required - no performance hit here because
|
||||||
// WideCharToMultiByte is highly optimised
|
// WideCharToMultiByte is highly optimised
|
||||||
cchOutLen = WideCharToMultiByte( encoding, flags,
|
cchOutLen = WideCharToMultiByte( encoding, flags,
|
||||||
inString, cchInLen,
|
inString, cchInLen,
|
||||||
NULL, 0, NULL, NULL );
|
NULL, 0, NULL, NULL );
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
|
|
||||||
if( cchOutLen == 0 ) {
|
if( cchOutLen == 0 ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +173,7 @@ bool convert_string_from_utf16( _In_ SQLSRV_ENCODING encoding, _In_reads_bytes_(
|
||||||
// Create a buffer to fit the encoded string
|
// Create a buffer to fit the encoded string
|
||||||
char* newString = reinterpret_cast<char*>( sqlsrv_malloc( cchOutLen + 1 /* NULL char*/ ));
|
char* newString = reinterpret_cast<char*>( sqlsrv_malloc( cchOutLen + 1 /* NULL char*/ ));
|
||||||
memset(newString, '\0', cchOutLen+1);
|
memset(newString, '\0', cchOutLen+1);
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
int rc = SystemLocale::FromUtf16Strict( encoding, inString, cchInLen, newString, static_cast<int>(cchOutLen));
|
int rc = SystemLocale::FromUtf16Strict( encoding, inString, cchInLen, newString, static_cast<int>(cchOutLen));
|
||||||
#else
|
#else
|
||||||
|
@ -216,7 +216,7 @@ SQLWCHAR* utf16_string_from_mbcs_string( _In_ SQLSRV_ENCODING php_encoding, _In_
|
||||||
return utf16_string;
|
return utf16_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts an input (assuming a datetime string) to a zval containing a PHP DateTime object.
|
// Converts an input (assuming a datetime string) to a zval containing a PHP DateTime object.
|
||||||
// If the input is null, this simply returns a NULL zval. If anything wrong occurs during conversion,
|
// If the input is null, this simply returns a NULL zval. If anything wrong occurs during conversion,
|
||||||
// an exception will be thrown.
|
// an exception will be thrown.
|
||||||
void convert_datetime_string_to_zval(_Inout_ sqlsrv_stmt* stmt, _In_opt_ char* input, _In_ SQLLEN length, _Inout_ zval& out_zval)
|
void convert_datetime_string_to_zval(_Inout_ sqlsrv_stmt* stmt, _In_opt_ char* input, _In_ SQLLEN length, _Inout_ zval& out_zval)
|
||||||
|
@ -308,10 +308,10 @@ bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_nu
|
||||||
SQLLEN sqlstate_len = 0;
|
SQLLEN sqlstate_len = 0;
|
||||||
|
|
||||||
convert_string_from_utf16(enc, wsqlstate, wsqlstate_len, (char**)&error->sqlstate, sqlstate_len);
|
convert_string_from_utf16(enc, wsqlstate, wsqlstate_len, (char**)&error->sqlstate, sqlstate_len);
|
||||||
|
|
||||||
SQLLEN message_len = 0;
|
SQLLEN message_len = 0;
|
||||||
if (r == SQL_SUCCESS_WITH_INFO && wmessage_len > SQL_MAX_ERROR_MESSAGE_LENGTH) {
|
if (r == SQL_SUCCESS_WITH_INFO && wmessage_len > SQL_MAX_ERROR_MESSAGE_LENGTH) {
|
||||||
// note that wmessage_len is the number of characters required for the error message --
|
// note that wmessage_len is the number of characters required for the error message --
|
||||||
// create a new buffer big enough for this lengthy error message
|
// create a new buffer big enough for this lengthy error message
|
||||||
sqlsrv_malloc_auto_ptr<SQLWCHAR> wnative_message_str;
|
sqlsrv_malloc_auto_ptr<SQLWCHAR> wnative_message_str;
|
||||||
|
|
||||||
|
@ -319,7 +319,7 @@ bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_nu
|
||||||
SQLSMALLINT returned_len = 0;
|
SQLSMALLINT returned_len = 0;
|
||||||
|
|
||||||
wnative_message_str = reinterpret_cast<SQLWCHAR*>(sqlsrv_malloc(expected_len));
|
wnative_message_str = reinterpret_cast<SQLWCHAR*>(sqlsrv_malloc(expected_len));
|
||||||
memset(wnative_message_str, '\0', expected_len);
|
memset(wnative_message_str, '\0', expected_len);
|
||||||
|
|
||||||
SQLRETURN rtemp = ::SQLGetDiagFieldW(h_type, h, record_number, SQL_DIAG_MESSAGE_TEXT, wnative_message_str, wmessage_len, &returned_len);
|
SQLRETURN rtemp = ::SQLGetDiagFieldW(h_type, h, record_number, SQL_DIAG_MESSAGE_TEXT, wnative_message_str, wmessage_len, &returned_len);
|
||||||
if (!SQL_SUCCEEDED(rtemp) || returned_len != expected_len) {
|
if (!SQL_SUCCEEDED(rtemp) || returned_len != expected_len) {
|
||||||
|
@ -341,7 +341,7 @@ bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_nu
|
||||||
|
|
||||||
// Only overrides 'severity' if 'check_warning' is true (false by default)
|
// Only overrides 'severity' if 'check_warning' is true (false by default)
|
||||||
if (check_warning) {
|
if (check_warning) {
|
||||||
// The character string value returned for an SQLSTATE consists of a two-character class value
|
// The character string value returned for an SQLSTATE consists of a two-character class value
|
||||||
// followed by a three-character subclass value. A class value of "01" indicates a warning.
|
// followed by a three-character subclass value. A class value of "01" indicates a warning.
|
||||||
// https://docs.microsoft.com/sql/odbc/reference/appendixes/appendix-a-odbc-error-codes?view=sql-server-ver15
|
// https://docs.microsoft.com/sql/odbc/reference/appendixes/appendix-a-odbc-error-codes?view=sql-server-ver15
|
||||||
if (error->sqlstate[0] == '0' && error->sqlstate[1] == '1') {
|
if (error->sqlstate[0] == '0' && error->sqlstate[1] == '1') {
|
||||||
|
@ -360,7 +360,7 @@ bool core_sqlsrv_get_odbc_error( _Inout_ sqlsrv_context& ctx, _In_ int record_nu
|
||||||
}
|
}
|
||||||
|
|
||||||
// format and return a driver specfic error
|
// format and return a driver specfic error
|
||||||
void core_sqlsrv_format_driver_error( _In_ sqlsrv_context& ctx, _In_ sqlsrv_error_const const* custom_error,
|
void core_sqlsrv_format_driver_error( _In_ sqlsrv_context& ctx, _In_ sqlsrv_error_const const* custom_error,
|
||||||
_Out_ sqlsrv_error_auto_ptr& formatted_error, _In_ logging_severity severity, _In_opt_ va_list* args )
|
_Out_ sqlsrv_error_auto_ptr& formatted_error, _In_ logging_severity severity, _In_opt_ va_list* args )
|
||||||
{
|
{
|
||||||
// allocate space for the formatted message
|
// allocate space for the formatted message
|
||||||
|
@ -368,13 +368,13 @@ void core_sqlsrv_format_driver_error( _In_ sqlsrv_context& ctx, _In_ sqlsrv_erro
|
||||||
formatted_error->sqlstate = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_SQLSTATE_BUFSIZE ));
|
formatted_error->sqlstate = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_SQLSTATE_BUFSIZE ));
|
||||||
formatted_error->native_message = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_MAX_ERROR_MESSAGE_LENGTH + 1 ));
|
formatted_error->native_message = reinterpret_cast<SQLCHAR*>( sqlsrv_malloc( SQL_MAX_ERROR_MESSAGE_LENGTH + 1 ));
|
||||||
|
|
||||||
DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, reinterpret_cast<LPSTR>( custom_error->native_message ), 0, 0,
|
DWORD rc = FormatMessage( FORMAT_MESSAGE_FROM_STRING, reinterpret_cast<LPSTR>( custom_error->native_message ), 0, 0,
|
||||||
reinterpret_cast<LPSTR>( formatted_error->native_message ), SQL_MAX_ERROR_MESSAGE_LENGTH, args );
|
reinterpret_cast<LPSTR>( formatted_error->native_message ), SQL_MAX_ERROR_MESSAGE_LENGTH, args );
|
||||||
if( rc == 0 ) {
|
if( rc == 0 ) {
|
||||||
strcpy_s( reinterpret_cast<char*>( formatted_error->native_message ), SQL_MAX_ERROR_MESSAGE_LENGTH,
|
strcpy_s( reinterpret_cast<char*>( formatted_error->native_message ), SQL_MAX_ERROR_MESSAGE_LENGTH,
|
||||||
reinterpret_cast<char*>( INTERNAL_FORMAT_ERROR ));
|
reinterpret_cast<char*>( INTERNAL_FORMAT_ERROR ));
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy_s( reinterpret_cast<char*>( formatted_error->sqlstate ), SQL_SQLSTATE_BUFSIZE,
|
strcpy_s( reinterpret_cast<char*>( formatted_error->sqlstate ), SQL_SQLSTATE_BUFSIZE,
|
||||||
reinterpret_cast<char*>( custom_error->sqlstate ));
|
reinterpret_cast<char*>( custom_error->sqlstate ));
|
||||||
formatted_error->native_code = custom_error->native_code;
|
formatted_error->native_code = custom_error->native_code;
|
||||||
|
@ -471,7 +471,7 @@ unsigned int convert_string_from_default_encoding( _In_ unsigned int php_encodin
|
||||||
#else
|
#else
|
||||||
unsigned int required_len = MultiByteToWideChar( win_encoding, MB_ERR_INVALID_CHARS, mbcs_in_string, mbcs_len, utf16_out_string, utf16_len );
|
unsigned int required_len = MultiByteToWideChar( win_encoding, MB_ERR_INVALID_CHARS, mbcs_in_string, mbcs_len, utf16_out_string, utf16_len );
|
||||||
#endif // !_Win32
|
#endif // !_Win32
|
||||||
|
|
||||||
if( required_len == 0 ) {
|
if( required_len == 0 ) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -509,7 +509,7 @@ namespace data_classification {
|
||||||
|
|
||||||
bool converted = convert_string_from_utf16(encoding, temp_field_name, len, field_name, field_name_len);
|
bool converted = convert_string_from_utf16(encoding, temp_field_name, len, field_name, field_name_len);
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(!converted, stmt, SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE, get_last_error_message()) {
|
CHECK_CUSTOM_ERROR(!converted, stmt, SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE, get_last_error_message(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,16 +524,16 @@ namespace data_classification {
|
||||||
}
|
}
|
||||||
sqlsrv_free(pair);
|
sqlsrv_free(pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_sensitivity_name_id_pairs(_Inout_ sqlsrv_stmt* stmt, _Inout_ USHORT& numpairs, _Inout_ std::vector<name_id_pair*, sqlsrv_allocator<name_id_pair*>>* pairs, _Inout_ unsigned char **pptr)
|
void parse_sensitivity_name_id_pairs(_Inout_ sqlsrv_stmt* stmt, _Inout_ USHORT& numpairs, _Inout_ std::vector<name_id_pair*, sqlsrv_allocator<name_id_pair*>>* pairs, _Inout_ unsigned char **pptr)
|
||||||
{
|
{
|
||||||
unsigned char *ptr = *pptr;
|
unsigned char *ptr = *pptr;
|
||||||
unsigned short npairs;
|
unsigned short npairs;
|
||||||
numpairs = npairs = *(reinterpret_cast<unsigned short*>(ptr));
|
numpairs = npairs = *(reinterpret_cast<unsigned short*>(ptr));
|
||||||
SQLSRV_ENCODING encoding = ((stmt->encoding() == SQLSRV_ENCODING_DEFAULT ) ? stmt->conn->encoding() : stmt->encoding());
|
SQLSRV_ENCODING encoding = ((stmt->encoding() == SQLSRV_ENCODING_DEFAULT ) ? stmt->conn->encoding() : stmt->encoding());
|
||||||
|
|
||||||
pairs->reserve(numpairs);
|
pairs->reserve(numpairs);
|
||||||
|
|
||||||
ptr += sizeof(unsigned short);
|
ptr += sizeof(unsigned short);
|
||||||
while (npairs--) {
|
while (npairs--) {
|
||||||
int namelen, idlen;
|
int namelen, idlen;
|
||||||
|
@ -549,7 +549,7 @@ namespace data_classification {
|
||||||
namelen = *ptr++;
|
namelen = *ptr++;
|
||||||
nameptr = ptr;
|
nameptr = ptr;
|
||||||
|
|
||||||
pair->name_len = namelen;
|
pair->name_len = namelen;
|
||||||
convert_sensivity_field(stmt, encoding, nameptr, namelen, (char**)&name, field_len);
|
convert_sensivity_field(stmt, encoding, nameptr, namelen, (char**)&name, field_len);
|
||||||
pair->name = name;
|
pair->name = name;
|
||||||
|
|
||||||
|
@ -566,7 +566,7 @@ namespace data_classification {
|
||||||
pair.transferred();
|
pair.transferred();
|
||||||
}
|
}
|
||||||
*pptr = ptr;
|
*pptr = ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_column_sensitivity_props(_Inout_ sensitivity_metadata* meta, _Inout_ unsigned char **pptr, _In_ bool getRankInfo)
|
void parse_column_sensitivity_props(_Inout_ sensitivity_metadata* meta, _Inout_ unsigned char **pptr, _In_ bool getRankInfo)
|
||||||
{
|
{
|
||||||
|
@ -628,7 +628,7 @@ namespace data_classification {
|
||||||
if (meta == NULL) {
|
if (meta == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLSRV_ASSERT(colno >= 0 && colno < meta->num_columns, "fill_column_sensitivity_array: column number out of bounds");
|
SQLSRV_ASSERT(colno >= 0 && colno < meta->num_columns, "fill_column_sensitivity_array: column number out of bounds");
|
||||||
|
|
||||||
zval data_classification;
|
zval data_classification;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Contents: Contains functions for handling Windows format strings
|
// Contents: Contains functions for handling Windows format strings
|
||||||
// and UTF-16 on non-Windows platforms
|
// and UTF-16 on non-Windows platforms
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Contents: Contains a portable abstraction for interlocked, atomic
|
// Contents: Contains a portable abstraction for interlocked, atomic
|
||||||
// operations on int32_t and pointer types.
|
// operations on int32_t and pointer types.
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Contents: Contains a portable abstraction for interlocked, atomic
|
// Contents: Contains a portable abstraction for interlocked, atomic
|
||||||
// operations on int32_t and pointer types.
|
// operations on int32_t and pointer types.
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Contents: Contains a portable abstraction for interlocked, singly
|
// Contents: Contains a portable abstraction for interlocked, singly
|
||||||
// linked list.
|
// linked list.
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Contains portable classes for localization
|
// Contents: Contains portable classes for localization
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// Must be included in one c/cpp file per binary
|
// Must be included in one c/cpp file per binary
|
||||||
// A build error will occur if this inclusion policy is not followed
|
// A build error will occur if this inclusion policy is not followed
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
// pecuniary loss) arising out of the use of or inability to use
|
// pecuniary loss) arising out of the use of or inability to use
|
||||||
// this SDK, even if Microsoft has been advised of the possibility
|
// this SDK, even if Microsoft has been advised of the possibility
|
||||||
// of such damages.
|
// of such damages.
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Contains the minimal definitions to build on non-Windows platforms
|
// Contents: Contains the minimal definitions to build on non-Windows platforms
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
// File: typedefs_for_linux.h
|
// File: typedefs_for_linux.h
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// File: version.h
|
// File: version.h
|
||||||
// Contents: Version number constants
|
// Contents: Version number constants
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
@ -26,12 +26,12 @@
|
||||||
// Increase Minor with backward compatible new functionalities and API changes.
|
// Increase Minor with backward compatible new functionalities and API changes.
|
||||||
// Increase Patch for backward compatible fixes.
|
// Increase Patch for backward compatible fixes.
|
||||||
#define SQLVERSION_MAJOR 5
|
#define SQLVERSION_MAJOR 5
|
||||||
#define SQLVERSION_MINOR 10
|
#define SQLVERSION_MINOR 11
|
||||||
#define SQLVERSION_PATCH 1
|
#define SQLVERSION_PATCH 0
|
||||||
#define SQLVERSION_BUILD 0
|
#define SQLVERSION_BUILD 0
|
||||||
|
|
||||||
// For previews, set this constant to 1, 2 and so on. Otherwise, set it to 0
|
// For previews, set this constant to 1, 2 and so on. Otherwise, set it to 0
|
||||||
#define PREVIEW 0
|
#define PREVIEW 1
|
||||||
#define SEMVER_PRERELEASE
|
#define SEMVER_PRERELEASE
|
||||||
|
|
||||||
// Semantic versioning build metadata, build meta data is not counted in precedence order.
|
// Semantic versioning build metadata, build meta data is not counted in precedence order.
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
#define _FILEVERSION SQLVERSION_MAJOR,SQLVERSION_MINOR,SQLVERSION_PATCH,SQLVERSION_BUILD
|
#define _FILEVERSION SQLVERSION_MAJOR,SQLVERSION_MINOR,SQLVERSION_PATCH,SQLVERSION_BUILD
|
||||||
|
|
||||||
// PECL package version ('-' or '+' is not allowed) - to support Pickle do not use macros below
|
// PECL package version ('-' or '+' is not allowed) - to support Pickle do not use macros below
|
||||||
#define PHP_SQLSRV_VERSION "5.10.1"
|
#define PHP_SQLSRV_VERSION "5.11.0"
|
||||||
#define PHP_PDO_SQLSRV_VERSION "5.10.1"
|
#define PHP_PDO_SQLSRV_VERSION "5.11.0"
|
||||||
|
|
||||||
#endif // VERSION_H
|
#endif // VERSION_H
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: include for definition of Windows types for non-Windows platforms
|
// Contents: include for definition of Windows types for non-Windows platforms
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
// Contents: This module defines helper functions to prevent
|
// Contents: This module defines helper functions to prevent
|
||||||
// integer overflow bugs.
|
// integer overflow bugs.
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Contains the minimal definitions to build on non-Windows platforms
|
// Contents: Contains the minimal definitions to build on non-Windows platforms
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Contains the minimal definitions to build on non-Windows platforms
|
// Contents: Contains the minimal definitions to build on non-Windows platforms
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -4,7 +4,7 @@ dnl
|
||||||
dnl Contents: the code that will go into the configure script, indicating options,
|
dnl Contents: the code that will go into the configure script, indicating options,
|
||||||
dnl external libraries and includes, and what source files are to be compiled.
|
dnl external libraries and includes, and what source files are to be compiled.
|
||||||
dnl
|
dnl
|
||||||
dnl Microsoft Drivers 5.10 for PHP for SQL Server
|
dnl Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
dnl Copyright(c) Microsoft Corporation
|
dnl Copyright(c) Microsoft Corporation
|
||||||
dnl All rights reserved.
|
dnl All rights reserved.
|
||||||
dnl MIT License
|
dnl MIT License
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: JScript build configuration used by buildconf.bat
|
// Contents: JScript build configuration used by buildconf.bat
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -3,17 +3,17 @@
|
||||||
//
|
//
|
||||||
// Contents: Routines that use connection handles
|
// Contents: Routines that use connection handles
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
|
// 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,
|
// 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 :
|
// 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 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,
|
// 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
|
// 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
|
// 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.
|
// IN THE SOFTWARE.
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ struct conn_char_set_func {
|
||||||
if (!strnicmp( encoding, ss_encoding->iana, encoding_len )) {
|
if (!strnicmp( encoding, ss_encoding->iana, encoding_len )) {
|
||||||
|
|
||||||
if ( ss_encoding->not_for_connection ) {
|
if ( ss_encoding->not_for_connection ) {
|
||||||
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding );
|
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->set_encoding( static_cast<SQLSRV_ENCODING>(ss_encoding->code_page ));
|
conn->set_encoding( static_cast<SQLSRV_ENCODING>(ss_encoding->code_page ));
|
||||||
|
@ -125,7 +125,7 @@ struct conn_char_set_func {
|
||||||
}
|
}
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
|
||||||
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding );
|
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_CONNECT_ILLEGAL_ENCODING, encoding, NULL );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ struct int_conn_str_func {
|
||||||
|
|
||||||
static void func( _In_ connection_option const* option, _In_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str )
|
static void func( _In_ connection_option const* option, _In_ zval* value, sqlsrv_conn* /*conn*/, _Out_ std::string& conn_str )
|
||||||
{
|
{
|
||||||
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_LONG, "An integer is expected for this keyword" )
|
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_LONG, "An integer is expected for this keyword" )
|
||||||
|
|
||||||
char temp_str[MAX_CONN_VALSTRING_LEN];
|
char temp_str[MAX_CONN_VALSTRING_LEN];
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@ struct int_conn_attr_func {
|
||||||
static void func( connection_option const* /*option*/, _In_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ )
|
static void func( connection_option const* /*option*/, _In_ zval* value, _Inout_ sqlsrv_conn* conn, std::string& /*conn_str*/ )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|
||||||
core::SQLSetConnectAttr( conn, Attr, reinterpret_cast<SQLPOINTER>( Z_LVAL_P( value )), SQL_IS_UINTEGER );
|
core::SQLSetConnectAttr( conn, Attr, reinterpret_cast<SQLPOINTER>( Z_LVAL_P( value )), SQL_IS_UINTEGER );
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
@ -175,7 +175,7 @@ struct bool_conn_attr_func {
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
core::SQLSetConnectAttr(conn, Attr, reinterpret_cast<SQLPOINTER>((zend_long)zend_is_true(value)), SQL_IS_UINTEGER);
|
core::SQLSetConnectAttr(conn, Attr, reinterpret_cast<SQLPOINTER>((zend_long)zend_is_true(value)), SQL_IS_UINTEGER);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
throw;
|
throw;
|
||||||
|
@ -187,13 +187,13 @@ struct bool_conn_attr_func {
|
||||||
//// *** internal functions ***
|
//// *** internal functions ***
|
||||||
|
|
||||||
void sqlsrv_conn_close_stmts( _Inout_ ss_sqlsrv_conn* conn );
|
void sqlsrv_conn_close_stmts( _Inout_ ss_sqlsrv_conn* conn );
|
||||||
void validate_conn_options( _Inout_ sqlsrv_context& ctx, _In_ zval* user_options_z, _Inout_ char** uid, _Inout_ char** pwd,
|
void validate_conn_options( _Inout_ sqlsrv_context& ctx, _In_ zval* user_options_z, _Inout_ char** uid, _Inout_ char** pwd,
|
||||||
_Inout_ HashTable* ss_conn_options_ht );
|
_Inout_ HashTable* ss_conn_options_ht );
|
||||||
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* ss_stmt_options_ht );
|
void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_options, _Inout_ HashTable* ss_stmt_options_ht );
|
||||||
void add_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len,
|
void add_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len,
|
||||||
_Inout_ HashTable* options_ht, _Inout_ zval* data );
|
_Inout_ HashTable* options_ht, _Inout_ zval* data );
|
||||||
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len, _Inout_ HashTable* options_ht, _Inout_ zval* data );
|
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len, _Inout_ HashTable* options_ht, _Inout_ zval* data );
|
||||||
int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len, _Inout_ zval const* value_z );
|
int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len, _Inout_ zval const* value_z );
|
||||||
int get_stmt_option_key( _In_ zend_string* key, _In_ size_t key_len );
|
int get_stmt_option_key( _In_ zend_string* key, _In_ size_t key_len );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -264,60 +264,60 @@ const char HostNameInCertificate[] = "HostNameInCertificate";
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SS_CONN_OPTIONS {
|
enum SS_CONN_OPTIONS {
|
||||||
|
|
||||||
SS_CONN_OPTION_DATE_AS_STRING = SQLSRV_CONN_OPTION_DRIVER_SPECIFIC,
|
SS_CONN_OPTION_DATE_AS_STRING = SQLSRV_CONN_OPTION_DRIVER_SPECIFIC,
|
||||||
SS_CONN_OPTION_FORMAT_DECIMALS,
|
SS_CONN_OPTION_FORMAT_DECIMALS,
|
||||||
SS_CONN_OPTION_DECIMAL_PLACES,
|
SS_CONN_OPTION_DECIMAL_PLACES,
|
||||||
};
|
};
|
||||||
|
|
||||||
//List of all statement options supported by this driver
|
//List of all statement options supported by this driver
|
||||||
const stmt_option SS_STMT_OPTS[] = {
|
const stmt_option SS_STMT_OPTS[] = {
|
||||||
{
|
{
|
||||||
SSStmtOptionNames::QUERY_TIMEOUT,
|
SSStmtOptionNames::QUERY_TIMEOUT,
|
||||||
sizeof( SSStmtOptionNames::QUERY_TIMEOUT ),
|
sizeof( SSStmtOptionNames::QUERY_TIMEOUT ),
|
||||||
SQLSRV_STMT_OPTION_QUERY_TIMEOUT,
|
SQLSRV_STMT_OPTION_QUERY_TIMEOUT,
|
||||||
std::unique_ptr<stmt_option_query_timeout>( new stmt_option_query_timeout )
|
std::unique_ptr<stmt_option_query_timeout>( new stmt_option_query_timeout )
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSStmtOptionNames::SEND_STREAMS_AT_EXEC,
|
SSStmtOptionNames::SEND_STREAMS_AT_EXEC,
|
||||||
sizeof( SSStmtOptionNames::SEND_STREAMS_AT_EXEC ),
|
sizeof( SSStmtOptionNames::SEND_STREAMS_AT_EXEC ),
|
||||||
SQLSRV_STMT_OPTION_SEND_STREAMS_AT_EXEC,
|
SQLSRV_STMT_OPTION_SEND_STREAMS_AT_EXEC,
|
||||||
std::unique_ptr<stmt_option_send_at_exec>( new stmt_option_send_at_exec )
|
std::unique_ptr<stmt_option_send_at_exec>( new stmt_option_send_at_exec )
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSStmtOptionNames::SCROLLABLE,
|
SSStmtOptionNames::SCROLLABLE,
|
||||||
sizeof( SSStmtOptionNames::SCROLLABLE ),
|
sizeof( SSStmtOptionNames::SCROLLABLE ),
|
||||||
SQLSRV_STMT_OPTION_SCROLLABLE,
|
SQLSRV_STMT_OPTION_SCROLLABLE,
|
||||||
std::unique_ptr<stmt_option_ss_scrollable>( new stmt_option_ss_scrollable )
|
std::unique_ptr<stmt_option_ss_scrollable>( new stmt_option_ss_scrollable )
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE,
|
SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE,
|
||||||
sizeof( SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE ),
|
sizeof( SSStmtOptionNames::CLIENT_BUFFER_MAX_SIZE ),
|
||||||
SQLSRV_STMT_OPTION_CLIENT_BUFFER_MAX_SIZE,
|
SQLSRV_STMT_OPTION_CLIENT_BUFFER_MAX_SIZE,
|
||||||
std::unique_ptr<stmt_option_buffered_query_limit>( new stmt_option_buffered_query_limit )
|
std::unique_ptr<stmt_option_buffered_query_limit>( new stmt_option_buffered_query_limit )
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSStmtOptionNames::DATE_AS_STRING,
|
SSStmtOptionNames::DATE_AS_STRING,
|
||||||
sizeof( SSStmtOptionNames::DATE_AS_STRING ),
|
sizeof( SSStmtOptionNames::DATE_AS_STRING ),
|
||||||
SQLSRV_STMT_OPTION_DATE_AS_STRING,
|
SQLSRV_STMT_OPTION_DATE_AS_STRING,
|
||||||
std::unique_ptr<stmt_option_date_as_string>( new stmt_option_date_as_string )
|
std::unique_ptr<stmt_option_date_as_string>( new stmt_option_date_as_string )
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSStmtOptionNames::FORMAT_DECIMALS,
|
SSStmtOptionNames::FORMAT_DECIMALS,
|
||||||
sizeof( SSStmtOptionNames::FORMAT_DECIMALS ),
|
sizeof( SSStmtOptionNames::FORMAT_DECIMALS ),
|
||||||
SQLSRV_STMT_OPTION_FORMAT_DECIMALS,
|
SQLSRV_STMT_OPTION_FORMAT_DECIMALS,
|
||||||
std::unique_ptr<stmt_option_format_decimals>( new stmt_option_format_decimals )
|
std::unique_ptr<stmt_option_format_decimals>( new stmt_option_format_decimals )
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSStmtOptionNames::DECIMAL_PLACES,
|
SSStmtOptionNames::DECIMAL_PLACES,
|
||||||
sizeof( SSStmtOptionNames::DECIMAL_PLACES),
|
sizeof( SSStmtOptionNames::DECIMAL_PLACES),
|
||||||
SQLSRV_STMT_OPTION_DECIMAL_PLACES,
|
SQLSRV_STMT_OPTION_DECIMAL_PLACES,
|
||||||
std::unique_ptr<stmt_option_decimal_places>( new stmt_option_decimal_places )
|
std::unique_ptr<stmt_option_decimal_places>( new stmt_option_decimal_places )
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSStmtOptionNames::DATA_CLASSIFICATION,
|
SSStmtOptionNames::DATA_CLASSIFICATION,
|
||||||
sizeof( SSStmtOptionNames::DATA_CLASSIFICATION ),
|
sizeof( SSStmtOptionNames::DATA_CLASSIFICATION ),
|
||||||
SQLSRV_STMT_OPTION_DATA_CLASSIFICATION,
|
SQLSRV_STMT_OPTION_DATA_CLASSIFICATION,
|
||||||
std::unique_ptr<stmt_option_data_classification>( new stmt_option_data_classification )
|
std::unique_ptr<stmt_option_data_classification>( new stmt_option_data_classification )
|
||||||
},
|
},
|
||||||
{ NULL, 0, SQLSRV_STMT_OPTION_INVALID, std::unique_ptr<stmt_option_functor>{} },
|
{ NULL, 0, SQLSRV_STMT_OPTION_INVALID, std::unique_ptr<stmt_option_functor>{} },
|
||||||
|
@ -326,32 +326,32 @@ const stmt_option SS_STMT_OPTS[] = {
|
||||||
|
|
||||||
// List of all connection options supported by this driver.
|
// List of all connection options supported by this driver.
|
||||||
const connection_option SS_CONN_OPTS[] = {
|
const connection_option SS_CONN_OPTS[] = {
|
||||||
{
|
{
|
||||||
SSConnOptionNames::APP,
|
SSConnOptionNames::APP,
|
||||||
sizeof( SSConnOptionNames::APP ),
|
sizeof( SSConnOptionNames::APP ),
|
||||||
SQLSRV_CONN_OPTION_APP,
|
SQLSRV_CONN_OPTION_APP,
|
||||||
ODBCConnOptions::APP,
|
ODBCConnOptions::APP,
|
||||||
sizeof( ODBCConnOptions::APP ),
|
sizeof( ODBCConnOptions::APP ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSConnOptionNames::AccessToken,
|
SSConnOptionNames::AccessToken,
|
||||||
sizeof( SSConnOptionNames::AccessToken ),
|
sizeof( SSConnOptionNames::AccessToken ),
|
||||||
SQLSRV_CONN_OPTION_ACCESS_TOKEN,
|
SQLSRV_CONN_OPTION_ACCESS_TOKEN,
|
||||||
ODBCConnOptions::AccessToken,
|
ODBCConnOptions::AccessToken,
|
||||||
sizeof( ODBCConnOptions::AccessToken),
|
sizeof( ODBCConnOptions::AccessToken),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
access_token_set_func::func
|
access_token_set_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSConnOptionNames::ApplicationIntent,
|
SSConnOptionNames::ApplicationIntent,
|
||||||
sizeof( SSConnOptionNames::ApplicationIntent ),
|
sizeof( SSConnOptionNames::ApplicationIntent ),
|
||||||
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
|
SQLSRV_CONN_OPTION_APPLICATION_INTENT,
|
||||||
ODBCConnOptions::ApplicationIntent,
|
ODBCConnOptions::ApplicationIntent,
|
||||||
sizeof( ODBCConnOptions::ApplicationIntent ),
|
sizeof( ODBCConnOptions::ApplicationIntent ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSConnOptionNames::AttachDBFileName,
|
SSConnOptionNames::AttachDBFileName,
|
||||||
|
@ -447,17 +447,17 @@ const connection_option SS_CONN_OPTS[] = {
|
||||||
SSConnOptionNames::Encrypt,
|
SSConnOptionNames::Encrypt,
|
||||||
sizeof( SSConnOptionNames::Encrypt ),
|
sizeof( SSConnOptionNames::Encrypt ),
|
||||||
SQLSRV_CONN_OPTION_ENCRYPT,
|
SQLSRV_CONN_OPTION_ENCRYPT,
|
||||||
ODBCConnOptions::Encrypt,
|
ODBCConnOptions::Encrypt,
|
||||||
sizeof( ODBCConnOptions::Encrypt ),
|
sizeof( ODBCConnOptions::Encrypt ),
|
||||||
CONN_ATTR_MIXED,
|
CONN_ATTR_MIXED,
|
||||||
srv_encrypt_set_func::func
|
srv_encrypt_set_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSConnOptionNames::Failover_Partner,
|
SSConnOptionNames::Failover_Partner,
|
||||||
sizeof( SSConnOptionNames::Failover_Partner ),
|
sizeof( SSConnOptionNames::Failover_Partner ),
|
||||||
SQLSRV_CONN_OPTION_FAILOVER_PARTNER,
|
SQLSRV_CONN_OPTION_FAILOVER_PARTNER,
|
||||||
ODBCConnOptions::Failover_Partner,
|
ODBCConnOptions::Failover_Partner,
|
||||||
sizeof( ODBCConnOptions::Failover_Partner ),
|
sizeof( ODBCConnOptions::Failover_Partner ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
|
@ -468,7 +468,7 @@ const connection_option SS_CONN_OPTS[] = {
|
||||||
ODBCConnOptions::KeyStoreAuthentication,
|
ODBCConnOptions::KeyStoreAuthentication,
|
||||||
sizeof( ODBCConnOptions::KeyStoreAuthentication ),
|
sizeof( ODBCConnOptions::KeyStoreAuthentication ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
ce_akv_str_set_func::func
|
ce_akv_str_set_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSConnOptionNames::KeyStorePrincipalId,
|
SSConnOptionNames::KeyStorePrincipalId,
|
||||||
|
@ -477,7 +477,7 @@ const connection_option SS_CONN_OPTS[] = {
|
||||||
ODBCConnOptions::KeyStorePrincipalId,
|
ODBCConnOptions::KeyStorePrincipalId,
|
||||||
sizeof( ODBCConnOptions::KeyStorePrincipalId ),
|
sizeof( ODBCConnOptions::KeyStorePrincipalId ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
ce_akv_str_set_func::func
|
ce_akv_str_set_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSConnOptionNames::KeyStoreSecret,
|
SSConnOptionNames::KeyStoreSecret,
|
||||||
|
@ -495,7 +495,7 @@ const connection_option SS_CONN_OPTS[] = {
|
||||||
ODBCConnOptions::LoginTimeout,
|
ODBCConnOptions::LoginTimeout,
|
||||||
sizeof( ODBCConnOptions::LoginTimeout ),
|
sizeof( ODBCConnOptions::LoginTimeout ),
|
||||||
CONN_ATTR_INT,
|
CONN_ATTR_INT,
|
||||||
int_conn_attr_func<SQL_ATTR_LOGIN_TIMEOUT>::func
|
int_conn_attr_func<SQL_ATTR_LOGIN_TIMEOUT>::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSConnOptionNames::MARS_Option,
|
SSConnOptionNames::MARS_Option,
|
||||||
|
@ -529,9 +529,9 @@ const connection_option SS_CONN_OPTS[] = {
|
||||||
sizeof( SSConnOptionNames::TraceFile ),
|
sizeof( SSConnOptionNames::TraceFile ),
|
||||||
SQLSRV_CONN_OPTION_TRACE_FILE,
|
SQLSRV_CONN_OPTION_TRACE_FILE,
|
||||||
ODBCConnOptions::TraceFile,
|
ODBCConnOptions::TraceFile,
|
||||||
sizeof( ODBCConnOptions::TraceFile ),
|
sizeof( ODBCConnOptions::TraceFile ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
str_conn_attr_func<SQL_ATTR_TRACEFILE>::func
|
str_conn_attr_func<SQL_ATTR_TRACEFILE>::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SSConnOptionNames::TraceOn,
|
SSConnOptionNames::TraceOn,
|
||||||
|
@ -575,7 +575,7 @@ const connection_option SS_CONN_OPTS[] = {
|
||||||
SQLSRV_CONN_OPTION_WSID,
|
SQLSRV_CONN_OPTION_WSID,
|
||||||
ODBCConnOptions::WSID,
|
ODBCConnOptions::WSID,
|
||||||
sizeof( ODBCConnOptions::WSID ),
|
sizeof( ODBCConnOptions::WSID ),
|
||||||
CONN_ATTR_STRING,
|
CONN_ATTR_STRING,
|
||||||
conn_str_append_func::func
|
conn_str_append_func::func
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -643,11 +643,11 @@ const connection_option SS_CONN_OPTS[] = {
|
||||||
// $connectionInfo [OPTIONAL]: An associative array that contains connection
|
// $connectionInfo [OPTIONAL]: An associative array that contains connection
|
||||||
// attributes (for example, array("Database" => "AdventureWorks")).
|
// attributes (for example, array("Database" => "AdventureWorks")).
|
||||||
//
|
//
|
||||||
// Return Value
|
// Return Value
|
||||||
// A PHP connection resource. If a connection cannot be successfully created and
|
// A PHP connection resource. If a connection cannot be successfully created and
|
||||||
// opened, false is returned
|
// opened, false is returned
|
||||||
|
|
||||||
PHP_FUNCTION ( sqlsrv_connect )
|
PHP_FUNCTION ( sqlsrv_connect )
|
||||||
{
|
{
|
||||||
LOG_FUNCTION( "sqlsrv_connect" );
|
LOG_FUNCTION( "sqlsrv_connect" );
|
||||||
g_ss_henv_cp->set_func(_FN_);
|
g_ss_henv_cp->set_func(_FN_);
|
||||||
|
@ -664,11 +664,11 @@ PHP_FUNCTION ( sqlsrv_connect )
|
||||||
ZVAL_UNDEF(&conn_z);
|
ZVAL_UNDEF(&conn_z);
|
||||||
// get the server name and connection options
|
// get the server name and connection options
|
||||||
int result = zend_parse_parameters( ZEND_NUM_ARGS(), "s|a", &server, &server_len, &options_z );
|
int result = zend_parse_parameters( ZEND_NUM_ARGS(), "s|a", &server, &server_len, &options_z );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( result == FAILURE ), *g_ss_henv_cp, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, "sqlsrv_connect" ) {
|
CHECK_CUSTOM_ERROR(( result == FAILURE ), *g_ss_henv_cp, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, "sqlsrv_connect", NULL) {
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
hash_auto_ptr ss_conn_options_ht;
|
hash_auto_ptr ss_conn_options_ht;
|
||||||
hash_auto_ptr stmts;
|
hash_auto_ptr stmts;
|
||||||
ss_sqlsrv_conn* conn = NULL;
|
ss_sqlsrv_conn* conn = NULL;
|
||||||
|
@ -677,38 +677,38 @@ PHP_FUNCTION ( sqlsrv_connect )
|
||||||
|
|
||||||
// Initialize the options array to be passed to the core layer
|
// Initialize the options array to be passed to the core layer
|
||||||
ALLOC_HASHTABLE( ss_conn_options_ht );
|
ALLOC_HASHTABLE( ss_conn_options_ht );
|
||||||
|
|
||||||
core::sqlsrv_zend_hash_init( *g_ss_henv_cp, ss_conn_options_ht, 10 /* # of buckets */,
|
core::sqlsrv_zend_hash_init( *g_ss_henv_cp, ss_conn_options_ht, 10 /* # of buckets */,
|
||||||
ZVAL_PTR_DTOR, 0 /*persistent*/ );
|
ZVAL_PTR_DTOR, 0 /*persistent*/ );
|
||||||
|
|
||||||
// Either of g_ss_henv_cp or g_ss_henv_ncp can be used to propagate the error.
|
// Either of g_ss_henv_cp or g_ss_henv_ncp can be used to propagate the error.
|
||||||
::validate_conn_options( *g_ss_henv_cp, options_z, &uid, &pwd, ss_conn_options_ht );
|
::validate_conn_options( *g_ss_henv_cp, options_z, &uid, &pwd, ss_conn_options_ht );
|
||||||
|
|
||||||
// call the core connect function
|
// call the core connect function
|
||||||
conn = static_cast<ss_sqlsrv_conn*>( core_sqlsrv_connect( *g_ss_henv_cp, *g_ss_henv_ncp, &core::allocate_conn<ss_sqlsrv_conn>,
|
conn = static_cast<ss_sqlsrv_conn*>( core_sqlsrv_connect( *g_ss_henv_cp, *g_ss_henv_ncp, &core::allocate_conn<ss_sqlsrv_conn>,
|
||||||
server, uid, pwd, ss_conn_options_ht, ss_error_handler,
|
server, uid, pwd, ss_conn_options_ht, ss_error_handler,
|
||||||
SS_CONN_OPTS, NULL, "sqlsrv_connect" ));
|
SS_CONN_OPTS, NULL, "sqlsrv_connect" ));
|
||||||
|
|
||||||
SQLSRV_ASSERT( conn != NULL, "sqlsrv_connect: Invalid connection returned. Exception should have been thrown." );
|
SQLSRV_ASSERT( conn != NULL, "sqlsrv_connect: Invalid connection returned. Exception should have been thrown." );
|
||||||
|
|
||||||
// create a bunch of statements
|
// create a bunch of statements
|
||||||
ALLOC_HASHTABLE( stmts );
|
ALLOC_HASHTABLE( stmts );
|
||||||
|
|
||||||
core::sqlsrv_zend_hash_init( *g_ss_henv_cp, stmts, 5, NULL /* dtor */, 0 /* persistent */ );
|
core::sqlsrv_zend_hash_init( *g_ss_henv_cp, stmts, 5, NULL /* dtor */, 0 /* persistent */ );
|
||||||
|
|
||||||
// register the connection with the PHP runtime
|
// register the connection with the PHP runtime
|
||||||
|
|
||||||
ss::zend_register_resource(conn_z, conn, ss_sqlsrv_conn::descriptor, ss_sqlsrv_conn::resource_name);
|
ss::zend_register_resource(conn_z, conn, ss_sqlsrv_conn::descriptor, ss_sqlsrv_conn::resource_name);
|
||||||
|
|
||||||
conn->stmts = stmts;
|
conn->stmts = stmts;
|
||||||
stmts.transferred();
|
stmts.transferred();
|
||||||
RETURN_RES( Z_RES(conn_z) );
|
RETURN_RES( Z_RES(conn_z) );
|
||||||
}
|
}
|
||||||
|
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
|
||||||
if( conn != NULL ) {
|
if( conn != NULL ) {
|
||||||
|
|
||||||
conn->invalidate();
|
conn->invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -732,7 +732,7 @@ PHP_FUNCTION ( sqlsrv_connect )
|
||||||
// queries are automatically committed upon success unless they have been
|
// queries are automatically committed upon success unless they have been
|
||||||
// designated as part of an explicit transaction by using
|
// designated as part of an explicit transaction by using
|
||||||
// sqlsrv_begin_transaction.
|
// sqlsrv_begin_transaction.
|
||||||
//
|
//
|
||||||
// If sqlsrv_begin_transaction is called after a transaction has already been
|
// If sqlsrv_begin_transaction is called after a transaction has already been
|
||||||
// initiated on the connection but not completed by calling either sqlsrv_commit
|
// initiated on the connection but not completed by calling either sqlsrv_commit
|
||||||
// or sqlsrv_rollback, the call returns false and an Already in Transaction
|
// or sqlsrv_rollback, the call returns false and an Already in Transaction
|
||||||
|
@ -744,11 +744,11 @@ PHP_FUNCTION ( sqlsrv_connect )
|
||||||
// Return Value
|
// Return Value
|
||||||
// A Boolean value: true if the transaction was successfully begun. Otherwise, false.
|
// A Boolean value: true if the transaction was successfully begun. Otherwise, false.
|
||||||
|
|
||||||
PHP_FUNCTION( sqlsrv_begin_transaction )
|
PHP_FUNCTION( sqlsrv_begin_transaction )
|
||||||
{
|
{
|
||||||
LOG_FUNCTION( "sqlsrv_begin_transaction" );
|
LOG_FUNCTION( "sqlsrv_begin_transaction" );
|
||||||
|
|
||||||
|
|
||||||
ss_sqlsrv_conn* conn = NULL;
|
ss_sqlsrv_conn* conn = NULL;
|
||||||
PROCESS_PARAMS( conn, "r", _FN_, 0 );
|
PROCESS_PARAMS( conn, "r", _FN_, 0 );
|
||||||
|
|
||||||
|
@ -766,7 +766,7 @@ PHP_FUNCTION( sqlsrv_begin_transaction )
|
||||||
|
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
catch( ... ) {
|
catch( ... ) {
|
||||||
|
|
||||||
DIE("sqlsrv_begin_transaction: Unknown exception caught.");
|
DIE("sqlsrv_begin_transaction: Unknown exception caught.");
|
||||||
|
@ -793,33 +793,33 @@ PHP_FUNCTION( sqlsrv_begin_transaction )
|
||||||
PHP_FUNCTION( sqlsrv_close )
|
PHP_FUNCTION( sqlsrv_close )
|
||||||
{
|
{
|
||||||
LOG_FUNCTION( "sqlsrv_close" );
|
LOG_FUNCTION( "sqlsrv_close" );
|
||||||
|
|
||||||
zval* conn_r = NULL;
|
zval* conn_r = NULL;
|
||||||
ss_sqlsrv_conn* conn = NULL;
|
ss_sqlsrv_conn* conn = NULL;
|
||||||
sqlsrv_context_auto_ptr error_ctx;
|
sqlsrv_context_auto_ptr error_ctx;
|
||||||
|
|
||||||
reset_errors();
|
reset_errors();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// dummy context to pass to the error handler
|
// dummy context to pass to the error handler
|
||||||
error_ctx = new (sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
|
error_ctx = new (sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
|
||||||
error_ctx->set_func(_FN_);
|
error_ctx->set_func(_FN_);
|
||||||
|
|
||||||
if( zend_parse_parameters(ZEND_NUM_ARGS(), "r", &conn_r) == FAILURE ) {
|
if( zend_parse_parameters(ZEND_NUM_ARGS(), "r", &conn_r) == FAILURE ) {
|
||||||
|
|
||||||
// Check if it was a zval
|
// Check if it was a zval
|
||||||
int zr = zend_parse_parameters( ZEND_NUM_ARGS(), "z", &conn_r );
|
int zr = zend_parse_parameters( ZEND_NUM_ARGS(), "z", &conn_r );
|
||||||
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
|
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ , NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if sqlsrv_close was called on a non-existent connection then we just return success.
|
// if sqlsrv_close was called on a non-existent connection then we just return success.
|
||||||
if( Z_TYPE_P( conn_r ) == IS_NULL ) {
|
if( Z_TYPE_P( conn_r ) == IS_NULL ) {
|
||||||
RETURN_TRUE;
|
RETURN_TRUE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SQLSRV_ASSERT( conn_r != NULL, "sqlsrv_close: conn_r was null" );
|
SQLSRV_ASSERT( conn_r != NULL, "sqlsrv_close: conn_r was null" );
|
||||||
|
@ -829,16 +829,16 @@ PHP_FUNCTION( sqlsrv_close )
|
||||||
if ( Z_RES_TYPE_P( conn_r ) == RSRC_INVALID_TYPE) {
|
if ( Z_RES_TYPE_P( conn_r ) == RSRC_INVALID_TYPE) {
|
||||||
RETURN_TRUE;
|
RETURN_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( conn == NULL ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
|
CHECK_CUSTOM_ERROR(( conn == NULL ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
conn->set_func(_FN_);
|
conn->set_func(_FN_);
|
||||||
|
|
||||||
// cause any variables still holding a reference to this to be invalid so they cause
|
// cause any variables still holding a reference to this to be invalid so they cause
|
||||||
// an error when passed to a sqlsrv function. There's nothing we can do if the
|
// an error when passed to a sqlsrv function. There's nothing we can do if the
|
||||||
// removal fails, so we just log it and move on.
|
// removal fails, so we just log it and move on.
|
||||||
#if PHP_VERSION_ID < 80000
|
#if PHP_VERSION_ID < 80000
|
||||||
if (zend_list_close(Z_RES_P(conn_r)) == FAILURE) {
|
if (zend_list_close(Z_RES_P(conn_r)) == FAILURE) {
|
||||||
|
@ -857,7 +857,7 @@ PHP_FUNCTION( sqlsrv_close )
|
||||||
RETURN_TRUE;
|
RETURN_TRUE;
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
catch( ... ) {
|
catch( ... ) {
|
||||||
|
@ -868,7 +868,7 @@ PHP_FUNCTION( sqlsrv_close )
|
||||||
|
|
||||||
void __cdecl sqlsrv_conn_dtor( _Inout_ zend_resource *rsrc )
|
void __cdecl sqlsrv_conn_dtor( _Inout_ zend_resource *rsrc )
|
||||||
{
|
{
|
||||||
// Without sqlsrv_close(), this function is invoked by php during the final clean up stage.
|
// Without sqlsrv_close(), this function is invoked by php during the final clean up stage.
|
||||||
// To prevent memory/resource leaks, no more logging at this point.
|
// To prevent memory/resource leaks, no more logging at this point.
|
||||||
//LOG_FUNCTION( "sqlsrv_conn_dtor" );
|
//LOG_FUNCTION( "sqlsrv_conn_dtor" );
|
||||||
|
|
||||||
|
@ -883,17 +883,17 @@ void __cdecl sqlsrv_conn_dtor( _Inout_ zend_resource *rsrc )
|
||||||
|
|
||||||
// close the connection itself.
|
// close the connection itself.
|
||||||
core_sqlsrv_close( conn );
|
core_sqlsrv_close( conn );
|
||||||
|
|
||||||
rsrc->ptr = NULL;
|
rsrc->ptr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sqlsrv_commit( resource $conn )
|
// sqlsrv_commit( resource $conn )
|
||||||
//
|
//
|
||||||
// Commits the current transaction on the specified connection and returns the
|
// Commits the current transaction on the specified connection and returns the
|
||||||
// connection to the auto-commit mode. The current transaction includes all
|
// connection to the auto-commit mode. The current transaction includes all
|
||||||
// statements on the specified connection that were executed after the call to
|
// statements on the specified connection that were executed after the call to
|
||||||
// sqlsrv_begin_transaction and before any calls to sqlsrv_rollback or
|
// sqlsrv_begin_transaction and before any calls to sqlsrv_rollback or
|
||||||
// sqlsrv_commit.
|
// sqlsrv_commit.
|
||||||
|
|
||||||
// The SQLSRV driver is in auto-commit mode by
|
// The SQLSRV driver is in auto-commit mode by
|
||||||
// default. This means that all queries are automatically committed upon success
|
// default. This means that all queries are automatically committed upon success
|
||||||
|
@ -902,7 +902,7 @@ void __cdecl sqlsrv_conn_dtor( _Inout_ zend_resource *rsrc )
|
||||||
// not in an active transaction and that was initiated with
|
// not in an active transaction and that was initiated with
|
||||||
// sqlsrv_begin_transaction, the call returns false and a Not in Transaction
|
// sqlsrv_begin_transaction, the call returns false and a Not in Transaction
|
||||||
// error is added to the error collection.
|
// error is added to the error collection.
|
||||||
//
|
//
|
||||||
// Parameters
|
// Parameters
|
||||||
// $conn: The connection on which the transaction is active.
|
// $conn: The connection on which the transaction is active.
|
||||||
//
|
//
|
||||||
|
@ -921,7 +921,7 @@ PHP_FUNCTION( sqlsrv_commit )
|
||||||
CHECK_CUSTOM_ERROR(( conn->in_transaction == false ), *conn, SS_SQLSRV_ERROR_NOT_IN_TXN ) {
|
CHECK_CUSTOM_ERROR(( conn->in_transaction == false ), *conn, SS_SQLSRV_ERROR_NOT_IN_TXN ) {
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
conn->in_transaction = false;
|
conn->in_transaction = false;
|
||||||
|
@ -945,7 +945,7 @@ PHP_FUNCTION( sqlsrv_commit )
|
||||||
// statements on the specified connection that were executed after the call to
|
// statements on the specified connection that were executed after the call to
|
||||||
// sqlsrv_begin_transaction and before any calls to sqlsrv_rollback or
|
// sqlsrv_begin_transaction and before any calls to sqlsrv_rollback or
|
||||||
// sqlsrv_commit.
|
// sqlsrv_commit.
|
||||||
//
|
//
|
||||||
// The SQLSRV driver is in auto-commit mode by default. This
|
// The SQLSRV driver is in auto-commit mode by default. This
|
||||||
// means that all queries are automatically committed upon success unless they
|
// means that all queries are automatically committed upon success unless they
|
||||||
// have been designated as part of an explicit transaction by using
|
// have been designated as part of an explicit transaction by using
|
||||||
|
@ -955,7 +955,7 @@ PHP_FUNCTION( sqlsrv_commit )
|
||||||
// transaction that was initiated with sqlsrv_begin_transaction, the call
|
// transaction that was initiated with sqlsrv_begin_transaction, the call
|
||||||
// returns false and a Not in Transaction error is added to the error
|
// returns false and a Not in Transaction error is added to the error
|
||||||
// collection.
|
// collection.
|
||||||
//
|
//
|
||||||
// Parameters
|
// Parameters
|
||||||
// $conn: The connection on which the transaction is active.
|
// $conn: The connection on which the transaction is active.
|
||||||
//
|
//
|
||||||
|
@ -970,14 +970,14 @@ PHP_FUNCTION( sqlsrv_rollback )
|
||||||
ss_sqlsrv_conn* conn = NULL;
|
ss_sqlsrv_conn* conn = NULL;
|
||||||
|
|
||||||
PROCESS_PARAMS( conn, "r", _FN_, 0 );
|
PROCESS_PARAMS( conn, "r", _FN_, 0 );
|
||||||
|
|
||||||
// Return false if not in transaction
|
// Return false if not in transaction
|
||||||
CHECK_CUSTOM_ERROR(( conn->in_transaction == false ), *conn, SS_SQLSRV_ERROR_NOT_IN_TXN ) {
|
CHECK_CUSTOM_ERROR(( conn->in_transaction == false ), *conn, SS_SQLSRV_ERROR_NOT_IN_TXN ) {
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
conn->in_transaction = false;
|
conn->in_transaction = false;
|
||||||
core_sqlsrv_rollback( conn );
|
core_sqlsrv_rollback( conn );
|
||||||
RETURN_TRUE;
|
RETURN_TRUE;
|
||||||
|
@ -1002,7 +1002,7 @@ PHP_FUNCTION( sqlsrv_client_info )
|
||||||
LOG_FUNCTION( "sqlsrv_client_info" );
|
LOG_FUNCTION( "sqlsrv_client_info" );
|
||||||
ss_sqlsrv_conn* conn = NULL;
|
ss_sqlsrv_conn* conn = NULL;
|
||||||
PROCESS_PARAMS( conn, "r", _FN_, 0 );
|
PROCESS_PARAMS( conn, "r", _FN_, 0 );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
core_sqlsrv_get_client_info(conn, return_value);
|
core_sqlsrv_get_client_info(conn, return_value);
|
||||||
|
|
||||||
|
@ -1019,14 +1019,14 @@ PHP_FUNCTION( sqlsrv_client_info )
|
||||||
}
|
}
|
||||||
|
|
||||||
// sqlsrv_server_info( resource $conn )
|
// sqlsrv_server_info( resource $conn )
|
||||||
//
|
//
|
||||||
// Returns information about the server.
|
// Returns information about the server.
|
||||||
//
|
//
|
||||||
// Parameters
|
// Parameters
|
||||||
// $conn: The connection resource by which the client and server are connected.
|
// $conn: The connection resource by which the client and server are connected.
|
||||||
//
|
//
|
||||||
// Return Value
|
// Return Value
|
||||||
// An associative array with the following keys:
|
// An associative array with the following keys:
|
||||||
// CurrentDatabase
|
// CurrentDatabase
|
||||||
// The database currently being targeted.
|
// The database currently being targeted.
|
||||||
// SQLServerVersion
|
// SQLServerVersion
|
||||||
|
@ -1051,7 +1051,7 @@ PHP_FUNCTION( sqlsrv_server_info )
|
||||||
|
|
||||||
|
|
||||||
// sqlsrv_prepare( resource $conn, string $tsql [, array $params [, array $options]])
|
// sqlsrv_prepare( resource $conn, string $tsql [, array $params [, array $options]])
|
||||||
//
|
//
|
||||||
// Creates a statement resource associated with the specified connection. A statement
|
// Creates a statement resource associated with the specified connection. A statement
|
||||||
// resource returned by sqlsrv_prepare may be executed multiple times by sqlsrv_execute.
|
// resource returned by sqlsrv_prepare may be executed multiple times by sqlsrv_execute.
|
||||||
// In between each execution, the values may be updated by changing the value of the
|
// In between each execution, the values may be updated by changing the value of the
|
||||||
|
@ -1097,7 +1097,7 @@ PHP_FUNCTION( sqlsrv_prepare )
|
||||||
zval stmt_z;
|
zval stmt_z;
|
||||||
ZVAL_UNDEF(&stmt_z);
|
ZVAL_UNDEF(&stmt_z);
|
||||||
|
|
||||||
PROCESS_PARAMS( conn, "rs|a!a!", _FN_, 4, &sql, &sql_len, ¶ms_z, &options_z );
|
PROCESS_PARAMS( conn, "rs|a!a!", _FN_, 4, &sql, &sql_len, ¶ms_z, &options_z, NULL );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -1105,19 +1105,19 @@ PHP_FUNCTION( sqlsrv_prepare )
|
||||||
|
|
||||||
// Initialize the options array to be passed to the core layer
|
// Initialize the options array to be passed to the core layer
|
||||||
ALLOC_HASHTABLE( ss_stmt_options_ht );
|
ALLOC_HASHTABLE( ss_stmt_options_ht );
|
||||||
core::sqlsrv_zend_hash_init( *conn , ss_stmt_options_ht, 5 /* # of buckets */,
|
core::sqlsrv_zend_hash_init( *conn , ss_stmt_options_ht, 5 /* # of buckets */,
|
||||||
ZVAL_PTR_DTOR, 0 /*persistent*/ );
|
ZVAL_PTR_DTOR, 0 /*persistent*/ );
|
||||||
|
|
||||||
validate_stmt_options( *conn, options_z, ss_stmt_options_ht );
|
validate_stmt_options( *conn, options_z, ss_stmt_options_ht );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( params_z && Z_TYPE_P( params_z ) != IS_ARRAY ) {
|
if( params_z && Z_TYPE_P( params_z ) != IS_ARRAY ) {
|
||||||
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( options_z && Z_TYPE_P( options_z ) != IS_ARRAY ) {
|
if( options_z && Z_TYPE_P( options_z ) != IS_ARRAY ) {
|
||||||
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sql == NULL ) {
|
if( sql == NULL ) {
|
||||||
|
@ -1125,12 +1125,12 @@ PHP_FUNCTION( sqlsrv_prepare )
|
||||||
DIE( "sqlsrv_prepare: sql string was null." );
|
DIE( "sqlsrv_prepare: sql string was null." );
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt = static_cast<ss_sqlsrv_stmt*>( core_sqlsrv_create_stmt( conn, core::allocate_stmt<ss_sqlsrv_stmt>,
|
stmt = static_cast<ss_sqlsrv_stmt*>( core_sqlsrv_create_stmt( conn, core::allocate_stmt<ss_sqlsrv_stmt>,
|
||||||
ss_stmt_options_ht, SS_STMT_OPTS,
|
ss_stmt_options_ht, SS_STMT_OPTS,
|
||||||
ss_error_handler, NULL ) );
|
ss_error_handler, NULL ) );
|
||||||
|
|
||||||
core_sqlsrv_prepare( stmt, sql, sql_len );
|
core_sqlsrv_prepare( stmt, sql, sql_len );
|
||||||
|
|
||||||
if (params_z) {
|
if (params_z) {
|
||||||
stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval));
|
stmt->params_z = (zval *)sqlsrv_malloc(sizeof(zval));
|
||||||
ZVAL_COPY(stmt->params_z, params_z);
|
ZVAL_COPY(stmt->params_z, params_z);
|
||||||
|
@ -1138,27 +1138,27 @@ PHP_FUNCTION( sqlsrv_prepare )
|
||||||
|
|
||||||
stmt->prepared = true;
|
stmt->prepared = true;
|
||||||
|
|
||||||
// register the statement with the PHP runtime
|
// register the statement with the PHP runtime
|
||||||
ss::zend_register_resource( stmt_z, stmt, ss_sqlsrv_stmt::descriptor, ss_sqlsrv_stmt::resource_name );
|
ss::zend_register_resource( stmt_z, stmt, ss_sqlsrv_stmt::descriptor, ss_sqlsrv_stmt::resource_name );
|
||||||
|
|
||||||
// store the resource id with the connection so the connection
|
// store the resource id with the connection so the connection
|
||||||
// can release this statement when it closes.
|
// can release this statement when it closes.
|
||||||
zend_long next_index = zend_hash_next_free_element( conn->stmts );
|
zend_long next_index = zend_hash_next_free_element( conn->stmts );
|
||||||
|
|
||||||
core::sqlsrv_zend_hash_index_update(*conn, conn->stmts, next_index, &stmt_z);
|
core::sqlsrv_zend_hash_index_update(*conn, conn->stmts, next_index, &stmt_z);
|
||||||
|
|
||||||
stmt->conn_index = next_index;
|
stmt->conn_index = next_index;
|
||||||
|
|
||||||
// the statement is now registered with EG( regular_list )
|
// the statement is now registered with EG( regular_list )
|
||||||
stmt.transferred();
|
stmt.transferred();
|
||||||
|
|
||||||
RETURN_RES(Z_RES(stmt_z));
|
RETURN_RES(Z_RES(stmt_z));
|
||||||
|
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
|
||||||
if( stmt ) {
|
if( stmt ) {
|
||||||
|
|
||||||
stmt->conn = NULL;
|
stmt->conn = NULL;
|
||||||
stmt->~ss_sqlsrv_stmt();
|
stmt->~ss_sqlsrv_stmt();
|
||||||
}
|
}
|
||||||
|
@ -1176,7 +1176,7 @@ PHP_FUNCTION( sqlsrv_prepare )
|
||||||
}
|
}
|
||||||
|
|
||||||
// sqlsrv_query( resource $conn, string $tsql [, array $params [, array $options]])
|
// sqlsrv_query( resource $conn, string $tsql [, array $params [, array $options]])
|
||||||
//
|
//
|
||||||
// Creates a statement resource associated with the specified connection. The statement
|
// Creates a statement resource associated with the specified connection. The statement
|
||||||
// is immediately executed and may not be executed again using sqlsrv_execute.
|
// is immediately executed and may not be executed again using sqlsrv_execute.
|
||||||
//
|
//
|
||||||
|
@ -1215,11 +1215,11 @@ PHP_FUNCTION( sqlsrv_query )
|
||||||
hash_auto_ptr ss_stmt_options_ht;
|
hash_auto_ptr ss_stmt_options_ht;
|
||||||
size_t sql_len = 0;
|
size_t sql_len = 0;
|
||||||
zval* options_z = NULL;
|
zval* options_z = NULL;
|
||||||
zval* params_z = NULL;
|
zval* params_z = NULL;
|
||||||
zval stmt_z;
|
zval stmt_z;
|
||||||
ZVAL_UNDEF(&stmt_z);
|
ZVAL_UNDEF(&stmt_z);
|
||||||
|
|
||||||
PROCESS_PARAMS( conn, "rs|a!a!", _FN_, 4, &sql, &sql_len, ¶ms_z, &options_z );
|
PROCESS_PARAMS( conn, "rs|a!a!", _FN_, 4, &sql, &sql_len, ¶ms_z, &options_z, NULL );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -1228,18 +1228,18 @@ PHP_FUNCTION( sqlsrv_query )
|
||||||
|
|
||||||
// Initialize the options array to be passed to the core layer
|
// Initialize the options array to be passed to the core layer
|
||||||
ALLOC_HASHTABLE( ss_stmt_options_ht );
|
ALLOC_HASHTABLE( ss_stmt_options_ht );
|
||||||
core::sqlsrv_zend_hash_init( *conn , ss_stmt_options_ht, 5 /* # of buckets */, ZVAL_PTR_DTOR,
|
core::sqlsrv_zend_hash_init( *conn , ss_stmt_options_ht, 5 /* # of buckets */, ZVAL_PTR_DTOR,
|
||||||
0 /*persistent*/ );
|
0 /*persistent*/ );
|
||||||
|
|
||||||
validate_stmt_options( *conn, options_z, ss_stmt_options_ht );
|
validate_stmt_options( *conn, options_z, ss_stmt_options_ht );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( params_z && Z_TYPE_P( params_z ) != IS_ARRAY ) {
|
if( params_z && Z_TYPE_P( params_z ) != IS_ARRAY ) {
|
||||||
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( options_z && Z_TYPE_P( options_z ) != IS_ARRAY ) {
|
if( options_z && Z_TYPE_P( options_z ) != IS_ARRAY ) {
|
||||||
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_SS_ERROR( conn, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sql == NULL ) {
|
if( sql == NULL ) {
|
||||||
|
@ -1247,8 +1247,8 @@ PHP_FUNCTION( sqlsrv_query )
|
||||||
DIE( "sqlsrv_query: sql string was null." );
|
DIE( "sqlsrv_query: sql string was null." );
|
||||||
}
|
}
|
||||||
|
|
||||||
stmt = static_cast<ss_sqlsrv_stmt*>( core_sqlsrv_create_stmt( conn, core::allocate_stmt<ss_sqlsrv_stmt>,
|
stmt = static_cast<ss_sqlsrv_stmt*>( core_sqlsrv_create_stmt( conn, core::allocate_stmt<ss_sqlsrv_stmt>,
|
||||||
ss_stmt_options_ht, SS_STMT_OPTS,
|
ss_stmt_options_ht, SS_STMT_OPTS,
|
||||||
ss_error_handler, NULL ) );
|
ss_error_handler, NULL ) );
|
||||||
|
|
||||||
if( params_z ) {
|
if( params_z ) {
|
||||||
|
@ -1262,13 +1262,13 @@ PHP_FUNCTION( sqlsrv_query )
|
||||||
|
|
||||||
// execute the statement
|
// execute the statement
|
||||||
core_sqlsrv_execute( stmt, sql, static_cast<int>( sql_len ) );
|
core_sqlsrv_execute( stmt, sql, static_cast<int>( sql_len ) );
|
||||||
|
|
||||||
// register the statement with the PHP runtime
|
// register the statement with the PHP runtime
|
||||||
ss::zend_register_resource(stmt_z, stmt, ss_sqlsrv_stmt::descriptor, ss_sqlsrv_stmt::resource_name);
|
ss::zend_register_resource(stmt_z, stmt, ss_sqlsrv_stmt::descriptor, ss_sqlsrv_stmt::resource_name);
|
||||||
// store the resource id with the connection so the connection
|
// store the resource id with the connection so the connection
|
||||||
// can release this statement when it closes.
|
// can release this statement when it closes.
|
||||||
zend_ulong next_index = zend_hash_next_free_element( conn->stmts );
|
zend_ulong next_index = zend_hash_next_free_element( conn->stmts );
|
||||||
|
|
||||||
core::sqlsrv_zend_hash_index_update(*conn, conn->stmts, next_index, &stmt_z);
|
core::sqlsrv_zend_hash_index_update(*conn, conn->stmts, next_index, &stmt_z);
|
||||||
stmt->conn_index = next_index;
|
stmt->conn_index = next_index;
|
||||||
stmt.transferred();
|
stmt.transferred();
|
||||||
|
@ -1311,7 +1311,7 @@ void free_stmt_resource( _Inout_ zval* stmt_z )
|
||||||
|
|
||||||
// internal connection functions
|
// internal connection functions
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// must close all statement handles opened by this connection before closing the connection
|
// must close all statement handles opened by this connection before closing the connection
|
||||||
// no errors are returned, since close should always succeed
|
// no errors are returned, since close should always succeed
|
||||||
|
@ -1322,8 +1322,8 @@ void sqlsrv_conn_close_stmts( _Inout_ ss_sqlsrv_conn* conn )
|
||||||
SQLSRV_ASSERT(( conn->handle() != NULL ), "sqlsrv_conn_close_stmts: Connection handle is NULL. Trying to destroy an "
|
SQLSRV_ASSERT(( conn->handle() != NULL ), "sqlsrv_conn_close_stmts: Connection handle is NULL. Trying to destroy an "
|
||||||
"already destroyed connection.");
|
"already destroyed connection.");
|
||||||
SQLSRV_ASSERT(( conn->stmts ), "sqlsrv_conn_close_stmts: Connection doesn't contain a statement array." );
|
SQLSRV_ASSERT(( conn->stmts ), "sqlsrv_conn_close_stmts: Connection doesn't contain a statement array." );
|
||||||
|
|
||||||
// loop through the stmts hash table and destroy each stmt resource so we can close the
|
// loop through the stmts hash table and destroy each stmt resource so we can close the
|
||||||
// ODBC connection
|
// ODBC connection
|
||||||
|
|
||||||
zval* rsrc_ptr = NULL;
|
zval* rsrc_ptr = NULL;
|
||||||
|
@ -1368,16 +1368,16 @@ void sqlsrv_conn_close_stmts( _Inout_ ss_sqlsrv_conn* conn )
|
||||||
conn->stmts = NULL;
|
conn->stmts = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len, _Inout_ zval const* value_z )
|
int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len, _Inout_ zval const* value_z )
|
||||||
{
|
{
|
||||||
for( int i=0; SS_CONN_OPTS[i].conn_option_key != SQLSRV_CONN_OPTION_INVALID; ++i )
|
for( int i=0; SS_CONN_OPTS[i].conn_option_key != SQLSRV_CONN_OPTION_INVALID; ++i )
|
||||||
{
|
{
|
||||||
if( key_len == SS_CONN_OPTS[i].sqlsrv_len && !stricmp( ZSTR_VAL( key ), SS_CONN_OPTS[i].sqlsrv_name )) {
|
if( key_len == SS_CONN_OPTS[i].sqlsrv_len && !stricmp( ZSTR_VAL( key ), SS_CONN_OPTS[i].sqlsrv_name )) {
|
||||||
|
|
||||||
|
|
||||||
switch( SS_CONN_OPTS[i].value_type ) {
|
switch( SS_CONN_OPTS[i].value_type ) {
|
||||||
|
|
||||||
case CONN_ATTR_BOOL:
|
case CONN_ATTR_BOOL:
|
||||||
// bool attributes can be either strings to be appended to the connection string
|
// bool attributes can be either strings to be appended to the connection string
|
||||||
// as yes or no or integral connection attributes. This will have to be reworked
|
// as yes or no or integral connection attributes. This will have to be reworked
|
||||||
// if we ever introduce a boolean connection option that maps to a string connection
|
// if we ever introduce a boolean connection option that maps to a string connection
|
||||||
|
@ -1388,7 +1388,7 @@ int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In
|
||||||
case CONN_ATTR_INT:
|
case CONN_ATTR_INT:
|
||||||
{
|
{
|
||||||
CHECK_CUSTOM_ERROR( (Z_TYPE_P( value_z ) != IS_LONG ), ctx, SQLSRV_ERROR_INVALID_OPTION_TYPE_INT,
|
CHECK_CUSTOM_ERROR( (Z_TYPE_P( value_z ) != IS_LONG ), ctx, SQLSRV_ERROR_INVALID_OPTION_TYPE_INT,
|
||||||
SS_CONN_OPTS[i].sqlsrv_name )
|
SS_CONN_OPTS[i].sqlsrv_name, NULL)
|
||||||
{
|
{
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
@ -1396,8 +1396,8 @@ int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In
|
||||||
}
|
}
|
||||||
case CONN_ATTR_STRING:
|
case CONN_ATTR_STRING:
|
||||||
{
|
{
|
||||||
CHECK_CUSTOM_ERROR( Z_TYPE_P( value_z ) != IS_STRING, ctx, SQLSRV_ERROR_INVALID_OPTION_TYPE_STRING,
|
CHECK_CUSTOM_ERROR( Z_TYPE_P( value_z ) != IS_STRING, ctx, SQLSRV_ERROR_INVALID_OPTION_TYPE_STRING,
|
||||||
SS_CONN_OPTS[i].sqlsrv_name ) {
|
SS_CONN_OPTS[i].sqlsrv_name, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
@ -1406,7 +1406,7 @@ int get_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In
|
||||||
size_t value_len = Z_STRLEN_P( value_z );
|
size_t value_len = Z_STRLEN_P( value_z );
|
||||||
bool escaped = core_is_conn_opt_value_escaped( value, value_len );
|
bool escaped = core_is_conn_opt_value_escaped( value, value_len );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR( !escaped, ctx, SS_SQLSRV_ERROR_CONNECT_BRACES_NOT_ESCAPED, SS_CONN_OPTS[i].sqlsrv_name ) {
|
CHECK_CUSTOM_ERROR( !escaped, ctx, SS_SQLSRV_ERROR_CONNECT_BRACES_NOT_ESCAPED, SS_CONN_OPTS[i].sqlsrv_name, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
@ -1435,34 +1435,34 @@ int get_stmt_option_key( _In_ zend_string* key, _In_ size_t key_len )
|
||||||
return SQLSRV_STMT_OPTION_INVALID;
|
return SQLSRV_STMT_OPTION_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len,
|
void add_stmt_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len,
|
||||||
_Inout_ HashTable* options_ht, _Inout_ zval* data )
|
_Inout_ HashTable* options_ht, _Inout_ zval* data )
|
||||||
{
|
{
|
||||||
int option_key = ::get_stmt_option_key( key, key_len );
|
int option_key = ::get_stmt_option_key( key, key_len );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR((option_key == SQLSRV_STMT_OPTION_INVALID ), ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, ZSTR_VAL( key ) ) {
|
CHECK_CUSTOM_ERROR((option_key == SQLSRV_STMT_OPTION_INVALID ), ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, ZSTR_VAL( key ), NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Z_TRY_ADDREF_P(data); // inc the ref count since this is going into the options_ht too.
|
Z_TRY_ADDREF_P(data); // inc the ref count since this is going into the options_ht too.
|
||||||
core::sqlsrv_zend_hash_index_update( ctx, options_ht, option_key, data );
|
core::sqlsrv_zend_hash_index_update( ctx, options_ht, option_key, data );
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len,
|
void add_conn_option_key( _Inout_ sqlsrv_context& ctx, _In_ zend_string* key, _In_ size_t key_len,
|
||||||
_Inout_ HashTable* options_ht, _Inout_ zval* data )
|
_Inout_ HashTable* options_ht, _Inout_ zval* data )
|
||||||
{
|
{
|
||||||
int option_key = ::get_conn_option_key( ctx, key, key_len, data );
|
int option_key = ::get_conn_option_key( ctx, key, key_len, data );
|
||||||
CHECK_CUSTOM_ERROR((option_key == SQLSRV_STMT_OPTION_INVALID ), ctx, SS_SQLSRV_ERROR_INVALID_OPTION, ZSTR_VAL( key ) ) {
|
CHECK_CUSTOM_ERROR((option_key == SQLSRV_STMT_OPTION_INVALID ), ctx, SS_SQLSRV_ERROR_INVALID_OPTION, ZSTR_VAL( key ), NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
Z_TRY_ADDREF_P(data); // inc the ref count since this is going into the options_ht too.
|
Z_TRY_ADDREF_P(data); // inc the ref count since this is going into the options_ht too.
|
||||||
core::sqlsrv_zend_hash_index_update( ctx, options_ht, option_key, data );
|
core::sqlsrv_zend_hash_index_update( ctx, options_ht, option_key, data );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterates through the list of statement options provided by the user and validates them
|
// Iterates through the list of statement options provided by the user and validates them
|
||||||
// against the list of supported statement options by this driver. After validation
|
// against the list of supported statement options by this driver. After validation
|
||||||
// creates a Hashtable of statement options to be sent to the core layer for processing.
|
// creates a Hashtable of statement options to be sent to the core layer for processing.
|
||||||
|
|
||||||
|
@ -1470,7 +1470,7 @@ void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_opti
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if( stmt_options ) {
|
if( stmt_options ) {
|
||||||
|
|
||||||
HashTable* options_ht = Z_ARRVAL_P( stmt_options );
|
HashTable* options_ht = Z_ARRVAL_P( stmt_options );
|
||||||
zend_ulong int_key = -1;
|
zend_ulong int_key = -1;
|
||||||
zend_string *key = NULL;
|
zend_string *key = NULL;
|
||||||
|
@ -1482,7 +1482,7 @@ void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_opti
|
||||||
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
|
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
|
||||||
|
|
||||||
if (type != HASH_KEY_IS_STRING) {
|
if (type != HASH_KEY_IS_STRING) {
|
||||||
CHECK_CUSTOM_ERROR(true, ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, std::to_string( int_key ).c_str() ) {
|
CHECK_CUSTOM_ERROR(true, ctx, SQLSRV_ERROR_INVALID_OPTION_KEY, std::to_string( int_key ).c_str(), NULL) {
|
||||||
throw core::CoreException();
|
throw core::CoreException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1502,7 +1502,7 @@ void validate_stmt_options( _Inout_ sqlsrv_context& ctx, _Inout_ zval* stmt_opti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterates through the list of connection options provided by the user and validates them
|
// Iterates through the list of connection options provided by the user and validates them
|
||||||
// against the predefined list of supported connection options by this driver. After validation
|
// against the predefined list of supported connection options by this driver. After validation
|
||||||
// creates a Hashtable of connection options to be sent to the core layer for processing.
|
// creates a Hashtable of connection options to be sent to the core layer for processing.
|
||||||
|
|
||||||
|
@ -1520,7 +1520,7 @@ void validate_conn_options( _Inout_ sqlsrv_context& ctx, _In_ zval* user_options
|
||||||
int type = HASH_KEY_NON_EXISTENT;
|
int type = HASH_KEY_NON_EXISTENT;
|
||||||
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
|
type = key ? HASH_KEY_IS_STRING : HASH_KEY_IS_LONG;
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( Z_TYPE_P( data ) == IS_NULL || Z_TYPE_P( data ) == IS_UNDEF ), ctx, SS_SQLSRV_ERROR_INVALID_OPTION, key) {
|
CHECK_CUSTOM_ERROR(( Z_TYPE_P( data ) == IS_NULL || Z_TYPE_P( data ) == IS_UNDEF ), ctx, SS_SQLSRV_ERROR_INVALID_OPTION, key, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1548,7 +1548,7 @@ void validate_conn_options( _Inout_ sqlsrv_context& ctx, _In_ zval* user_options
|
||||||
DIE( "validate_conn_options: key was null." );
|
DIE( "validate_conn_options: key was null." );
|
||||||
}
|
}
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
throw;
|
throw;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// File: init.cpp
|
// File: init.cpp
|
||||||
// Contents: initialization routines for the extension
|
// Contents: initialization routines for the extension
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
//
|
//
|
||||||
// Comments: Also contains "internal" declarations shared across source files.
|
// Comments: Also contains "internal" declarations shared across source files.
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -6,19 +6,19 @@
|
||||||
//
|
//
|
||||||
// Contents: Internal declarations for the extension
|
// Contents: Internal declarations for the extension
|
||||||
//
|
//
|
||||||
// Comments: Also contains "internal" declarations shared across source files.
|
// Comments: Also contains "internal" declarations shared across source files.
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
|
// 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,
|
// 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 :
|
// 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 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,
|
// 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
|
// 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
|
// 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.
|
// IN THE SOFTWARE.
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -44,9 +44,9 @@
|
||||||
PHP_INI_BEGIN()
|
PHP_INI_BEGIN()
|
||||||
STD_PHP_INI_BOOLEAN( INI_PREFIX INI_WARNINGS_RETURN_AS_ERRORS , "1", PHP_INI_ALL, OnUpdateBool, warnings_return_as_errors,
|
STD_PHP_INI_BOOLEAN( INI_PREFIX INI_WARNINGS_RETURN_AS_ERRORS , "1", PHP_INI_ALL, OnUpdateBool, warnings_return_as_errors,
|
||||||
zend_sqlsrv_globals, sqlsrv_globals )
|
zend_sqlsrv_globals, sqlsrv_globals )
|
||||||
STD_PHP_INI_ENTRY( INI_PREFIX INI_LOG_SEVERITY, "0", PHP_INI_ALL, OnUpdateLong, log_severity, zend_sqlsrv_globals,
|
STD_PHP_INI_ENTRY( INI_PREFIX INI_LOG_SEVERITY, "0", PHP_INI_ALL, OnUpdateLong, log_severity, zend_sqlsrv_globals,
|
||||||
sqlsrv_globals )
|
sqlsrv_globals )
|
||||||
STD_PHP_INI_ENTRY( INI_PREFIX INI_LOG_SUBSYSTEMS, "0", PHP_INI_ALL, OnUpdateLong, log_subsystems, zend_sqlsrv_globals,
|
STD_PHP_INI_ENTRY( INI_PREFIX INI_LOG_SUBSYSTEMS, "0", PHP_INI_ALL, OnUpdateLong, log_subsystems, zend_sqlsrv_globals,
|
||||||
sqlsrv_globals )
|
sqlsrv_globals )
|
||||||
STD_PHP_INI_ENTRY( INI_PREFIX INI_BUFFERED_QUERY_LIMIT, INI_BUFFERED_QUERY_LIMIT_DEFAULT, PHP_INI_ALL, OnUpdateLong, buffered_query_limit,
|
STD_PHP_INI_ENTRY( INI_PREFIX INI_BUFFERED_QUERY_LIMIT, INI_BUFFERED_QUERY_LIMIT_DEFAULT, PHP_INI_ALL, OnUpdateLong, buffered_query_limit,
|
||||||
zend_sqlsrv_globals, sqlsrv_globals )
|
zend_sqlsrv_globals, sqlsrv_globals )
|
||||||
|
@ -85,13 +85,13 @@ struct ss_sqlsrv_conn : sqlsrv_conn
|
||||||
bool format_decimals; // flag set to turn on formatting for values of decimal / numeric types
|
bool format_decimals; // flag set to turn on formatting for values of decimal / numeric types
|
||||||
short decimal_places; // number of decimal digits to show in a result set unless format_numbers is false
|
short decimal_places; // number of decimal digits to show in a result set unless format_numbers is false
|
||||||
bool in_transaction; // flag set when inside a transaction and used for checking validity of tran API calls
|
bool in_transaction; // flag set when inside a transaction and used for checking validity of tran API calls
|
||||||
|
|
||||||
// static variables used in process_params
|
// static variables used in process_params
|
||||||
static const char* resource_name;
|
static const char* resource_name;
|
||||||
static int descriptor;
|
static int descriptor;
|
||||||
|
|
||||||
// initialize with default values
|
// initialize with default values
|
||||||
ss_sqlsrv_conn( _In_ SQLHANDLE h, _In_ error_callback e, _In_ void* drv ) :
|
ss_sqlsrv_conn( _In_ SQLHANDLE h, _In_ error_callback e, _In_ void* drv ) :
|
||||||
sqlsrv_conn( h, e, drv, SQLSRV_ENCODING_SYSTEM ),
|
sqlsrv_conn( h, e, drv, SQLSRV_ENCODING_SYSTEM ),
|
||||||
stmts( NULL ),
|
stmts( NULL ),
|
||||||
date_as_string( false ),
|
date_as_string( false ),
|
||||||
|
@ -125,7 +125,7 @@ struct ss_sqlsrv_stmt : public sqlsrv_stmt {
|
||||||
|
|
||||||
virtual ~ss_sqlsrv_stmt( void );
|
virtual ~ss_sqlsrv_stmt( void );
|
||||||
|
|
||||||
void new_result_set( void );
|
void new_result_set( void );
|
||||||
|
|
||||||
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
|
// driver specific conversion rules from a SQL Server/ODBC type to one of the SQLSRV_PHPTYPE_* constants
|
||||||
sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream );
|
sqlsrv_phptype sql_type_to_php_type( _In_ SQLINTEGER sql_type, _In_ SQLUINTEGER size, _In_ bool prefer_string_to_stream );
|
||||||
|
@ -164,7 +164,7 @@ void __cdecl sqlsrv_stmt_dtor( _Inout_ zend_resource *rsrc );
|
||||||
|
|
||||||
// "internal" statement functions shared by functions in conn.cpp and stmt.cpp
|
// "internal" statement functions shared by functions in conn.cpp and stmt.cpp
|
||||||
void bind_params( _Inout_ ss_sqlsrv_stmt* stmt );
|
void bind_params( _Inout_ ss_sqlsrv_stmt* stmt );
|
||||||
bool sqlsrv_stmt_common_execute( sqlsrv_stmt* s, const SQLCHAR* sql_string, int sql_len, bool direct, const char* function
|
bool sqlsrv_stmt_common_execute( sqlsrv_stmt* s, const SQLCHAR* sql_string, int sql_len, bool direct, const char* function
|
||||||
);
|
);
|
||||||
void free_odbc_resources( ss_sqlsrv_stmt* stmt );
|
void free_odbc_resources( ss_sqlsrv_stmt* stmt );
|
||||||
void free_stmt_resource( _Inout_ zval* stmt_z );
|
void free_stmt_resource( _Inout_ zval* stmt_z );
|
||||||
|
@ -183,12 +183,12 @@ struct ss_error {
|
||||||
|
|
||||||
// List of all driver specific error codes.
|
// List of all driver specific error codes.
|
||||||
enum SS_ERROR_CODES {
|
enum SS_ERROR_CODES {
|
||||||
|
|
||||||
SS_SQLSRV_ERROR_ALREADY_IN_TXN = SQLSRV_ERROR_DRIVER_SPECIFIC,
|
SS_SQLSRV_ERROR_ALREADY_IN_TXN = SQLSRV_ERROR_DRIVER_SPECIFIC,
|
||||||
SS_SQLSRV_ERROR_NOT_IN_TXN,
|
SS_SQLSRV_ERROR_NOT_IN_TXN,
|
||||||
SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER,
|
SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER,
|
||||||
SS_SQLSRV_ERROR_REGISTER_RESOURCE,
|
SS_SQLSRV_ERROR_REGISTER_RESOURCE,
|
||||||
SS_SQLSRV_ERROR_INVALID_CONNECTION_KEY,
|
SS_SQLSRV_ERROR_INVALID_CONNECTION_KEY,
|
||||||
SS_SQLSRV_ERROR_STATEMENT_NOT_PREPARED,
|
SS_SQLSRV_ERROR_STATEMENT_NOT_PREPARED,
|
||||||
SS_SQLSRV_ERROR_INVALID_FETCH_STYLE,
|
SS_SQLSRV_ERROR_INVALID_FETCH_STYLE,
|
||||||
SS_SQLSRV_ERROR_INVALID_FETCH_TYPE,
|
SS_SQLSRV_ERROR_INVALID_FETCH_TYPE,
|
||||||
|
@ -227,9 +227,9 @@ SQLWCHAR* utf16_string_from_mbcs_string( _In_ unsigned int php_encoding, _In_rea
|
||||||
_In_ unsigned int mbcs_len, _Out_ unsigned int* utf16_len, bool use_strict_conversion = false );
|
_In_ unsigned int mbcs_len, _Out_ unsigned int* utf16_len, bool use_strict_conversion = false );
|
||||||
|
|
||||||
// *** internal error macros and functions ***
|
// *** internal error macros and functions ***
|
||||||
bool handle_error( sqlsrv_context const* ctx, int log_subsystem, const char* function,
|
bool handle_error( sqlsrv_context const* ctx, int log_subsystem, const char* function,
|
||||||
sqlsrv_error const* ssphp, ... );
|
sqlsrv_error const* ssphp, ... );
|
||||||
void handle_warning( sqlsrv_context const* ctx, int log_subsystem, const char* function,
|
void handle_warning( sqlsrv_context const* ctx, int log_subsystem, const char* function,
|
||||||
sqlsrv_error const* ssphp, ... );
|
sqlsrv_error const* ssphp, ... );
|
||||||
void __cdecl sqlsrv_error_dtor( zend_resource *rsrc );
|
void __cdecl sqlsrv_error_dtor( zend_resource *rsrc );
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ public:
|
||||||
const char* _FN_ = function_name; \
|
const char* _FN_ = function_name; \
|
||||||
SQLSRV_G( current_subsystem ) = current_log_subsystem; \
|
SQLSRV_G( current_subsystem ) = current_log_subsystem; \
|
||||||
core_sqlsrv_register_severity_checker(ss_severity_check); \
|
core_sqlsrv_register_severity_checker(ss_severity_check); \
|
||||||
LOG(SEV_NOTICE, "%1!s!: entering", _FN_);
|
LOG(SEV_NOTICE, "%1!s!: entering", _FN_);
|
||||||
|
|
||||||
// check the global variables of sqlsrv severity whether the message qualifies to be logged with the LOG macro
|
// check the global variables of sqlsrv severity whether the message qualifies to be logged with the LOG macro
|
||||||
bool ss_severity_check(_In_ unsigned int severity);
|
bool ss_severity_check(_In_ unsigned int severity);
|
||||||
|
@ -323,7 +323,7 @@ enum logging_subsystems {
|
||||||
|
|
||||||
|
|
||||||
//*********************************************************************************************************************************
|
//*********************************************************************************************************************************
|
||||||
// Common function wrappers
|
// Common function wrappers
|
||||||
// have to place this namespace before the utility functions
|
// have to place this namespace before the utility functions
|
||||||
// otherwise can't compile in Linux because 'ss' not defined
|
// otherwise can't compile in Linux because 'ss' not defined
|
||||||
//*********************************************************************************************************************************
|
//*********************************************************************************************************************************
|
||||||
|
@ -342,7 +342,7 @@ namespace ss {
|
||||||
{
|
{
|
||||||
int zr = (NULL != (Z_RES(rsrc_result) = ::zend_register_resource(rsrc_pointer, rsrc_type)) ? SUCCESS : FAILURE);
|
int zr = (NULL != (Z_RES(rsrc_result) = ::zend_register_resource(rsrc_pointer, rsrc_type)) ? SUCCESS : FAILURE);
|
||||||
CHECK_CUSTOM_ERROR(( zr == FAILURE ), reinterpret_cast<sqlsrv_context*>( rsrc_pointer ), SS_SQLSRV_ERROR_REGISTER_RESOURCE,
|
CHECK_CUSTOM_ERROR(( zr == FAILURE ), reinterpret_cast<sqlsrv_context*>( rsrc_pointer ), SS_SQLSRV_ERROR_REGISTER_RESOURCE,
|
||||||
rsrc_name ) {
|
rsrc_name, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
Z_TYPE_INFO(rsrc_result) = IS_RESOURCE_EX;
|
Z_TYPE_INFO(rsrc_result) = IS_RESOURCE_EX;
|
||||||
|
@ -363,7 +363,7 @@ inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, _In_ char const* param_s
|
||||||
|
|
||||||
zval* rsrc;
|
zval* rsrc;
|
||||||
H* h = NULL;
|
H* h = NULL;
|
||||||
|
|
||||||
// reset the errors from the previous API call
|
// reset the errors from the previous API call
|
||||||
reset_errors();
|
reset_errors();
|
||||||
|
|
||||||
|
@ -384,14 +384,14 @@ inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, _In_ char const* param_s
|
||||||
va_start(vaList, param_count); //set the pointer to first argument
|
va_start(vaList, param_count); //set the pointer to first argument
|
||||||
|
|
||||||
for(size_t i = 0; i < param_count; ++i) {
|
for(size_t i = 0; i < param_count; ++i) {
|
||||||
|
|
||||||
arr[i] = va_arg(vaList, void*);
|
arr[i] = va_arg(vaList, void*);
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end(vaList);
|
va_end(vaList);
|
||||||
|
|
||||||
int result = SUCCESS;
|
int result = SUCCESS;
|
||||||
|
|
||||||
// dummy context to pass to the error handler
|
// dummy context to pass to the error handler
|
||||||
sqlsrv_context error_ctx( 0, ss_error_handler, NULL );
|
sqlsrv_context error_ctx( 0, ss_error_handler, NULL );
|
||||||
error_ctx.set_func( calling_func );
|
error_ctx.set_func( calling_func );
|
||||||
|
@ -403,50 +403,50 @@ inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, _In_ char const* param_s
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0] );
|
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
||||||
arr[1] );
|
arr[1] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
||||||
arr[1], arr[2] );
|
arr[1], arr[2] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
||||||
arr[1], arr[2], arr[3] );
|
arr[1], arr[2], arr[3] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
||||||
arr[1], arr[2], arr[3], arr[4] );
|
arr[1], arr[2], arr[3], arr[4] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6:
|
case 6:
|
||||||
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
result = zend_parse_parameters( ZEND_NUM_ARGS(), const_cast<char*>( param_spec ), &rsrc, arr[0],
|
||||||
arr[1], arr[2], arr[3], arr[4], arr[5] );
|
arr[1], arr[2], arr[3], arr[4], arr[5] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func );
|
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func, NULL );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( result == FAILURE ), &error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func ) {
|
CHECK_CUSTOM_ERROR(( result == FAILURE ), &error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the resource registered
|
// get the resource registered
|
||||||
h = static_cast<H*>( zend_fetch_resource(Z_RES_P(rsrc), H::resource_name, H::descriptor ));
|
h = static_cast<H*>( zend_fetch_resource(Z_RES_P(rsrc), H::resource_name, H::descriptor ));
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( h == NULL ), &error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func ) {
|
CHECK_CUSTOM_ERROR(( h == NULL ), &error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, calling_func, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
@ -455,11 +455,11 @@ inline H* process_params( INTERNAL_FUNCTION_PARAMETERS, _In_ char const* param_s
|
||||||
}
|
}
|
||||||
|
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
catch ( ... ) {
|
catch ( ... ) {
|
||||||
|
|
||||||
DIE( "%1!s!: Unknown exception caught in process_params.", calling_func );
|
DIE( "%1!s!: Unknown exception caught in process_params.", calling_func );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Routines that use statement handles
|
// Contents: Routines that use statement handles
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
@ -100,8 +100,8 @@ void type_and_encoding( INTERNAL_FUNCTION_PARAMETERS, _In_ int type );
|
||||||
void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type );
|
void type_and_size_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type );
|
||||||
void type_and_precision_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type );
|
void type_and_precision_calc( INTERNAL_FUNCTION_PARAMETERS, _In_ int type );
|
||||||
bool verify_and_set_encoding( _In_ const char* encoding_string, _Inout_ sqlsrv_phptype& phptype_encoding );
|
bool verify_and_set_encoding( _In_ const char* encoding_string, _Inout_ sqlsrv_phptype& phptype_encoding );
|
||||||
zval* parse_param_array(_Inout_ ss_sqlsrv_stmt* stmt, _Inout_ HashTable* param_ht, zend_ulong index,
|
zval* parse_param_array(_Inout_ ss_sqlsrv_stmt* stmt, _Inout_ HashTable* param_ht, zend_ulong index,
|
||||||
_Out_ SQLSMALLINT& direction, _Out_ SQLSRV_PHPTYPE& php_out_type,
|
_Out_ SQLSMALLINT& direction, _Out_ SQLSRV_PHPTYPE& php_out_type,
|
||||||
_Out_ SQLSRV_ENCODING& encoding, _Out_ SQLSMALLINT& sql_type,
|
_Out_ SQLSRV_ENCODING& encoding, _Out_ SQLSMALLINT& sql_type,
|
||||||
_Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits);
|
_Out_ SQLULEN& column_size, _Out_ SQLSMALLINT& decimal_digits);
|
||||||
|
|
||||||
|
@ -341,7 +341,7 @@ PHP_FUNCTION( sqlsrv_fetch )
|
||||||
zend_long fetch_offset = 0; // default value for parameter if one isn't supplied
|
zend_long fetch_offset = 0; // default value for parameter if one isn't supplied
|
||||||
|
|
||||||
// take only the statement resource
|
// take only the statement resource
|
||||||
PROCESS_PARAMS( stmt, "r|ll", _FN_, 2, &fetch_style, &fetch_offset );
|
PROCESS_PARAMS( stmt, "r|ll", _FN_, 2, &fetch_style, &fetch_offset, NULL );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ PHP_FUNCTION( sqlsrv_fetch_array )
|
||||||
|
|
||||||
// retrieve the statement resource and optional fetch type (see enum SQLSRV_FETCH_TYPE),
|
// retrieve the statement resource and optional fetch type (see enum SQLSRV_FETCH_TYPE),
|
||||||
// fetch style (see SQLSRV_SCROLL_* constants) and fetch offset
|
// fetch style (see SQLSRV_SCROLL_* constants) and fetch offset
|
||||||
PROCESS_PARAMS( stmt, "r|lll", _FN_, 3, &fetch_type, &fetch_style, &fetch_offset );
|
PROCESS_PARAMS( stmt, "r|lll", _FN_, 3, &fetch_type, &fetch_style, &fetch_offset, NULL );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -786,7 +786,7 @@ PHP_FUNCTION( sqlsrv_fetch_object )
|
||||||
// fetch style (see SQLSRV_SCROLL_* constants) and fetch offset
|
// fetch style (see SQLSRV_SCROLL_* constants) and fetch offset
|
||||||
// we also use z! instead of s and a so that null may be passed in as valid values for
|
// we also use z! instead of s and a so that null may be passed in as valid values for
|
||||||
// the class name and ctor params
|
// the class name and ctor params
|
||||||
PROCESS_PARAMS( stmt, "r|z!z!ll", _FN_, 4, &class_name_z, &ctor_params_z, &fetch_style, &fetch_offset );
|
PROCESS_PARAMS( stmt, "r|z!z!ll", _FN_, 4, &class_name_z, &ctor_params_z, &fetch_style, &fetch_offset, NULL );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -797,7 +797,7 @@ PHP_FUNCTION( sqlsrv_fetch_object )
|
||||||
|
|
||||||
if( class_name_z ) {
|
if( class_name_z ) {
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( Z_TYPE_P( class_name_z ) != IS_STRING ), stmt, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
|
CHECK_CUSTOM_ERROR(( Z_TYPE_P( class_name_z ) != IS_STRING ), stmt, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
class_name = Z_STRVAL( *class_name_z );
|
class_name = Z_STRVAL( *class_name_z );
|
||||||
|
@ -805,7 +805,7 @@ PHP_FUNCTION( sqlsrv_fetch_object )
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ctor_params_z && Z_TYPE_P( ctor_params_z ) != IS_ARRAY ) {
|
if( ctor_params_z && Z_TYPE_P( ctor_params_z ) != IS_ARRAY ) {
|
||||||
THROW_SS_ERROR( stmt, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_SS_ERROR( stmt, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch the data
|
// fetch the data
|
||||||
|
@ -822,14 +822,14 @@ PHP_FUNCTION( sqlsrv_fetch_object )
|
||||||
zend_string* class_name_str_z = zend_string_init( class_name, class_name_len, 0 );
|
zend_string* class_name_str_z = zend_string_init( class_name, class_name_len, 0 );
|
||||||
int zr = ( NULL != ( class_entry = zend_lookup_class( class_name_str_z ))) ? SUCCESS : FAILURE;
|
int zr = ( NULL != ( class_entry = zend_lookup_class( class_name_str_z ))) ? SUCCESS : FAILURE;
|
||||||
zend_string_release( class_name_str_z );
|
zend_string_release( class_name_str_z );
|
||||||
CHECK_ZEND_ERROR( zr, stmt, SS_SQLSRV_ERROR_ZEND_BAD_CLASS, class_name ) {
|
CHECK_ZEND_ERROR( zr, stmt, SS_SQLSRV_ERROR_ZEND_BAD_CLASS, class_name, NULL ) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an instance of the object with its default properties
|
// create an instance of the object with its default properties
|
||||||
// we pass NULL for the properties so that the object will be populated by its default properties
|
// we pass NULL for the properties so that the object will be populated by its default properties
|
||||||
zr = object_and_properties_init( &retval_z, class_entry, NULL /*properties*/ );
|
zr = object_and_properties_init( &retval_z, class_entry, NULL /*properties*/ );
|
||||||
CHECK_ZEND_ERROR( zr, stmt, SS_SQLSRV_ERROR_ZEND_OBJECT_FAILED, class_name ) {
|
CHECK_ZEND_ERROR( zr, stmt, SS_SQLSRV_ERROR_ZEND_OBJECT_FAILED, class_name, NULL ) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -872,7 +872,7 @@ PHP_FUNCTION( sqlsrv_fetch_object )
|
||||||
zval* value_z = NULL;
|
zval* value_z = NULL;
|
||||||
ZEND_HASH_FOREACH_VAL( ctor_params_ht, value_z ) {
|
ZEND_HASH_FOREACH_VAL( ctor_params_ht, value_z ) {
|
||||||
zr = ( value_z ) ? SUCCESS : FAILURE;
|
zr = ( value_z ) ? SUCCESS : FAILURE;
|
||||||
CHECK_ZEND_ERROR( zr, stmt, SS_SQLSRV_ERROR_ZEND_OBJECT_FAILED, class_name ) {
|
CHECK_ZEND_ERROR( zr, stmt, SS_SQLSRV_ERROR_ZEND_OBJECT_FAILED, class_name, NULL ) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
ZVAL_COPY_VALUE(¶ms_m[i], value_z);
|
ZVAL_COPY_VALUE(¶ms_m[i], value_z);
|
||||||
|
@ -906,7 +906,7 @@ PHP_FUNCTION( sqlsrv_fetch_object )
|
||||||
fcic.object = Z_OBJ_P( &retval_z );
|
fcic.object = Z_OBJ_P( &retval_z );
|
||||||
|
|
||||||
zr = zend_call_function( &fci, &fcic );
|
zr = zend_call_function( &fci, &fcic );
|
||||||
CHECK_ZEND_ERROR( zr, stmt, SS_SQLSRV_ERROR_ZEND_OBJECT_FAILED, class_name ) {
|
CHECK_ZEND_ERROR( zr, stmt, SS_SQLSRV_ERROR_ZEND_OBJECT_FAILED, class_name, NULL ) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1083,7 +1083,7 @@ PHP_FUNCTION( sqlsrv_get_field )
|
||||||
ZVAL_UNDEF(&retval_z);
|
ZVAL_UNDEF(&retval_z);
|
||||||
|
|
||||||
// get the statement, the field index and the optional type
|
// get the statement, the field index and the optional type
|
||||||
PROCESS_PARAMS( stmt, "rl|l", _FN_, 2, &field_index, &sqlsrv_php_type );
|
PROCESS_PARAMS( stmt, "rl|l", _FN_, 2, &field_index, &sqlsrv_php_type, NULL );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -1091,7 +1091,7 @@ PHP_FUNCTION( sqlsrv_get_field )
|
||||||
SQLSMALLINT num_cols = get_resultset_meta_data(stmt);
|
SQLSMALLINT num_cols = get_resultset_meta_data(stmt);
|
||||||
|
|
||||||
if( field_index < 0 || field_index >= num_cols ) {
|
if( field_index < 0 || field_index >= num_cols ) {
|
||||||
THROW_SS_ERROR( stmt, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_SS_ERROR( stmt, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
core_sqlsrv_get_field( stmt, static_cast<SQLUSMALLINT>( field_index ), sqlsrv_php_type, false, field_value, &field_len, false/*cache_field*/,
|
core_sqlsrv_get_field( stmt, static_cast<SQLUSMALLINT>( field_index ), sqlsrv_php_type, false, field_value, &field_len, false/*cache_field*/,
|
||||||
|
@ -1227,7 +1227,7 @@ void bind_params( _Inout_ ss_sqlsrv_stmt* stmt )
|
||||||
// Simply get the first variable and use the defaults
|
// Simply get the first variable and use the defaults
|
||||||
value_z = zend_hash_index_find(param_ht, 0);
|
value_z = zend_hash_index_find(param_ht, 0);
|
||||||
if (value_z == NULL) {
|
if (value_z == NULL) {
|
||||||
THROW_SS_ERROR(stmt, SS_SQLSRV_ERROR_VAR_REQUIRED, index + 1);
|
THROW_SS_ERROR(stmt, SS_SQLSRV_ERROR_VAR_REQUIRED, index + 1, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (core::CoreException&) {
|
} catch (core::CoreException&) {
|
||||||
|
@ -1300,7 +1300,7 @@ PHP_FUNCTION( sqlsrv_cancel )
|
||||||
close_active_stream( stmt );
|
close_active_stream( stmt );
|
||||||
|
|
||||||
SQLRETURN r = SQLCancel( stmt->handle() );
|
SQLRETURN r = SQLCancel( stmt->handle() );
|
||||||
CHECK_SQL_ERROR_OR_WARNING( r, stmt ) {
|
CHECK_SQL_ERROR_OR_WARNING( r, stmt, NULL ) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1375,7 +1375,7 @@ PHP_FUNCTION( sqlsrv_free_stmt )
|
||||||
|
|
||||||
// Check if it was a zval
|
// Check if it was a zval
|
||||||
int zr = zend_parse_parameters( ZEND_NUM_ARGS(), "z", &stmt_r );
|
int zr = zend_parse_parameters( ZEND_NUM_ARGS(), "z", &stmt_r );
|
||||||
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
|
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
@ -1386,7 +1386,7 @@ PHP_FUNCTION( sqlsrv_free_stmt )
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1402,7 +1402,7 @@ PHP_FUNCTION( sqlsrv_free_stmt )
|
||||||
|
|
||||||
if( stmt == NULL ) {
|
if( stmt == NULL ) {
|
||||||
|
|
||||||
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete the resource from Zend's master list, which will trigger the statement's destructor
|
// delete the resource from Zend's master list, which will trigger the statement's destructor
|
||||||
|
@ -1774,7 +1774,7 @@ void determine_stmt_has_rows( _Inout_ ss_sqlsrv_stmt* stmt )
|
||||||
if( SQL_SUCCEEDED( r )) {
|
if( SQL_SUCCEEDED( r )) {
|
||||||
|
|
||||||
stmt->has_rows = true;
|
stmt->has_rows = true;
|
||||||
CHECK_SQL_WARNING( r, stmt );
|
CHECK_SQL_WARNING( r, stmt, NULL );
|
||||||
// restore the cursor to its original position.
|
// restore the cursor to its original position.
|
||||||
r = stmt->current_results->fetch( SQL_FETCH_ABSOLUTE, 0 );
|
r = stmt->current_results->fetch( SQL_FETCH_ABSOLUTE, 0 );
|
||||||
SQLSRV_ASSERT(( r == SQL_NO_DATA ), "core_sqlsrv_has_rows: Should have scrolled the cursor to the beginning "
|
SQLSRV_ASSERT(( r == SQL_NO_DATA ), "core_sqlsrv_has_rows: Should have scrolled the cursor to the beginning "
|
||||||
|
@ -1791,7 +1791,7 @@ void determine_stmt_has_rows( _Inout_ ss_sqlsrv_stmt* stmt )
|
||||||
if( SQL_SUCCEEDED( r )) {
|
if( SQL_SUCCEEDED( r )) {
|
||||||
|
|
||||||
stmt->has_rows = true;
|
stmt->has_rows = true;
|
||||||
CHECK_SQL_WARNING( r, stmt );
|
CHECK_SQL_WARNING( r, stmt, NULL );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1841,7 +1841,7 @@ void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, _In_ zend_long fetch_typ
|
||||||
SQLSRV_PHPTYPE sqlsrv_php_type_out = SQLSRV_PHPTYPE_INVALID;
|
SQLSRV_PHPTYPE sqlsrv_php_type_out = SQLSRV_PHPTYPE_INVALID;
|
||||||
|
|
||||||
// make sure that the fetch type is legal
|
// make sure that the fetch type is legal
|
||||||
CHECK_CUSTOM_ERROR((fetch_type < MIN_SQLSRV_FETCH || fetch_type > MAX_SQLSRV_FETCH), stmt, SS_SQLSRV_ERROR_INVALID_FETCH_TYPE, stmt->func()) {
|
CHECK_CUSTOM_ERROR((fetch_type < MIN_SQLSRV_FETCH || fetch_type > MAX_SQLSRV_FETCH), stmt, SS_SQLSRV_ERROR_INVALID_FETCH_TYPE, stmt->func(), NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1893,7 +1893,7 @@ void fetch_fields_common( _Inout_ ss_sqlsrv_stmt* stmt, _In_ zend_long fetch_typ
|
||||||
if( fetch_type & SQLSRV_FETCH_ASSOC ) {
|
if( fetch_type & SQLSRV_FETCH_ASSOC ) {
|
||||||
|
|
||||||
CHECK_CUSTOM_WARNING_AS_ERROR(( stmt->fetch_field_names[i].len == 0 && !allow_empty_field_names ), stmt,
|
CHECK_CUSTOM_WARNING_AS_ERROR(( stmt->fetch_field_names[i].len == 0 && !allow_empty_field_names ), stmt,
|
||||||
SS_SQLSRV_WARNING_FIELD_NAME_EMPTY) {
|
SS_SQLSRV_WARNING_FIELD_NAME_EMPTY, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1924,16 +1924,16 @@ zval* parse_param_array(_Inout_ ss_sqlsrv_stmt* stmt, _Inout_ HashTable* param_h
|
||||||
zval* dir = zend_hash_index_find(param_ht, 1);
|
zval* dir = zend_hash_index_find(param_ht, 1);
|
||||||
if (Z_TYPE_P(dir) != IS_NULL) {
|
if (Z_TYPE_P(dir) != IS_NULL) {
|
||||||
// if param direction is specified, make sure it's valid
|
// if param direction is specified, make sure it's valid
|
||||||
CHECK_CUSTOM_ERROR(Z_TYPE_P(dir) != IS_LONG, stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_DIRECTION, index + 1) {
|
CHECK_CUSTOM_ERROR(Z_TYPE_P(dir) != IS_LONG, stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_DIRECTION, index + 1, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
direction = static_cast<SQLSMALLINT>(Z_LVAL_P(dir));
|
direction = static_cast<SQLSMALLINT>(Z_LVAL_P(dir));
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(direction != SQL_PARAM_INPUT && direction != SQL_PARAM_OUTPUT && direction != SQL_PARAM_INPUT_OUTPUT,
|
CHECK_CUSTOM_ERROR(direction != SQL_PARAM_INPUT && direction != SQL_PARAM_OUTPUT && direction != SQL_PARAM_INPUT_OUTPUT,
|
||||||
stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_DIRECTION, index + 1) {
|
stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_DIRECTION, index + 1, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
CHECK_CUSTOM_ERROR(direction != SQL_PARAM_INPUT && !Z_ISREF_P(var_or_val), stmt, SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF, index + 1) {
|
CHECK_CUSTOM_ERROR(direction != SQL_PARAM_INPUT && !Z_ISREF_P(var_or_val), stmt, SS_SQLSRV_ERROR_PARAM_VAR_NOT_REF, index + 1, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1953,13 +1953,13 @@ zval* parse_param_array(_Inout_ ss_sqlsrv_stmt* stmt, _Inout_ HashTable* param_h
|
||||||
php_out_type = zend_to_sqlsrv_phptype[Z_TYPE_P(var_or_val)];
|
php_out_type = zend_to_sqlsrv_phptype[Z_TYPE_P(var_or_val)];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CHECK_CUSTOM_ERROR(Z_TYPE_P(phptype_z) != IS_LONG, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, index + 1) {
|
CHECK_CUSTOM_ERROR(Z_TYPE_P(phptype_z) != IS_LONG, stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, index + 1, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlsrv_phptype srv_phptype;
|
sqlsrv_phptype srv_phptype;
|
||||||
srv_phptype.value = Z_LVAL_P(phptype_z);
|
srv_phptype.value = Z_LVAL_P(phptype_z);
|
||||||
CHECK_CUSTOM_ERROR(!is_valid_sqlsrv_phptype(srv_phptype), stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, index + 1) {
|
CHECK_CUSTOM_ERROR(!is_valid_sqlsrv_phptype(srv_phptype), stmt, SQLSRV_ERROR_INVALID_PARAMETER_PHPTYPE, index + 1, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1978,19 +1978,19 @@ zval* parse_param_array(_Inout_ ss_sqlsrv_stmt* stmt, _Inout_ HashTable* param_h
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
CHECK_CUSTOM_ERROR(Z_TYPE_P(sqltype_z) != IS_LONG, stmt, SQLSRV_ERROR_INVALID_PARAMETER_SQLTYPE, index + 1) {
|
CHECK_CUSTOM_ERROR(Z_TYPE_P(sqltype_z) != IS_LONG, stmt, SQLSRV_ERROR_INVALID_PARAMETER_SQLTYPE, index + 1, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
// since the user supplied this type, make sure it's valid
|
// since the user supplied this type, make sure it's valid
|
||||||
sqlsrv_sqltype sqlsrv_sql_type;
|
sqlsrv_sqltype sqlsrv_sql_type;
|
||||||
sqlsrv_sql_type.value = Z_LVAL_P(sqltype_z);
|
sqlsrv_sql_type.value = Z_LVAL_P(sqltype_z);
|
||||||
CHECK_CUSTOM_ERROR(!is_valid_sqlsrv_sqltype(sqlsrv_sql_type), stmt, SQLSRV_ERROR_INVALID_PARAMETER_SQLTYPE, index + 1) {
|
CHECK_CUSTOM_ERROR(!is_valid_sqlsrv_sqltype(sqlsrv_sql_type), stmt, SQLSRV_ERROR_INVALID_PARAMETER_SQLTYPE, index + 1, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool size_okay = determine_column_size_or_precision(stmt, sqlsrv_sql_type, &column_size, &decimal_digits);
|
bool size_okay = determine_column_size_or_precision(stmt, sqlsrv_sql_type, &column_size, &decimal_digits);
|
||||||
CHECK_CUSTOM_ERROR(!size_okay, stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_PRECISION, index + 1) {
|
CHECK_CUSTOM_ERROR(!size_okay, stmt, SS_SQLSRV_ERROR_INVALID_PARAMETER_PRECISION, index + 1, NULL) {
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// Contents: Version resource
|
// Contents: Version resource
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
|
|
|
@ -5,17 +5,17 @@
|
||||||
//
|
//
|
||||||
// Comments: Mostly error handling and some type handling
|
// Comments: Mostly error handling and some type handling
|
||||||
//
|
//
|
||||||
// Microsoft Drivers 5.10 for PHP for SQL Server
|
// Microsoft Drivers 5.11 for PHP for SQL Server
|
||||||
// Copyright(c) Microsoft Corporation
|
// Copyright(c) Microsoft Corporation
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
// MIT License
|
// MIT License
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the ""Software""),
|
// 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,
|
// 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 :
|
// 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 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,
|
// 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
|
// 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
|
// 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.
|
// IN THE SOFTWARE.
|
||||||
//---------------------------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -26,17 +26,17 @@ extern "C" {
|
||||||
#include "php_sqlsrv_int.h"
|
#include "php_sqlsrv_int.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// current subsytem. defined for the CHECK_SQL_{ERROR|WARNING} macros
|
// current subsytem. defined for the CHECK_SQL_{ERROR|WARNING} macros
|
||||||
unsigned int current_log_subsystem = LOG_UTIL;
|
unsigned int current_log_subsystem = LOG_UTIL;
|
||||||
|
|
||||||
// *** internal functions ***
|
// *** internal functions ***
|
||||||
sqlsrv_error_const* get_error_message( _In_ unsigned int sqlsrv_error_code );
|
sqlsrv_error_const* get_error_message( _In_ unsigned int sqlsrv_error_code );
|
||||||
|
|
||||||
void copy_error_to_zval( _Inout_ zval* error_z, _In_ sqlsrv_error_const* error, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain,
|
void copy_error_to_zval( _Inout_ zval* error_z, _In_ sqlsrv_error_const* error, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain,
|
||||||
_In_ bool warning );
|
_In_ bool warning );
|
||||||
bool ignore_warning( _In_ char* sql_state, _In_ int native_code );
|
bool ignore_warning( _In_ char* sql_state, _In_ int native_code );
|
||||||
bool handle_errors_and_warnings( _Inout_ sqlsrv_context& ctx, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain, _In_ logging_severity log_severity,
|
bool handle_errors_and_warnings( _Inout_ sqlsrv_context& ctx, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain, _In_ logging_severity log_severity,
|
||||||
_In_ unsigned int sqlsrv_error_code, _In_ int warning, _In_opt_ va_list* print_args );
|
_In_ unsigned int sqlsrv_error_code, _In_ int warning, _In_opt_ va_list* print_args );
|
||||||
|
|
||||||
int sqlsrv_merge_zend_hash_dtor( _Inout_ zval* dest );
|
int sqlsrv_merge_zend_hash_dtor( _Inout_ zval* dest );
|
||||||
|
@ -46,9 +46,9 @@ bool sqlsrv_merge_zend_hash( _Inout_ zval* dest_z, zval const* src_z );
|
||||||
|
|
||||||
// List of all error messages
|
// List of all error messages
|
||||||
ss_error SS_ERRORS[] = {
|
ss_error SS_ERRORS[] = {
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_INVALID_OPTION,
|
SS_SQLSRV_ERROR_INVALID_OPTION,
|
||||||
{ IMSSP, (SQLCHAR*)"Invalid option %1!s! was passed to sqlsrv_connect.", -1, true }
|
{ IMSSP, (SQLCHAR*)"Invalid option %1!s! was passed to sqlsrv_connect.", -1, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -57,23 +57,23 @@ ss_error SS_ERRORS[] = {
|
||||||
|
|
||||||
// these two share the same code since they are basically the same error.
|
// these two share the same code since they are basically the same error.
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_UID_PWD_BRACES_NOT_ESCAPED,
|
SQLSRV_ERROR_UID_PWD_BRACES_NOT_ESCAPED,
|
||||||
{ IMSSP, (SQLCHAR*) "An unescaped right brace (}) was found in either the user name or password. All right braces must be"
|
{ IMSSP, (SQLCHAR*) "An unescaped right brace (}) was found in either the user name or password. All right braces must be"
|
||||||
" escaped with another right brace (}}).", -4, false }
|
" escaped with another right brace (}}).", -4, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_CONNECT_BRACES_NOT_ESCAPED,
|
SS_SQLSRV_ERROR_CONNECT_BRACES_NOT_ESCAPED,
|
||||||
{ IMSSP, (SQLCHAR*)"An unescaped right brace (}) was found in option %1!s!.", -4, true }
|
{ IMSSP, (SQLCHAR*)"An unescaped right brace (}) was found in option %1!s!.", -4, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
|
||||||
SQLSRV_ERROR_NO_DATA,
|
|
||||||
{ IMSSP, (SQLCHAR*)"Field %1!d! returned no data.", -5, true }
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_STREAMABLE_TYPES_ONLY,
|
SQLSRV_ERROR_NO_DATA,
|
||||||
|
{ IMSSP, (SQLCHAR*)"Field %1!d! returned no data.", -5, true }
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
SQLSRV_ERROR_STREAMABLE_TYPES_ONLY,
|
||||||
{ IMSSP, (SQLCHAR*)"Only char, nchar, varchar, nvarchar, binary, varbinary, and large object types can be read by using "
|
{ IMSSP, (SQLCHAR*)"Only char, nchar, varchar, nvarchar, binary, varbinary, and large object types can be read by using "
|
||||||
"streams.", -6, false}
|
"streams.", -6, false}
|
||||||
},
|
},
|
||||||
|
@ -90,12 +90,12 @@ ss_error SS_ERRORS[] = {
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_VAR_REQUIRED,
|
SS_SQLSRV_ERROR_VAR_REQUIRED,
|
||||||
{ IMSSP, (SQLCHAR*)"Parameter array %1!d! must have at least one value or variable.", -9, true }
|
{ IMSSP, (SQLCHAR*)"Parameter array %1!d! must have at least one value or variable.", -9, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_INVALID_FETCH_TYPE,
|
SS_SQLSRV_ERROR_INVALID_FETCH_TYPE,
|
||||||
{ IMSSP, (SQLCHAR*)"An invalid fetch type was specified. SQLSRV_FETCH_NUMERIC, SQLSRV_FETCH_ARRAY and SQLSRV_FETCH_BOTH are acceptable values.", -10, false }
|
{ IMSSP, (SQLCHAR*)"An invalid fetch type was specified. SQLSRV_FETCH_NUMERIC, SQLSRV_FETCH_ARRAY and SQLSRV_FETCH_BOTH are acceptable values.", -10, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -103,24 +103,24 @@ ss_error SS_ERRORS[] = {
|
||||||
SQLSRV_ERROR_STATEMENT_NOT_EXECUTED,
|
SQLSRV_ERROR_STATEMENT_NOT_EXECUTED,
|
||||||
{ IMSSP, (SQLCHAR*)"The statement must be executed before results can be retrieved.", -11, false }
|
{ IMSSP, (SQLCHAR*)"The statement must be executed before results can be retrieved.", -11, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_ALREADY_IN_TXN,
|
SS_SQLSRV_ERROR_ALREADY_IN_TXN,
|
||||||
{ IMSSP, (SQLCHAR*)"Cannot begin a transaction until the current transaction has been completed by calling either "
|
{ IMSSP, (SQLCHAR*)"Cannot begin a transaction until the current transaction has been completed by calling either "
|
||||||
"sqlsrv_commit or sqlsrv_rollback.", -12, false }
|
"sqlsrv_commit or sqlsrv_rollback.", -12, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_NOT_IN_TXN,
|
SS_SQLSRV_ERROR_NOT_IN_TXN,
|
||||||
{ IMSSP, (SQLCHAR*)"A transaction must be started by calling sqlsrv_begin_transaction before calling sqlsrv_commit or "
|
{ IMSSP, (SQLCHAR*)"A transaction must be started by calling sqlsrv_begin_transaction before calling sqlsrv_commit or "
|
||||||
"sqlsrv_rollback.", -13, false }
|
"sqlsrv_rollback.", -13, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER,
|
SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER,
|
||||||
{ IMSSP, (SQLCHAR*)"An invalid parameter was passed to %1!s!.", -14, true }
|
{ IMSSP, (SQLCHAR*)"An invalid parameter was passed to %1!s!.", -14, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_INVALID_PARAMETER_DIRECTION,
|
SS_SQLSRV_ERROR_INVALID_PARAMETER_DIRECTION,
|
||||||
{ IMSSP, (SQLCHAR*)"An invalid direction for parameter %1!d! was specified. SQLSRV_PARAM_IN, SQLSRV_PARAM_OUT, and "
|
{ IMSSP, (SQLCHAR*)"An invalid direction for parameter %1!d! was specified. SQLSRV_PARAM_IN, SQLSRV_PARAM_OUT, and "
|
||||||
|
@ -140,7 +140,7 @@ ss_error SS_ERRORS[] = {
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_FETCH_NOT_CALLED,
|
SQLSRV_ERROR_FETCH_NOT_CALLED,
|
||||||
{ IMSSP, (SQLCHAR*)"A row must be retrieved with sqlsrv_fetch before retrieving data with sqlsrv_get_field.", -18, false }
|
{ IMSSP, (SQLCHAR*)"A row must be retrieved with sqlsrv_fetch before retrieving data with sqlsrv_get_field.", -18, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_FIELD_INDEX_ERROR,
|
SQLSRV_ERROR_FIELD_INDEX_ERROR,
|
||||||
|
@ -159,14 +159,14 @@ ss_error SS_ERRORS[] = {
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_FETCH_PAST_END,
|
SQLSRV_ERROR_FETCH_PAST_END,
|
||||||
{ IMSSP, (SQLCHAR*)"There are no more rows in the active result set. Since this result set is not scrollable, no more "
|
{ IMSSP, (SQLCHAR*)"There are no more rows in the active result set. Since this result set is not scrollable, no more "
|
||||||
"data may be retrieved.", -22, false }
|
"data may be retrieved.", -22, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_STATEMENT_NOT_PREPARED,
|
SS_SQLSRV_ERROR_STATEMENT_NOT_PREPARED,
|
||||||
{ IMSSP, (SQLCHAR*)"A statement must be prepared with sqlsrv_prepare before calling sqlsrv_execute.", -23, false }
|
{ IMSSP, (SQLCHAR*)"A statement must be prepared with sqlsrv_prepare before calling sqlsrv_execute.", -23, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_ZEND_HASH,
|
SQLSRV_ERROR_ZEND_HASH,
|
||||||
{ IMSSP, (SQLCHAR*)"An error occurred while creating or accessing a Zend hash table.", -24, false }
|
{ IMSSP, (SQLCHAR*)"An error occurred while creating or accessing a Zend hash table.", -24, false }
|
||||||
|
@ -181,37 +181,37 @@ ss_error SS_ERRORS[] = {
|
||||||
SQLSRV_ERROR_NEXT_RESULT_PAST_END,
|
SQLSRV_ERROR_NEXT_RESULT_PAST_END,
|
||||||
{ IMSSP, (SQLCHAR*)"There are no more results returned by the query.", -26, false }
|
{ IMSSP, (SQLCHAR*)"There are no more results returned by the query.", -26, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_STREAM_CREATE,
|
SQLSRV_ERROR_STREAM_CREATE,
|
||||||
{ IMSSP, (SQLCHAR*)"An error occurred while retrieving a SQL Server field as a stream.", -27, false }
|
{ IMSSP, (SQLCHAR*)"An error occurred while retrieving a SQL Server field as a stream.", -27, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_NO_FIELDS,
|
SQLSRV_ERROR_NO_FIELDS,
|
||||||
{ IMSSP, (SQLCHAR*)"The active result for the query contains no fields.", -28, false }
|
{ IMSSP, (SQLCHAR*)"The active result for the query contains no fields.", -28, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_ZEND_BAD_CLASS,
|
SS_SQLSRV_ERROR_ZEND_BAD_CLASS,
|
||||||
{ IMSSP, (SQLCHAR*)"Failed to find class %1!s!.", -29, true }
|
{ IMSSP, (SQLCHAR*)"Failed to find class %1!s!.", -29, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_ZEND_OBJECT_FAILED,
|
SS_SQLSRV_ERROR_ZEND_OBJECT_FAILED,
|
||||||
{ IMSSP, (SQLCHAR*)"Failed to create an instance of class %1!s!.", -30, true }
|
{ IMSSP, (SQLCHAR*)"Failed to create an instance of class %1!s!.", -30, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_INVALID_PARAMETER_PRECISION,
|
SS_SQLSRV_ERROR_INVALID_PARAMETER_PRECISION,
|
||||||
{ IMSSP, (SQLCHAR*)"An invalid size or precision for parameter %1!d! was specified.", -31, true }
|
{ IMSSP, (SQLCHAR*)"An invalid size or precision for parameter %1!d! was specified.", -31, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_INVALID_OPTION_KEY,
|
SQLSRV_ERROR_INVALID_OPTION_KEY,
|
||||||
{ IMSSP, (SQLCHAR*)"Option %1!s! is invalid.", -32, true }
|
{ IMSSP, (SQLCHAR*)"Option %1!s! is invalid.", -32, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
// these three errors are returned for invalid options, so they are given the same number for compatibility with 1.1
|
// these three errors are returned for invalid options, so they are given the same number for compatibility with 1.1
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE,
|
SQLSRV_ERROR_INVALID_QUERY_TIMEOUT_VALUE,
|
||||||
|
@ -219,17 +219,17 @@ ss_error SS_ERRORS[] = {
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_INVALID_OPTION_TYPE_INT,
|
SQLSRV_ERROR_INVALID_OPTION_TYPE_INT,
|
||||||
{ IMSSP, (SQLCHAR*) "Invalid value type for option %1!s! was specified. Integer type was expected.", -33, true }
|
{ IMSSP, (SQLCHAR*) "Invalid value type for option %1!s! was specified. Integer type was expected.", -33, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_INVALID_OPTION_TYPE_STRING,
|
SQLSRV_ERROR_INVALID_OPTION_TYPE_STRING,
|
||||||
{ IMSSP, (SQLCHAR*) "Invalid value type for option %1!s! was specified. String type was expected.", -33, true }
|
{ IMSSP, (SQLCHAR*) "Invalid value type for option %1!s! was specified. String type was expected.", -33, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_INPUT_OUTPUT_PARAM_TYPE_MATCH,
|
SQLSRV_ERROR_INPUT_OUTPUT_PARAM_TYPE_MATCH,
|
||||||
{ IMSSP, (SQLCHAR*)"The type of output parameter %1!d! does not match the type specified by the SQLSRV_PHPTYPE_* constant."
|
{ IMSSP, (SQLCHAR*)"The type of output parameter %1!d! does not match the type specified by the SQLSRV_PHPTYPE_* constant."
|
||||||
" For output parameters, the type of the variable's current value must match the SQLSRV_PHPTYPE_* constant, or be NULL. "
|
" For output parameters, the type of the variable's current value must match the SQLSRV_PHPTYPE_* constant, or be NULL. "
|
||||||
"If the type is NULL, the PHP type of the output parameter is inferred from the SQLSRV_SQLTYPE_* constant.", -34, true }
|
"If the type is NULL, the PHP type of the output parameter is inferred from the SQLSRV_SQLTYPE_* constant.", -34, true }
|
||||||
|
@ -238,14 +238,14 @@ ss_error SS_ERRORS[] = {
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_INVALID_TYPE,
|
SQLSRV_ERROR_INVALID_TYPE,
|
||||||
{ IMSSP, (SQLCHAR*)"Invalid type", -35, false }
|
{ IMSSP, (SQLCHAR*)"Invalid type", -35, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
// 36-38 have no equivalent 2.0 errors
|
// 36-38 have no equivalent 2.0 errors
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_REGISTER_RESOURCE,
|
SS_SQLSRV_ERROR_REGISTER_RESOURCE,
|
||||||
{ IMSSP, (SQLCHAR*)"Registering the %1!s! resource failed.", -39, true }
|
{ IMSSP, (SQLCHAR*)"Registering the %1!s! resource failed.", -39, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE,
|
SQLSRV_ERROR_INPUT_PARAM_ENCODING_TRANSLATE,
|
||||||
|
@ -256,7 +256,7 @@ ss_error SS_ERRORS[] = {
|
||||||
SQLSRV_ERROR_OUTPUT_PARAM_ENCODING_TRANSLATE,
|
SQLSRV_ERROR_OUTPUT_PARAM_ENCODING_TRANSLATE,
|
||||||
{ IMSSP, (SQLCHAR*)"An error occurred translating string for an output param to UTF-8: %1!s!", -41, true }
|
{ IMSSP, (SQLCHAR*)"An error occurred translating string for an output param to UTF-8: %1!s!", -41, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE,
|
SQLSRV_ERROR_FIELD_ENCODING_TRANSLATE,
|
||||||
{ IMSSP, (SQLCHAR*)"An error occurred translating string for a field to UTF-8: %1!s!", -42, true }
|
{ IMSSP, (SQLCHAR*)"An error occurred translating string for a field to UTF-8: %1!s!", -42, true }
|
||||||
|
@ -267,24 +267,24 @@ ss_error SS_ERRORS[] = {
|
||||||
{ IMSSP, (SQLCHAR*)"An error occurred translating a PHP stream from UTF-8 to UTF-16: %1!s!", -43, true }
|
{ IMSSP, (SQLCHAR*)"An error occurred translating a PHP stream from UTF-8 to UTF-16: %1!s!", -43, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_MARS_OFF,
|
SQLSRV_ERROR_MARS_OFF,
|
||||||
{ IMSSP, (SQLCHAR*)"The connection cannot process this operation because there is a statement with pending results. "
|
{ IMSSP, (SQLCHAR*)"The connection cannot process this operation because there is a statement with pending results. "
|
||||||
"To make the connection available for other queries, either fetch all results or cancel or free the statement. "
|
"To make the connection available for other queries, either fetch all results or cancel or free the statement. "
|
||||||
"For more information, see the product documentation about the MultipleActiveResultSets connection option.", -44, false }
|
"For more information, see the product documentation about the MultipleActiveResultSets connection option.", -44, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_CONN_OPTS_WRONG_TYPE,
|
SQLSRV_ERROR_CONN_OPTS_WRONG_TYPE,
|
||||||
{ IMSSP, (SQLCHAR*) "Expected an array of options for the connection. Connection options must be passed as an array of "
|
{ IMSSP, (SQLCHAR*) "Expected an array of options for the connection. Connection options must be passed as an array of "
|
||||||
"key/value pairs.", -45, false }
|
"key/value pairs.", -45, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE,
|
SQLSRV_ERROR_QUERY_STRING_ENCODING_TRANSLATE,
|
||||||
{ IMSSP, (SQLCHAR*) "An error occurred translating the query string to UTF-16: %1!s!.", -46, true }
|
{ IMSSP, (SQLCHAR*) "An error occurred translating the query string to UTF-16: %1!s!.", -46, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_CONNECT_STRING_ENCODING_TRANSLATE,
|
SQLSRV_ERROR_CONNECT_STRING_ENCODING_TRANSLATE,
|
||||||
{ IMSSP, (SQLCHAR*) "An error occurred translating the connection string to UTF-16: %1!s!", -47, true }
|
{ IMSSP, (SQLCHAR*) "An error occurred translating the connection string to UTF-16: %1!s!", -47, true }
|
||||||
|
@ -300,13 +300,13 @@ ss_error SS_ERRORS[] = {
|
||||||
{ IMSSP, (SQLCHAR*) "This extension requires the Microsoft ODBC Driver for SQL Server. "
|
{ IMSSP, (SQLCHAR*) "This extension requires the Microsoft ODBC Driver for SQL Server. "
|
||||||
"Access the following URL to download the ODBC Driver for SQL Server for %1!s!: "
|
"Access the following URL to download the ODBC Driver for SQL Server for %1!s!: "
|
||||||
"https://go.microsoft.com/fwlink/?LinkId=163712", -49, true }
|
"https://go.microsoft.com/fwlink/?LinkId=163712", -49, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_STATEMENT_NOT_SCROLLABLE,
|
SS_SQLSRV_ERROR_STATEMENT_NOT_SCROLLABLE,
|
||||||
{ IMSSP, (SQLCHAR*)"This function only works with statements that have static or keyset scrollable cursors.", -50, false }
|
{ IMSSP, (SQLCHAR*)"This function only works with statements that have static or keyset scrollable cursors.", -50, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_STATEMENT_SCROLLABLE,
|
SS_SQLSRV_ERROR_STATEMENT_SCROLLABLE,
|
||||||
{ IMSSP, (SQLCHAR*)"This function only works with statements that are not scrollable.", -51, false }
|
{ IMSSP, (SQLCHAR*)"This function only works with statements that are not scrollable.", -51, false }
|
||||||
|
@ -314,11 +314,11 @@ ss_error SS_ERRORS[] = {
|
||||||
|
|
||||||
// new error for 2.0, used here since 1.1 didn't have a -52
|
// new error for 2.0, used here since 1.1 didn't have a -52
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_MAX_PARAMS_EXCEEDED,
|
SQLSRV_ERROR_MAX_PARAMS_EXCEEDED,
|
||||||
{ IMSSP, (SQLCHAR*) "Tried to bind parameter number %1!d!. SQL Server supports a maximum of 2100 parameters.", -52, true }
|
{ IMSSP, (SQLCHAR*) "Tried to bind parameter number %1!d!. SQL Server supports a maximum of 2100 parameters.", -52, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SS_SQLSRV_ERROR_INVALID_FETCH_STYLE,
|
SS_SQLSRV_ERROR_INVALID_FETCH_STYLE,
|
||||||
{ IMSSP, (SQLCHAR*)"The scroll type passed to sqlsrv_fetch, sqlsrv_fetch_array, or sqlsrv_fetch_object was not valid. "
|
{ IMSSP, (SQLCHAR*)"The scroll type passed to sqlsrv_fetch, sqlsrv_fetch_array, or sqlsrv_fetch_object was not valid. "
|
||||||
"Please use one of the SQLSRV_SCROLL constants.", -53, false }
|
"Please use one of the SQLSRV_SCROLL constants.", -53, false }
|
||||||
|
@ -329,14 +329,14 @@ ss_error SS_ERRORS[] = {
|
||||||
{ IMSSP, (SQLCHAR*)"The value passed for the 'Scrollable' statement option is invalid. Please use 'static', 'dynamic', "
|
{ IMSSP, (SQLCHAR*)"The value passed for the 'Scrollable' statement option is invalid. Please use 'static', 'dynamic', "
|
||||||
"'keyset', 'forward', or 'buffered'.", -54, false }
|
"'keyset', 'forward', or 'buffered'.", -54, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_UNKNOWN_SERVER_VERSION,
|
SQLSRV_ERROR_UNKNOWN_SERVER_VERSION,
|
||||||
{ IMSSP, (SQLCHAR*)"Failed to retrieve the server version. Unable to continue.", -55, false }
|
{ IMSSP, (SQLCHAR*)"Failed to retrieve the server version. Unable to continue.", -55, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_INVALID_PARAMETER_ENCODING,
|
SQLSRV_ERROR_INVALID_PARAMETER_ENCODING,
|
||||||
{ IMSSP, (SQLCHAR*) "An invalid encoding was specified for parameter %1!d!.", -56, true }
|
{ IMSSP, (SQLCHAR*) "An invalid encoding was specified for parameter %1!d!.", -56, true }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -346,7 +346,7 @@ ss_error SS_ERRORS[] = {
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED,
|
SQLSRV_ERROR_OUTPUT_PARAM_TRUNCATED,
|
||||||
{ IMSSP, (SQLCHAR*) "String data, right truncated for output parameter %1!d!.", -58, true }
|
{ IMSSP, (SQLCHAR*) "String data, right truncated for output parameter %1!d!.", -58, true }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -472,7 +472,7 @@ ss_error SS_ERRORS[] = {
|
||||||
{
|
{
|
||||||
SQLSRV_ERROR_TVP_INPUT_PARAM_ONLY,
|
SQLSRV_ERROR_TVP_INPUT_PARAM_ONLY,
|
||||||
{ IMSSP, (SQLCHAR*) "You cannot return data in a table-valued parameter. Table-valued parameters are input-only.", -130, false }
|
{ IMSSP, (SQLCHAR*) "You cannot return data in a table-valued parameter. Table-valued parameters are input-only.", -130, false }
|
||||||
},
|
},
|
||||||
|
|
||||||
// terminate the list of errors/warnings
|
// terminate the list of errors/warnings
|
||||||
{ UINT_MAX, {} }
|
{ UINT_MAX, {} }
|
||||||
|
@ -491,7 +491,7 @@ bool ss_error_handler( _Inout_ sqlsrv_context& ctx, _In_ unsigned int sqlsrv_err
|
||||||
severity = SEV_WARNING;
|
severity = SEV_WARNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
return handle_errors_and_warnings( ctx, &SQLSRV_G( errors ), &SQLSRV_G( warnings ), severity, sqlsrv_error_code, warning,
|
return handle_errors_and_warnings( ctx, &SQLSRV_G( errors ), &SQLSRV_G( warnings ), severity, sqlsrv_error_code, warning,
|
||||||
print_args );
|
print_args );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +507,7 @@ bool ss_error_handler( _Inout_ sqlsrv_context& ctx, _In_ unsigned int sqlsrv_err
|
||||||
//
|
//
|
||||||
// $errorsAndOrWarnings[OPTIONAL]: A predefined constant. This parameter can
|
// $errorsAndOrWarnings[OPTIONAL]: A predefined constant. This parameter can
|
||||||
// take one of the values listed:
|
// take one of the values listed:
|
||||||
//
|
//
|
||||||
// SQLSRV_ERR_ALL
|
// SQLSRV_ERR_ALL
|
||||||
// Errors and warnings generated on the last sqlsrv function call are returned.
|
// Errors and warnings generated on the last sqlsrv function call are returned.
|
||||||
// SQLSRV_ERR_ERRORS
|
// SQLSRV_ERR_ERRORS
|
||||||
|
@ -603,10 +603,10 @@ PHP_FUNCTION( sqlsrv_configure )
|
||||||
// dummy context to pass onto the error handler
|
// dummy context to pass onto the error handler
|
||||||
error_ctx = new ( sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
|
error_ctx = new ( sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
|
||||||
error_ctx->set_func(_FN_);
|
error_ctx->set_func(_FN_);
|
||||||
|
|
||||||
int zr = zend_parse_parameters( ZEND_NUM_ARGS(), "sz", &option, &option_len, &value_z );
|
int zr = zend_parse_parameters( ZEND_NUM_ARGS(), "sz", &option, &option_len, &value_z );
|
||||||
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
|
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,11 +622,11 @@ PHP_FUNCTION( sqlsrv_configure )
|
||||||
// LogSeverity
|
// LogSeverity
|
||||||
else if( !stricmp( option, INI_LOG_SEVERITY )) {
|
else if( !stricmp( option, INI_LOG_SEVERITY )) {
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( Z_TYPE_P( value_z ) != IS_LONG ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
|
CHECK_CUSTOM_ERROR(( Z_TYPE_P( value_z ) != IS_LONG ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_long severity_mask = Z_LVAL_P( value_z );
|
zend_long severity_mask = Z_LVAL_P( value_z );
|
||||||
// make sure they can't use 0 to shut off the masking in the severity
|
// make sure they can't use 0 to shut off the masking in the severity
|
||||||
if( severity_mask < SEV_ALL || severity_mask == 0 || severity_mask > (SEV_NOTICE + SEV_ERROR + SEV_WARNING) ) {
|
if( severity_mask < SEV_ALL || severity_mask == 0 || severity_mask > (SEV_NOTICE + SEV_ERROR + SEV_WARNING) ) {
|
||||||
|
@ -641,11 +641,11 @@ PHP_FUNCTION( sqlsrv_configure )
|
||||||
// LogSubsystems
|
// LogSubsystems
|
||||||
else if( !stricmp( option, INI_LOG_SUBSYSTEMS )) {
|
else if( !stricmp( option, INI_LOG_SUBSYSTEMS )) {
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( Z_TYPE_P( value_z ) != IS_LONG ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
|
CHECK_CUSTOM_ERROR(( Z_TYPE_P( value_z ) != IS_LONG ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_long subsystem_mask = Z_LVAL_P( value_z );
|
zend_long subsystem_mask = Z_LVAL_P( value_z );
|
||||||
|
|
||||||
if( subsystem_mask < LOG_ALL || subsystem_mask > (LOG_INIT + LOG_CONN + LOG_STMT + LOG_UTIL) ) {
|
if( subsystem_mask < LOG_ALL || subsystem_mask > (LOG_INIT + LOG_CONN + LOG_STMT + LOG_UTIL) ) {
|
||||||
|
@ -658,15 +658,15 @@ PHP_FUNCTION( sqlsrv_configure )
|
||||||
}
|
}
|
||||||
|
|
||||||
else if( !stricmp( option, INI_BUFFERED_QUERY_LIMIT )) {
|
else if( !stricmp( option, INI_BUFFERED_QUERY_LIMIT )) {
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR(( Z_TYPE_P( value_z ) != IS_LONG ), error_ctx, SQLSRV_ERROR_INVALID_BUFFER_LIMIT, _FN_ ) {
|
CHECK_CUSTOM_ERROR(( Z_TYPE_P( value_z ) != IS_LONG ), error_ctx, SQLSRV_ERROR_INVALID_BUFFER_LIMIT, _FN_, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_long buffered_query_limit = Z_LVAL_P( value_z );
|
zend_long buffered_query_limit = Z_LVAL_P( value_z );
|
||||||
|
|
||||||
CHECK_CUSTOM_ERROR( buffered_query_limit <= 0, error_ctx, SQLSRV_ERROR_INVALID_BUFFER_LIMIT, _FN_ ) {
|
CHECK_CUSTOM_ERROR( buffered_query_limit <= 0, error_ctx, SQLSRV_ERROR_INVALID_BUFFER_LIMIT, _FN_, NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
|
@ -678,7 +678,7 @@ PHP_FUNCTION( sqlsrv_configure )
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
||||||
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
@ -693,7 +693,7 @@ PHP_FUNCTION( sqlsrv_configure )
|
||||||
|
|
||||||
|
|
||||||
// sqlsrv_get_config( string $setting )
|
// sqlsrv_get_config( string $setting )
|
||||||
//
|
//
|
||||||
// Returns the current value of the specified configuration setting.
|
// Returns the current value of the specified configuration setting.
|
||||||
//
|
//
|
||||||
// Parameters
|
// Parameters
|
||||||
|
@ -719,15 +719,15 @@ PHP_FUNCTION( sqlsrv_get_config )
|
||||||
reset_errors();
|
reset_errors();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// dummy context to pass onto the error handler
|
// dummy context to pass onto the error handler
|
||||||
error_ctx = new ( sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
|
error_ctx = new ( sqlsrv_malloc( sizeof( sqlsrv_context ))) sqlsrv_context( 0, ss_error_handler, NULL );
|
||||||
error_ctx->set_func(_FN_);
|
error_ctx->set_func(_FN_);
|
||||||
|
|
||||||
int zr = zend_parse_parameters( ZEND_NUM_ARGS(), "s", &option, &option_len );
|
int zr = zend_parse_parameters( ZEND_NUM_ARGS(), "s", &option, &option_len );
|
||||||
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ ) {
|
CHECK_CUSTOM_ERROR(( zr == FAILURE ), error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ , NULL) {
|
||||||
|
|
||||||
throw ss::SSException();
|
throw ss::SSException();
|
||||||
}
|
}
|
||||||
SQLSRV_ASSERT( option != NULL, "sqlsrv_get_config: option was null." );
|
SQLSRV_ASSERT( option != NULL, "sqlsrv_get_config: option was null." );
|
||||||
if( !stricmp( option, INI_WARNINGS_RETURN_AS_ERRORS )) {
|
if( !stricmp( option, INI_WARNINGS_RETURN_AS_ERRORS )) {
|
||||||
|
@ -751,16 +751,16 @@ PHP_FUNCTION( sqlsrv_get_config )
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_ );
|
THROW_CORE_ERROR( error_ctx, SS_SQLSRV_ERROR_INVALID_FUNCTION_PARAMETER, _FN_, NULL );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch( core::CoreException& ) {
|
catch( core::CoreException& ) {
|
||||||
|
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
catch( ... ) {
|
catch( ... ) {
|
||||||
|
|
||||||
DIE( "sqlsrv_get_config: Unknown exception caught." );
|
DIE( "sqlsrv_get_config: Unknown exception caught." );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -782,13 +782,13 @@ sqlsrv_error_const* get_error_message( _In_ unsigned int sqlsrv_error_code ) {
|
||||||
return error_message;
|
return error_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_error_to_zval( _Inout_ zval* error_z, _In_ sqlsrv_error_const* error, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain,
|
void copy_error_to_zval( _Inout_ zval* error_z, _In_ sqlsrv_error_const* error, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain,
|
||||||
_In_ bool warning )
|
_In_ bool warning )
|
||||||
{
|
{
|
||||||
array_init(error_z);
|
array_init(error_z);
|
||||||
|
|
||||||
// sqlstate
|
// sqlstate
|
||||||
zval temp;
|
zval temp;
|
||||||
ZVAL_UNDEF(&temp);
|
ZVAL_UNDEF(&temp);
|
||||||
core::sqlsrv_zval_stringl( &temp, reinterpret_cast<char*>( error->sqlstate ), SQL_SQLSTATE_SIZE );
|
core::sqlsrv_zval_stringl( &temp, reinterpret_cast<char*>( error->sqlstate ), SQL_SQLSTATE_SIZE );
|
||||||
Z_TRY_ADDREF_P( &temp );
|
Z_TRY_ADDREF_P( &temp );
|
||||||
|
@ -819,36 +819,36 @@ void copy_error_to_zval( _Inout_ zval* error_z, _In_ sqlsrv_error_const* error,
|
||||||
// add the error or warning to the reported_chain.
|
// add the error or warning to the reported_chain.
|
||||||
if( !warning || SQLSRV_G( warnings_return_as_errors ) )
|
if( !warning || SQLSRV_G( warnings_return_as_errors ) )
|
||||||
{
|
{
|
||||||
// if the warning is part of the ignored warning list than
|
// if the warning is part of the ignored warning list than
|
||||||
// add to the ignored chain if the ignored chain is not null.
|
// add to the ignored chain if the ignored chain is not null.
|
||||||
if( warning && ignore_warning( reinterpret_cast<char*>(error->sqlstate), error->native_code ) &&
|
if( warning && ignore_warning( reinterpret_cast<char*>(error->sqlstate), error->native_code ) &&
|
||||||
ignored_chain != NULL ) {
|
ignored_chain != NULL ) {
|
||||||
|
|
||||||
if( add_next_index_zval( ignored_chain, error_z ) == FAILURE ) {
|
if( add_next_index_zval( ignored_chain, error_z ) == FAILURE ) {
|
||||||
DIE( "Fatal error during error processing" );
|
DIE( "Fatal error during error processing" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// It is either an error or a warning which should not be ignored.
|
// It is either an error or a warning which should not be ignored.
|
||||||
if( add_next_index_zval( reported_chain, error_z ) == FAILURE ) {
|
if( add_next_index_zval( reported_chain, error_z ) == FAILURE ) {
|
||||||
DIE( "Fatal error during error processing" );
|
DIE( "Fatal error during error processing" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// It is a warning with warning_return_as_errors as false, so simply add it to the ignored_chain list
|
// It is a warning with warning_return_as_errors as false, so simply add it to the ignored_chain list
|
||||||
if( ignored_chain != NULL ) {
|
if( ignored_chain != NULL ) {
|
||||||
|
|
||||||
if( add_next_index_zval( ignored_chain, error_z ) == FAILURE ) {
|
if( add_next_index_zval( ignored_chain, error_z ) == FAILURE ) {
|
||||||
DIE( "Fatal error during error processing" );
|
DIE( "Fatal error during error processing" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool handle_errors_and_warnings( _Inout_ sqlsrv_context& ctx, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain, _In_ logging_severity log_severity,
|
bool handle_errors_and_warnings( _Inout_ sqlsrv_context& ctx, _Inout_ zval* reported_chain, _Inout_ zval* ignored_chain, _In_ logging_severity log_severity,
|
||||||
_In_ unsigned int sqlsrv_error_code, _In_ int warning, _In_opt_ va_list* print_args )
|
_In_ unsigned int sqlsrv_error_code, _In_ int warning, _In_opt_ va_list* print_args )
|
||||||
{
|
{
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
@ -872,20 +872,20 @@ bool handle_errors_and_warnings( _Inout_ sqlsrv_context& ctx, _Inout_ zval* repo
|
||||||
|
|
||||||
// array of ignored errors
|
// array of ignored errors
|
||||||
if( ignored_chain != NULL ) {
|
if( ignored_chain != NULL ) {
|
||||||
|
|
||||||
if( Z_TYPE_P( ignored_chain ) == IS_NULL ) {
|
if( Z_TYPE_P( ignored_chain ) == IS_NULL ) {
|
||||||
|
|
||||||
ignored_chain_was_null = true;
|
ignored_chain_was_null = true;
|
||||||
array_init( ignored_chain );
|
array_init( ignored_chain );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sqlsrv_error_code != SQLSRV_ERROR_ODBC ) {
|
if( sqlsrv_error_code != SQLSRV_ERROR_ODBC ) {
|
||||||
|
|
||||||
core_sqlsrv_format_driver_error( ctx, get_error_message( sqlsrv_error_code ), error, log_severity, print_args );
|
core_sqlsrv_format_driver_error( ctx, get_error_message( sqlsrv_error_code ), error, log_severity, print_args );
|
||||||
copy_error_to_zval( &error_z, error, reported_chain, ignored_chain, warning );
|
copy_error_to_zval( &error_z, error, reported_chain, ignored_chain, warning );
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLSMALLINT record_number = 0;
|
SQLSMALLINT record_number = 0;
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
@ -894,7 +894,7 @@ bool handle_errors_and_warnings( _Inout_ sqlsrv_context& ctx, _Inout_ zval* repo
|
||||||
copy_error_to_zval( &error_z, error, reported_chain, ignored_chain, warning );
|
copy_error_to_zval( &error_z, error, reported_chain, ignored_chain, warning );
|
||||||
}
|
}
|
||||||
} while( result );
|
} while( result );
|
||||||
|
|
||||||
// If it were a warning, we report that warnings where ignored except if warnings_return_as_errors
|
// If it were a warning, we report that warnings where ignored except if warnings_return_as_errors
|
||||||
// was true and we added some warnings to the reported_chain.
|
// was true and we added some warnings to the reported_chain.
|
||||||
if( warning ) {
|
if( warning ) {
|
||||||
|
@ -902,9 +902,9 @@ bool handle_errors_and_warnings( _Inout_ sqlsrv_context& ctx, _Inout_ zval* repo
|
||||||
errors_ignored = true;
|
errors_ignored = true;
|
||||||
|
|
||||||
if( SQLSRV_G( warnings_return_as_errors ) ) {
|
if( SQLSRV_G( warnings_return_as_errors ) ) {
|
||||||
|
|
||||||
if( zend_hash_num_elements( Z_ARRVAL_P( reported_chain )) > prev_reported_cnt ) {
|
if( zend_hash_num_elements( Z_ARRVAL_P( reported_chain )) > prev_reported_cnt ) {
|
||||||
|
|
||||||
// We actually added some errors
|
// We actually added some errors
|
||||||
errors_ignored = false;
|
errors_ignored = false;
|
||||||
}
|
}
|
||||||
|
@ -946,12 +946,12 @@ bool ignore_warning( _In_ char* sql_state, _In_ int native_code )
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sqlsrv_merge_zend_hash_dtor( _Inout_ zval* dest )
|
int sqlsrv_merge_zend_hash_dtor( _Inout_ zval* dest )
|
||||||
{
|
{
|
||||||
zval_ptr_dtor( dest );
|
zval_ptr_dtor( dest );
|
||||||
return ZEND_HASH_APPLY_REMOVE;
|
return ZEND_HASH_APPLY_REMOVE;
|
||||||
}
|
}
|
||||||
|
@ -988,6 +988,6 @@ bool sqlsrv_merge_zend_hash( _Inout_ zval* dest_z, zval const* src_z )
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -8,9 +8,13 @@ fetch with all fetch styles
|
||||||
$conn = new PDO( "sqlsrv:server=$server ; Database = $databaseName", "$uid", "$pwd");
|
$conn = new PDO( "sqlsrv:server=$server ; Database = $databaseName", "$uid", "$pwd");
|
||||||
|
|
||||||
print( "\n---------- PDO::FETCH_CLASS -------------\n" );
|
print( "\n---------- PDO::FETCH_CLASS -------------\n" );
|
||||||
$stmt = $conn->query( "select * from HumanResources.Department order by GroupName" );
|
$stmt = $conn->query( "select DepartmentID, Name, GroupName from HumanResources.Department order by GroupName" );
|
||||||
|
|
||||||
class cc {
|
class cc {
|
||||||
|
public $DepartmentID;
|
||||||
|
public $Name;
|
||||||
|
public $GroupName;
|
||||||
|
|
||||||
function __construct( $arg ) {
|
function __construct( $arg ) {
|
||||||
echo "$arg";
|
echo "$arg";
|
||||||
}
|
}
|
||||||
|
@ -26,7 +30,7 @@ fetch with all fetch styles
|
||||||
}
|
}
|
||||||
|
|
||||||
print( "\n---------- PDO::FETCH_INTO -------------\n" );
|
print( "\n---------- PDO::FETCH_INTO -------------\n" );
|
||||||
$stmt = $conn->query( "select * from HumanResources.Department order by GroupName" );
|
$stmt = $conn->query( "select DepartmentID, Name, GroupName from HumanResources.Department order by GroupName" );
|
||||||
$c_obj = new cc( '' );
|
$c_obj = new cc( '' );
|
||||||
|
|
||||||
$stmt->setFetchMode(PDO::FETCH_INTO, $c_obj);
|
$stmt->setFetchMode(PDO::FETCH_INTO, $c_obj);
|
||||||
|
|
|
@ -25,6 +25,10 @@ fetches the rows in a result set in an array
|
||||||
print "\n-----------\n";
|
print "\n-----------\n";
|
||||||
|
|
||||||
class cc {
|
class cc {
|
||||||
|
public $ContactTypeID;
|
||||||
|
public $Name;
|
||||||
|
public $ModifiedDate;
|
||||||
|
|
||||||
function __construct( $arg ) {
|
function __construct( $arg ) {
|
||||||
echo "$arg\n";
|
echo "$arg\n";
|
||||||
}
|
}
|
||||||
|
@ -34,7 +38,7 @@ fetches the rows in a result set in an array
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$stmt = $conn->query( 'SELECT TOP(2) * FROM Person.ContactType' );
|
$stmt = $conn->query( 'SELECT TOP(2) ContactTypeID, Name, ModifiedDate FROM Person.ContactType' );
|
||||||
$all = $stmt->fetchAll( PDO::FETCH_CLASS, 'cc', array( 'Hi!' ));
|
$all = $stmt->fetchAll( PDO::FETCH_CLASS, 'cc', array( 'Hi!' ));
|
||||||
var_dump( $all );
|
var_dump( $all );
|
||||||
|
|
||||||
|
|
|
@ -26,9 +26,13 @@ while ( $row = $stmt->fetch() ){
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "\n........ query with a new class ............\n";
|
echo "\n........ query with a new class ............\n";
|
||||||
$query = 'select * from HumanResources.Department order by GroupName';
|
$query = 'select DepartmentID, Name, GroupName from HumanResources.Department order by GroupName';
|
||||||
// query with a class
|
// query with a class
|
||||||
class cc {
|
class cc {
|
||||||
|
public $DepartmentID;
|
||||||
|
public $Name;
|
||||||
|
public $GroupName;
|
||||||
|
|
||||||
function __construct( $arg ) {
|
function __construct( $arg ) {
|
||||||
echo "$arg";
|
echo "$arg";
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ $tsql1 = "UPDATE Production.ProductReview
|
||||||
//
|
//
|
||||||
$reviewID = 3;
|
$reviewID = 3;
|
||||||
|
|
||||||
$comments = utf8_encode("testing 1, 2, 3, 4. Testing.");
|
$comments = mb_convert_encoding("testing 1, 2, 3, 4. Testing.", 'ISO-8859-1', 'UTF-8');
|
||||||
$params1 = array(
|
$params1 = array(
|
||||||
array( $comments, null ),
|
array( $comments, null ),
|
||||||
array( $reviewID, null )
|
array( $reviewID, null )
|
||||||
|
|
|
@ -7,6 +7,8 @@ retrieves each row of a result set as an instance of the Product class defined i
|
||||||
/* Define the Product class. */
|
/* Define the Product class. */
|
||||||
class Product
|
class Product
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/* Constructor */
|
/* Constructor */
|
||||||
public function ProductConstruct($ID)
|
public function ProductConstruct($ID)
|
||||||
{
|
{
|
||||||
|
@ -17,6 +19,8 @@ class Product
|
||||||
public $StockedQty;
|
public $StockedQty;
|
||||||
public $SafetyStockLevel;
|
public $SafetyStockLevel;
|
||||||
private $UnitPrice;
|
private $UnitPrice;
|
||||||
|
public $Name;
|
||||||
|
public $Color;
|
||||||
function getPrice()
|
function getPrice()
|
||||||
{
|
{
|
||||||
return $this->UnitPrice;
|
return $this->UnitPrice;
|
||||||
|
|
|
@ -27,7 +27,7 @@ $tsql1 = "UPDATE Production.ProductReview
|
||||||
// utf8_encode to simulate an application that uses UTF-8 encoded data.
|
// utf8_encode to simulate an application that uses UTF-8 encoded data.
|
||||||
//
|
//
|
||||||
$reviewID = 3;
|
$reviewID = 3;
|
||||||
$comments = utf8_encode("testing");
|
$comments = mb_convert_encoding("testing", 'ISO-8859-1', 'UTF-8');
|
||||||
$params1 = array(
|
$params1 = array(
|
||||||
array($comments,
|
array($comments,
|
||||||
SQLSRV_PARAM_IN,
|
SQLSRV_PARAM_IN,
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
Common functions (shared by all tests).
|
Common functions (shared by all tests).
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
error_reporting( ~E_DEPRECATED );
|
||||||
$tvpIncPath = dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'inc'.DIRECTORY_SEPARATOR;
|
$tvpIncPath = dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'inc'.DIRECTORY_SEPARATOR;
|
||||||
|
|
||||||
require_once($tvpIncPath. 'test_tvp_data.php');
|
require_once($tvpIncPath. 'test_tvp_data.php');
|
||||||
|
@ -1840,4 +1840,4 @@ function compareResourceToInput($actual, $expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
return $matched;
|
return $matched;
|
||||||
}
|
}
|
|
@ -59,6 +59,7 @@ function ExecStmt()
|
||||||
EndTest($testName);
|
EndTest($testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class Test
|
class Test
|
||||||
{
|
{
|
||||||
function __construct($name = 'N/A')
|
function __construct($name = 'N/A')
|
||||||
|
|
|
@ -48,6 +48,7 @@ function FetchMode()
|
||||||
EndTest($testName);
|
EndTest($testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class Test
|
class Test
|
||||||
{
|
{
|
||||||
function __construct($name = 'N/A')
|
function __construct($name = 'N/A')
|
||||||
|
|
|
@ -72,6 +72,7 @@ function FetchAll()
|
||||||
EndTest($testName);
|
EndTest($testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class Test1
|
class Test1
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
@ -80,6 +81,7 @@ class Test1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class Test2
|
class Test2
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
@ -88,6 +90,7 @@ class Test2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class Test3
|
class Test3
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
|
|
|
@ -64,6 +64,7 @@ function FetchAll()
|
||||||
EndTest($testName);
|
EndTest($testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class DerivedStatement extends PDOStatement
|
class DerivedStatement extends PDOStatement
|
||||||
{
|
{
|
||||||
private function __construct($name, $conn)
|
private function __construct($name, $conn)
|
||||||
|
@ -78,6 +79,7 @@ class DerivedStatement extends PDOStatement
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class Test1
|
class Test1
|
||||||
{
|
{
|
||||||
public function __construct($id, $val)
|
public function __construct($id, $val)
|
||||||
|
|
|
@ -10,6 +10,7 @@ PHPT_EXEC=true
|
||||||
<?php
|
<?php
|
||||||
include 'MsCommon.inc';
|
include 'MsCommon.inc';
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class TestClass
|
class TestClass
|
||||||
{
|
{
|
||||||
private $set_calls = 0;
|
private $set_calls = 0;
|
||||||
|
|
|
@ -48,6 +48,7 @@ function Extend()
|
||||||
EndTest($testName);
|
EndTest($testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class ExPDO extends PDO
|
class ExPDO extends PDO
|
||||||
{
|
{
|
||||||
public $test1 = 1;
|
public $test1 = 1;
|
||||||
|
@ -74,6 +75,7 @@ class ExPDO extends PDO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class ExPDOStatement extends PDOStatement
|
class ExPDOStatement extends PDOStatement
|
||||||
{
|
{
|
||||||
protected function __construct()
|
protected function __construct()
|
||||||
|
|
|
@ -46,27 +46,31 @@ function Extend()
|
||||||
EndTest($testName);
|
EndTest($testName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class ExPDO extends PDO
|
class ExPDO extends PDO
|
||||||
{
|
{
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->protocol();
|
$this->protocol();
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
return (call_user_func_array(array($this, 'parent::__construct'), $args));
|
$callable = parent::class . '::__construct';
|
||||||
|
return (call_user_func_array($callable, $args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exec(string $args1) : int|false
|
public function exec(string $args1) : int|false
|
||||||
{
|
{
|
||||||
$this->protocol();
|
$this->protocol();
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
return (call_user_func_array(array($this, 'parent::exec'), $args));
|
$callable = parent::class . '::exec';
|
||||||
|
return (call_user_func_array($callable, $args));
|
||||||
}
|
}
|
||||||
|
|
||||||
function query(string $sql, ?int $fetchMode = null, mixed ...$fetchModeArgs): PDOStatement|false
|
function query(string $sql, ?int $fetchMode = null, mixed ...$fetchModeArgs): PDOStatement|false
|
||||||
{
|
{
|
||||||
$this->protocol();
|
$this->protocol();
|
||||||
$args = func_get_args();
|
$args = func_get_args();
|
||||||
return (call_user_func_array(array($this, 'parent::query'), $args));
|
$callable = parent::class . '::query';
|
||||||
|
return (call_user_func_array($callable, $args));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __call($method, $args)
|
public function __call($method, $args)
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
--TEST--
|
||||||
|
GitHub issue 1391 - string truncation error when binding some parameters as longer strings the second time
|
||||||
|
--DESCRIPTION--
|
||||||
|
The test shows the same parameters, though bound as short strings in the first insertion, can be bound as longer strings in the subsequent insertions.
|
||||||
|
--ENV--
|
||||||
|
PHPT_EXEC=true
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require('skipif.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once("MsSetup.inc");
|
||||||
|
|
||||||
|
function dropTable($conn, $tableName)
|
||||||
|
{
|
||||||
|
$drop = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'" . $tableName . "') AND type in (N'U')) DROP TABLE $tableName";
|
||||||
|
$conn->exec($drop);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn = new PDO("sqlsrv:server=$server; Database = $databaseName;", $uid, $pwd);
|
||||||
|
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
|
||||||
|
dropTable($conn, 'long_strings');
|
||||||
|
|
||||||
|
$tsql = <<<CREATESQL
|
||||||
|
CREATE TABLE long_strings (
|
||||||
|
id bigint IDENTITY(1,1) NOT NULL,
|
||||||
|
four_thousand varchar(4002) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||||
|
var_max varchar(max) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
|
||||||
|
nvar_max varchar(max) NOT NULL,
|
||||||
|
CONSTRAINT PK__long_strings__1391E83F512B1391 PRIMARY KEY (id))
|
||||||
|
CREATESQL;
|
||||||
|
|
||||||
|
$conn->exec($tsql);
|
||||||
|
|
||||||
|
$tsql = <<<INSERTSQL
|
||||||
|
INSERT INTO long_strings (four_thousand, var_max, nvar_max) VALUES (?, ?, ?)
|
||||||
|
INSERTSQL;
|
||||||
|
|
||||||
|
$stmt = $conn->prepare($tsql);
|
||||||
|
|
||||||
|
// Bind and execute short string values first
|
||||||
|
$fourThousand = '4';
|
||||||
|
$varMax = 'v';
|
||||||
|
$nvarMax = 'n';
|
||||||
|
$stmt->bindParam(1, $fourThousand);
|
||||||
|
$stmt->bindParam(2, $varMax);
|
||||||
|
$stmt->bindParam(3, $nvarMax);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
// Bind and execute long string values second, on same $stmt
|
||||||
|
$fourThousand = str_repeat('4', 4001);
|
||||||
|
$varMax = str_repeat('v', 4001);
|
||||||
|
$nvarMax = str_repeat('n', 4001);
|
||||||
|
$stmt->bindParam(1, $fourThousand);
|
||||||
|
$stmt->bindParam(2, $varMax);
|
||||||
|
$stmt->bindParam(3, $nvarMax);
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
// fetch the data
|
||||||
|
$stmt = $conn->prepare("SELECT COUNT(*) FROM long_strings");
|
||||||
|
$stmt->execute();
|
||||||
|
$row = $stmt->fetch(PDO::FETCH_NUM);
|
||||||
|
echo $row[0]."\n";
|
||||||
|
|
||||||
|
dropTable($conn, 'long_strings');
|
||||||
|
|
||||||
|
echo "Done\n";
|
||||||
|
} catch (PdoException $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
2
|
||||||
|
Done
|
|
@ -3,7 +3,11 @@ Test some error conditions of Azure AD Managed Identity support
|
||||||
--DESCRIPTION--
|
--DESCRIPTION--
|
||||||
This test expects certain exceptions to be thrown under some conditions.
|
This test expects certain exceptions to be thrown under some conditions.
|
||||||
--SKIPIF--
|
--SKIPIF--
|
||||||
<?php require('skipif.inc');?>
|
<?php
|
||||||
|
require('skipif.inc');
|
||||||
|
require('skipif_Appveyor.inc');
|
||||||
|
require('skipif_unix.inc');
|
||||||
|
?>
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
require_once("MsCommon_mid-refactor.inc");
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
@ -41,7 +45,9 @@ function connectInvalidServer()
|
||||||
$conn = new PDO("sqlsrv:server = invalidServer; $connectionInfo", null, null);
|
$conn = new PDO("sqlsrv:server = invalidServer; $connectionInfo", null, null);
|
||||||
echo $message . $testCase . PHP_EOL;
|
echo $message . $testCase . PHP_EOL;
|
||||||
} catch(PDOException $e) {
|
} catch(PDOException $e) {
|
||||||
// TODO: check the exception message here
|
echo "Failed to connect\n";
|
||||||
|
print_r($e->getMessage());
|
||||||
|
echo "\n";
|
||||||
}
|
}
|
||||||
} catch(PDOException $e) {
|
} catch(PDOException $e) {
|
||||||
print_r($e->getMessage());
|
print_r($e->getMessage());
|
||||||
|
@ -72,7 +78,9 @@ function connectInvalidServerWithUser()
|
||||||
$conn = new PDO("sqlsrv:server = invalidServer; $connectionInfo", $user, null);
|
$conn = new PDO("sqlsrv:server = invalidServer; $connectionInfo", $user, null);
|
||||||
echo $message . $testCase . PHP_EOL;
|
echo $message . $testCase . PHP_EOL;
|
||||||
} catch(PDOException $e) {
|
} catch(PDOException $e) {
|
||||||
// TODO: check the exception message here
|
echo "Failed to connect\n";
|
||||||
|
print_r($e->getMessage());
|
||||||
|
echo "\n";
|
||||||
}
|
}
|
||||||
} catch(PDOException $e) {
|
} catch(PDOException $e) {
|
||||||
print_r($e->getMessage());
|
print_r($e->getMessage());
|
||||||
|
@ -82,10 +90,15 @@ function connectInvalidServerWithUser()
|
||||||
require_once('MsSetup.inc');
|
require_once('MsSetup.inc');
|
||||||
|
|
||||||
// Make a connection to an invalid server
|
// Make a connection to an invalid server
|
||||||
|
// Expect to get two error messages
|
||||||
connectInvalidServer();
|
connectInvalidServer();
|
||||||
connectInvalidServerWithUser();
|
connectInvalidServerWithUser();
|
||||||
|
|
||||||
echo "Done\n";
|
echo "Done\n";
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
|
Failed to connect
|
||||||
|
SQLSTATE[08001]: [Microsoft][ODBC Driver 17 for SQL Server]Named Pipes Provider: Could not open a connection to SQL Server [53].
|
||||||
|
Failed to connect
|
||||||
|
SQLSTATE[08001]: [Microsoft][ODBC Driver 17 for SQL Server]Named Pipes Provider: Could not open a connection to SQL Server [53].
|
||||||
Done
|
Done
|
||||||
|
|
|
@ -22,7 +22,6 @@ $conn = null;
|
||||||
testValidValues();
|
testValidValues();
|
||||||
testInvalidValues();
|
testInvalidValues();
|
||||||
testEncryptedWithODBC();
|
testEncryptedWithODBC();
|
||||||
testWrongODBC();
|
|
||||||
echo "Done" . PHP_EOL;
|
echo "Done" . PHP_EOL;
|
||||||
// end test
|
// end test
|
||||||
|
|
||||||
|
@ -118,17 +117,6 @@ function testEncryptedWithODBC()
|
||||||
connectVerifyOutput($connectionOptions, "Using ODBC 13 for AE", $expected);
|
connectVerifyOutput($connectionOptions, "Using ODBC 13 for AE", $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testWrongODBC()
|
|
||||||
{
|
|
||||||
global $msodbcsqlMaj;
|
|
||||||
|
|
||||||
$value = "ODBC Driver 18 for SQL Server";
|
|
||||||
$connectionOptions = "Driver = $value;";
|
|
||||||
$expected = "The specified ODBC Driver is not found.";
|
|
||||||
|
|
||||||
connectVerifyOutput($connectionOptions, "Connect with ODBC 18", $expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
Done
|
Done
|
||||||
|
|
|
@ -8,6 +8,8 @@ This test should not use temporary table as it might occasionally cause deadlock
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
include 'MsCommon.inc';
|
include 'MsCommon.inc';
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class PdoTestClass
|
class PdoTestClass
|
||||||
{
|
{
|
||||||
function __construct ()
|
function __construct ()
|
||||||
|
@ -16,6 +18,7 @@ class PdoTestClass
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class PdoTestClass2
|
class PdoTestClass2
|
||||||
{
|
{
|
||||||
function __construct ($a1, $a2)
|
function __construct ($a1, $a2)
|
||||||
|
|
|
@ -20,7 +20,7 @@ try {
|
||||||
--EXPECTREGEX--
|
--EXPECTREGEX--
|
||||||
Array
|
Array
|
||||||
\(
|
\(
|
||||||
\[(DriverDllName|DriverName)\] => (msodbcsql1[1-9].dll|(libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib))
|
\[(DriverDllName|DriverName)\] => (msodbcsql1[1-9].dll|(libmsodbcsql-[0-9]{2}\.[0-9]{1,2}\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib))
|
||||||
\[DriverODBCVer\] => [0-9]{1,2}\.[0-9]{1,2}
|
\[DriverODBCVer\] => [0-9]{1,2}\.[0-9]{1,2}
|
||||||
\[DriverVer\] => [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}
|
\[DriverVer\] => [0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}
|
||||||
\[ExtensionVer\] => [0-9]\.[0-9]+\.[0-9](-(RC[1-9]?|beta[1-9]))?(\.[0-9]+)?(\+[0-9]+)?
|
\[ExtensionVer\] => [0-9]\.[0-9]+\.[0-9](-(RC[1-9]?|beta[1-9]))?(\.[0-9]+)?(\+[0-9]+)?
|
||||||
|
|
|
@ -125,7 +125,7 @@ SQLSTATE\[IMSSP\]: A read-only attribute was designated on the PDO object.
|
||||||
Get Result PDO::ATTR_CLIENT_VERSION :
|
Get Result PDO::ATTR_CLIENT_VERSION :
|
||||||
array\(4\) {
|
array\(4\) {
|
||||||
\[\"(DriverDllName|DriverName)\"\]=>
|
\[\"(DriverDllName|DriverName)\"\]=>
|
||||||
(string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\")
|
(string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]{1,2}\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\")
|
||||||
\["DriverODBCVer"\]=>
|
\["DriverODBCVer"\]=>
|
||||||
string\(5\) \"[0-9]{1,2}\.[0-9]{1,2}\"
|
string\(5\) \"[0-9]{1,2}\.[0-9]{1,2}\"
|
||||||
\["DriverVer"\]=>
|
\["DriverVer"\]=>
|
||||||
|
|
|
@ -8,6 +8,7 @@ ORDER BY should work with sql_variants
|
||||||
<?php
|
<?php
|
||||||
require_once("MsCommon_mid-refactor.inc");
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class Food
|
class Food
|
||||||
{
|
{
|
||||||
public function getFood()
|
public function getFood()
|
||||||
|
|
|
@ -24,6 +24,6 @@ if ($c !== false) {
|
||||||
|
|
||||||
Fatal error: Uncaught PDOException: SQLSTATE\[(28000|08001|HYT00)\]: .*\[Microsoft\]\[ODBC Driver 1[0-9] for SQL Server\](\[SQL Server\])?(Named Pipes Provider: Could not open a connection to SQL Server \[2\]\. |TCP Provider: Error code (0x2726|0x2AF9)|Login timeout expired|Login failed for user 'sa'\.) in .+(\/|\\)pdo_utf8_conn\.php:[0-9]+
|
Fatal error: Uncaught PDOException: SQLSTATE\[(28000|08001|HYT00)\]: .*\[Microsoft\]\[ODBC Driver 1[0-9] for SQL Server\](\[SQL Server\])?(Named Pipes Provider: Could not open a connection to SQL Server \[2\]\. |TCP Provider: Error code (0x2726|0x2AF9)|Login timeout expired|Login failed for user 'sa'\.) in .+(\/|\\)pdo_utf8_conn\.php:[0-9]+
|
||||||
Stack trace:
|
Stack trace:
|
||||||
#0 .+(\/|\\)pdo_utf8_conn\.php\([0-9]+\): PDO->__construct(\(\)|\('sqlsrv:Server=l\.\.\.', 'sa', 'Sunshine4u'\))
|
#0 .+(\/|\\)pdo_utf8_conn\.php\([0-9]+\): PDO->__construct(\(\)|\('sqlsrv:Server=l\.\.\.', 'sa', ('Sunshine4u'|Object\(SensitiveParameterValue\))\))
|
||||||
#1 {main}
|
#1 {main}
|
||||||
thrown in .+(\/|\\)pdo_utf8_conn\.php on line [0-9]+
|
thrown in .+(\/|\\)pdo_utf8_conn\.php on line [0-9]+
|
||||||
|
|
4
test/functional/pdo_sqlsrv/skipif_Appveyor.inc
Normal file
4
test/functional/pdo_sqlsrv/skipif_Appveyor.inc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?php
|
||||||
|
if (getenv('APPVEYOR')) {
|
||||||
|
die("skip Appveyor pipeline");
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ require('skipif_versions_old.inc');
|
||||||
<?php
|
<?php
|
||||||
require_once('MsCommon.inc');
|
require_once('MsCommon.inc');
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class TestClass
|
class TestClass
|
||||||
{
|
{
|
||||||
public function __construct($a1, $a2, $a3)
|
public function __construct($a1, $a2, $a3)
|
||||||
|
|
|
@ -15,7 +15,7 @@ var_dump( $client_info );
|
||||||
--EXPECTREGEX--
|
--EXPECTREGEX--
|
||||||
array\(4\) {
|
array\(4\) {
|
||||||
\[\"(DriverDllName|DriverName)\"\]=>
|
\[\"(DriverDllName|DriverName)\"\]=>
|
||||||
(string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\")
|
(string\([0-9]+\) \"msodbcsql1[1-9].dll\"|string\([0-9]+\) \"(libmsodbcsql-[0-9]{2}\.[0-9]{1,2}\.so\.[0-9]\.[0-9]|libmsodbcsql.[0-9]{2}.dylib)\")
|
||||||
\[\"DriverODBCVer\"\]=>
|
\[\"DriverODBCVer\"\]=>
|
||||||
string\(5\) \"[0-9]{1,2}\.[0-9]{1,2}\"
|
string\(5\) \"[0-9]{1,2}\.[0-9]{1,2}\"
|
||||||
\[\"DriverVer\"\]=>
|
\[\"DriverVer\"\]=>
|
||||||
|
|
|
@ -20,7 +20,6 @@ sqlsrv_close($conn);
|
||||||
testValidValues($msodbcsqlMaj, $server, $connectionOptions);
|
testValidValues($msodbcsqlMaj, $server, $connectionOptions);
|
||||||
testInvalidValues($msodbcsqlMaj, $server, $connectionOptions);
|
testInvalidValues($msodbcsqlMaj, $server, $connectionOptions);
|
||||||
testEncryptedWithODBC($msodbcsqlMaj, $server, $connectionOptions);
|
testEncryptedWithODBC($msodbcsqlMaj, $server, $connectionOptions);
|
||||||
testWrongODBC($msodbcsqlMaj, $server, $connectionOptions);
|
|
||||||
echo "Done\n";
|
echo "Done\n";
|
||||||
// end test
|
// end test
|
||||||
|
|
||||||
|
@ -115,15 +114,6 @@ function testEncryptedWithODBC($msodbcsqlMaj, $server, $connectionOptions)
|
||||||
connectVerifyOutput($server, $connectionOptions, "Using ODBC 13 for AE", $expected);
|
connectVerifyOutput($server, $connectionOptions, "Using ODBC 13 for AE", $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testWrongODBC($msodbcsqlMaj, $server, $connectionOptions)
|
|
||||||
{
|
|
||||||
$value = "ODBC Driver 18 for SQL Server";
|
|
||||||
$connectionOptions['Driver']=$value;
|
|
||||||
$expected = "The specified ODBC Driver is not found.";
|
|
||||||
|
|
||||||
connectVerifyOutput($server, $connectionOptions, "Connect with ODBC 18", $expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECT--
|
--EXPECT--
|
||||||
Done
|
Done
|
||||||
|
|
|
@ -61,7 +61,7 @@ function isDataClassSupported($conn, &$driverCapable)
|
||||||
|
|
||||||
// ODBC Driver must be 17.2 or above
|
// ODBC Driver must be 17.2 or above
|
||||||
$driverCapable = true;
|
$driverCapable = true;
|
||||||
if ($version[0] < 17 || $version[1] < 2) {
|
if ($version[0] < 17 || ($version[0] == 17 && $version[1] < 2)) {
|
||||||
$driverCapable = false;
|
$driverCapable = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ function isDataClassSupported($conn, &$driverCapable)
|
||||||
|
|
||||||
// ODBC Driver must be 17.2 or above
|
// ODBC Driver must be 17.2 or above
|
||||||
$driverCapable = true;
|
$driverCapable = true;
|
||||||
if ($version[0] < 17 || $version[1] < 2) {
|
if ($version[0] < 17 || ($version[0] == 17 && $version[1] < 2)) {
|
||||||
$driverCapable = false;
|
$driverCapable = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ Test for fetch_object
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class foo
|
class foo
|
||||||
{
|
{
|
||||||
public $stuff = "stuff";
|
public $stuff = "stuff";
|
||||||
|
@ -25,6 +26,7 @@ class foo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class foo_noargs
|
class foo_noargs
|
||||||
{
|
{
|
||||||
public $stuff = "stuff";
|
public $stuff = "stuff";
|
||||||
|
|
|
@ -5,6 +5,7 @@ Test for fetch_object
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class foo
|
class foo
|
||||||
{
|
{
|
||||||
public $stuff = "stuff";
|
public $stuff = "stuff";
|
||||||
|
@ -25,6 +26,7 @@ class foo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class foo_noargs
|
class foo_noargs
|
||||||
{
|
{
|
||||||
public $stuff = "stuff";
|
public $stuff = "stuff";
|
||||||
|
|
|
@ -4,6 +4,7 @@ Test insert various data types and fetch as strings
|
||||||
<?php
|
<?php
|
||||||
require_once('MsCommon.inc');
|
require_once('MsCommon.inc');
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class TestClass2
|
class TestClass2
|
||||||
{
|
{
|
||||||
public function __construct($a1, $a2)
|
public function __construct($a1, $a2)
|
||||||
|
@ -12,6 +13,7 @@ class TestClass2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class TestClass3
|
class TestClass3
|
||||||
{
|
{
|
||||||
public function __construct($a1, $a2, $a3)
|
public function __construct($a1, $a2, $a3)
|
||||||
|
|
|
@ -5,6 +5,7 @@ Test for fetch_object with Unicode column name
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class foo
|
class foo
|
||||||
{
|
{
|
||||||
public $stuff = "stuff";
|
public $stuff = "stuff";
|
||||||
|
@ -25,6 +26,7 @@ class foo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class foo_noargs
|
class foo_noargs
|
||||||
{
|
{
|
||||||
public $stuff = "stuff";
|
public $stuff = "stuff";
|
||||||
|
|
|
@ -6,6 +6,7 @@ sqlsrv_fetch_object() into a class with Unicode column name
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
// Define the Product class
|
// Define the Product class
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class Product
|
class Product
|
||||||
{
|
{
|
||||||
public function __construct($ID, $UID)
|
public function __construct($ID, $UID)
|
||||||
|
@ -37,6 +38,7 @@ class Product
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class Sample extends Product
|
class Sample extends Product
|
||||||
{
|
{
|
||||||
public function __construct($ID)
|
public function __construct($ID)
|
||||||
|
|
|
@ -4,6 +4,8 @@ Send a large amount (10MB) using encryption. In a Linux CI environment use a sma
|
||||||
<?php require('skipif_azure_dw.inc'); ?>
|
<?php require('skipif_azure_dw.inc'); ?>
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
#[AllowDynamicProperties]
|
||||||
class my_stream
|
class my_stream
|
||||||
{
|
{
|
||||||
public $total_read = 0;
|
public $total_read = 0;
|
||||||
|
|
Loading…
Reference in a new issue