Merge remote-tracking branch 'upstream/dev' into 520changelog
This commit is contained in:
commit
f995a8585a
110
.travis.yml
110
.travis.yml
|
@ -1,58 +1,52 @@
|
|||
sudo: required
|
||||
|
||||
os: linux
|
||||
dist: trusty
|
||||
|
||||
group: edge
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
env:
|
||||
global:
|
||||
- REPORT_EXIT_STATUS=1
|
||||
- ACCEPT_EULA=Y
|
||||
- PHPSQLDIR=/REPO/msphpsql-dev
|
||||
- TEST_PHP_SQL_SERVER=sql
|
||||
- SQLSRV_DBNAME=msphpsql_sqlsrv
|
||||
- PDOSQLSRV_DBNAME=msphpsql_pdosqlsrv
|
||||
- TEST_PHP_SQL_UID=sa
|
||||
- TEST_PHP_SQL_PWD=Password123
|
||||
|
||||
before_install:
|
||||
- docker pull microsoft/mssql-server-linux:2017-latest
|
||||
|
||||
install:
|
||||
- docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Password123' -p 1433:1433 --name=$TEST_PHP_SQL_SERVER -d microsoft/mssql-server-linux:2017-latest
|
||||
- docker build --build-arg PHPSQLDIR=$PHPSQLDIR -t msphpsql-dev -f Dockerfile-msphpsql .
|
||||
|
||||
before_script:
|
||||
- sleep 30
|
||||
|
||||
script:
|
||||
- travis_retry docker run -e TRAVIS_JOB_ID -t -d -w $PHPSQLDIR --name=client --link $TEST_PHP_SQL_SERVER msphpsql-dev
|
||||
- docker ps -a
|
||||
- docker logs client
|
||||
- travis_retry docker exec client python ./test/functional/setup/setup_dbs.py -dbname $SQLSRV_DBNAME
|
||||
- travis_retry docker exec client python ./test/functional/setup/setup_dbs.py -dbname $PDOSQLSRV_DBNAME
|
||||
- docker exec client cp ./source/shared/msodbcsql.h ./test/functional/setup/
|
||||
- travis_retry docker exec client python ./test/functional/setup/build_ksp.py
|
||||
- docker exec client cp ./test/functional/setup/myKSP.so ./test/functional/sqlsrv/
|
||||
- docker exec client cp ./test/functional/setup/myKSP.so ./test/functional/pdo_sqlsrv/
|
||||
- travis_retry docker exec client python ./test/functional/setup/run_ksp.py -server $TEST_PHP_SQL_SERVER -dbname $SQLSRV_DBNAME -uid $TEST_PHP_SQL_UID -pwd $TEST_PHP_SQL_PWD
|
||||
- travis_retry docker exec client python ./test/functional/setup/run_ksp.py -server $TEST_PHP_SQL_SERVER -dbname $PDOSQLSRV_DBNAME -uid $TEST_PHP_SQL_UID -pwd $TEST_PHP_SQL_PWD
|
||||
- travis_retry docker exec client php ./source/pdo_sqlsrv/run-tests.php ./test/functional/pdo_sqlsrv/*.phpt
|
||||
- travis_retry docker exec client php ./source/sqlsrv/run-tests.php ./test/functional/sqlsrv/*.phpt
|
||||
- docker exec client bash -c 'for f in ./test/functional/sqlsrv/*.diff; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
|
||||
- docker exec client bash -c 'for f in ./test/functional/sqlsrv/*.out; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
|
||||
- docker exec client bash -c 'for f in ./test/functional/pdo_sqlsrv/*.diff; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
|
||||
- docker exec client bash -c 'for f in ./test/functional/pdo_sqlsrv/*.out; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
|
||||
- docker exec client python ./test/functional/setup/cleanup_dbs.py -dbname $SQLSRV_DBNAME
|
||||
- docker exec client python ./test/functional/setup/cleanup_dbs.py -dbname $PDOSQLSRV_DBNAME
|
||||
- docker exec client coveralls -e ./source/shared/ --gcov-options '\-lp'
|
||||
- docker stop client
|
||||
- docker ps -a
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
sudo: required
|
||||
|
||||
os: linux
|
||||
dist: trusty
|
||||
|
||||
group: edge
|
||||
|
||||
services:
|
||||
- docker
|
||||
|
||||
env:
|
||||
global:
|
||||
- REPORT_EXIT_STATUS=1
|
||||
- ACCEPT_EULA=Y
|
||||
- PHPSQLDIR=/REPO/msphpsql-dev
|
||||
- TEST_PHP_SQL_SERVER=sql
|
||||
- SQLSRV_DBNAME=msphpsql_sqlsrv
|
||||
- PDOSQLSRV_DBNAME=msphpsql_pdosqlsrv
|
||||
- TEST_PHP_SQL_UID=sa
|
||||
- TEST_PHP_SQL_PWD=Password123
|
||||
|
||||
before_install:
|
||||
- docker pull microsoft/mssql-server-linux:2017-latest
|
||||
|
||||
install:
|
||||
- docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Password123' -p 1433:1433 --name=$TEST_PHP_SQL_SERVER -d microsoft/mssql-server-linux:2017-latest
|
||||
- docker build --build-arg PHPSQLDIR=$PHPSQLDIR -t msphpsql-dev -f Dockerfile-msphpsql .
|
||||
|
||||
before_script:
|
||||
- sleep 30
|
||||
|
||||
script:
|
||||
- travis_retry docker run -e TRAVIS_JOB_ID -t -d -w $PHPSQLDIR --name=client --link $TEST_PHP_SQL_SERVER msphpsql-dev
|
||||
- docker ps -a
|
||||
- docker logs client
|
||||
- travis_retry docker exec client python ./test/functional/setup/setup_dbs.py -dbname $SQLSRV_DBNAME
|
||||
- travis_retry docker exec client python ./test/functional/setup/setup_dbs.py -dbname $PDOSQLSRV_DBNAME
|
||||
- travis_retry docker exec client php ./source/pdo_sqlsrv/run-tests.php ./test/functional/pdo_sqlsrv/*.phpt
|
||||
- travis_retry docker exec client php ./source/sqlsrv/run-tests.php ./test/functional/sqlsrv/*.phpt
|
||||
- docker exec client bash -c 'for f in ./test/functional/sqlsrv/*.diff; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
|
||||
- docker exec client bash -c 'for f in ./test/functional/sqlsrv/*.out; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
|
||||
- docker exec client bash -c 'for f in ./test/functional/pdo_sqlsrv/*.diff; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
|
||||
- docker exec client bash -c 'for f in ./test/functional/pdo_sqlsrv/*.out; do ls $f 2>/dev/null; cat $f 2>/dev/null; done || true'
|
||||
- docker exec client python ./test/functional/setup/cleanup_dbs.py -dbname $SQLSRV_DBNAME
|
||||
- docker exec client python ./test/functional/setup/cleanup_dbs.py -dbname $PDOSQLSRV_DBNAME
|
||||
- docker exec client coveralls -e ./source/shared/ --gcov-options '\-lp'
|
||||
- docker stop client
|
||||
- docker ps -a
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
|
|
37
appveyor.yml
37
appveyor.yml
|
@ -78,20 +78,24 @@ install:
|
|||
|
||||
Set-Service SQLBrowser -StartupType Manual;
|
||||
Start-Service SQLBrowser;
|
||||
- echo Set PHP version...
|
||||
- appveyor DownloadFile http://windows.php.net/downloads/releases/sha1sum.txt
|
||||
# determine latest PHP versions
|
||||
- ps: >-
|
||||
- echo Downloading prerequisites
|
||||
- ps: |
|
||||
$client = New-Object Net.WebClient;
|
||||
$client.Headers.Add("user-agent", "appveyor-ci-build1");
|
||||
$client.DownloadFile("http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip", "c:\projects\php-sdk-binary-tools-20110915.zip");
|
||||
- ps: |
|
||||
$client = New-Object Net.WebClient;
|
||||
$client.Headers.Add("user-agent", "appveyor-ci-build2");
|
||||
$client.DownloadFile("http://windows.php.net/downloads/releases/sha1sum.txt", "c:\projects\sha1sum.txt");
|
||||
If ($env:PHP_MINOR_VER -Match "latest") {
|
||||
$env:PHP_VERSION=type sha1sum.txt | where { $_ -match "php-($env:PHP_MAJOR_VER\.\d+)-src" } | foreach { $matches[1] } ;
|
||||
$env:PHP_VERSION=type c:\projects\sha1sum.txt | where { $_ -match "php-($env:PHP_MAJOR_VER\.\d+)-src" } | foreach { $matches[1] } ;
|
||||
} Else {
|
||||
$env:PHP_VERSION=$env:PHP_MAJOR_VER + '.' + $env:PHP_MINOR_VER;
|
||||
}
|
||||
- echo Downloading PHP-SDK
|
||||
- appveyor DownloadFile http://windows.php.net/downloads/php-sdk/php-sdk-binary-tools-20110915.zip
|
||||
- move php-sdk-binary-tools-20110915.zip ..
|
||||
- echo Downloading PHP source code [%PHP_VERSION%]
|
||||
- ps: (new-object net.webclient).DownloadFile('http://windows.php.net/downloads/releases/php-' + ${env:PHP_VERSION} + '-src.zip', ${env:APPVEYOR_BUILD_FOLDER} + '\..\php.zip')
|
||||
- ps: |
|
||||
$client = New-Object Net.WebClient;
|
||||
$client.Headers.Add("user-agent", "appveyor-ci-build3");
|
||||
$client.DownloadFile("http://windows.php.net/downloads/releases/php-" + ${env:PHP_VERSION} + "-src.zip", ${env:APPVEYOR_BUILD_FOLDER} + "\..\php.zip");
|
||||
- echo Downloading MSODBCSQL 13.1
|
||||
# AppVeyor build works are x64 VMs and 32-bit ODBC driver cannot be installed on it
|
||||
- ps: (new-object net.webclient).DownloadFile('https://download.microsoft.com/download/D/5/E/D5EEF288-A277-45C8-855B-8E2CB7E25B96/x64/msodbcsql.msi', 'c:\projects\msodbcsql.msi')
|
||||
|
@ -99,10 +103,9 @@ install:
|
|||
- echo Checking the version of MSODBCSQL
|
||||
- reg query "HKLM\SOFTWARE\ODBC\odbcinst.ini\ODBC Driver 13 for SQL Server"
|
||||
- dir C:\Windows\System32\msodbcsql13.dll
|
||||
- cd ..
|
||||
- cd
|
||||
- 7z x -y php-sdk-binary-tools-20110915.zip -o%PHP_SDK%
|
||||
- 7z x -y php.zip -o%PHP_SDK_DIR%
|
||||
- cd c:\projects
|
||||
- 7z x -y .\php-sdk-binary-tools-20110915.zip -o%PHP_SDK%
|
||||
- 7z x -y .\php.zip -o%PHP_SDK_DIR%
|
||||
- echo update SQL connection string
|
||||
- ps: (Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\functional\pdo_sqlsrv\MsSetup.inc) | ForEach-Object { $_ -replace "TARGET_SERVER", ${env:TEST_PHP_SQL_SERVER} -replace "TARGET_DATABASE", ${env:PDOSQLSRV_DBNAME} -replace "TARGET_USERNAME", ${env:TEST_PHP_SQL_UID} -replace "TARGET_PASSWORD", ${env:TEST_PHP_SQL_PWD} } | Set-Content ${env:APPVEYOR_BUILD_FOLDER}\test\functional\pdo_sqlsrv\MsSetup.inc
|
||||
- ps: Get-Content ${env:APPVEYOR_BUILD_FOLDER}\test\functional\pdo_sqlsrv\MsSetup.inc
|
||||
|
@ -150,12 +153,6 @@ test_script:
|
|||
- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\setup_dbs.py -dbname %SQLSRV_DBNAME%
|
||||
- Echo setup test database for PDO_SQLSRV tests - %PDOSQLSRV_DBNAME%
|
||||
- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\setup_dbs.py -dbname %PDOSQLSRV_DBNAME%
|
||||
#- copy %APPVEYOR_BUILD_FOLDER%\source\shared\msodbcsql.h %APPVEYOR_BUILD_FOLDER%\test\functional\setup\
|
||||
#- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\build_ksp.py
|
||||
#- copy %APPVEYOR_BUILD_FOLDER%\test\functional\setup\*.dll %APPVEYOR_BUILD_FOLDER%\test\functional\sqlsrv\
|
||||
#- copy %APPVEYOR_BUILD_FOLDER%\test\functional\setup\*.dll %APPVEYOR_BUILD_FOLDER%\test\functional\pdo_sqlsrv\
|
||||
#- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\run_ksp.py -server %TEST_PHP_SQL_SERVER% -dbname %SQLSRV_DBNAME% -uid %TEST_PHP_SQL_UID% -pwd %TEST_PHP_SQL_PWD%
|
||||
#- python %APPVEYOR_BUILD_FOLDER%\test\functional\setup\run_ksp.py -server %TEST_PHP_SQL_SERVER% -dbname %PDOSQLSRV_DBNAME% -uid %TEST_PHP_SQL_UID% -pwd %TEST_PHP_SQL_PWD%
|
||||
- ps: >-
|
||||
If ($env:SQL_INSTANCE -Match "SQL2016") {
|
||||
Write-Host "Running phpt tests via OpenCppCoverage..."
|
||||
|
|
|
@ -246,14 +246,13 @@ class BuildUtil(object):
|
|||
driver_dir = os.path.join(source_dir, driver)
|
||||
|
||||
if self.debug_enabled:
|
||||
# Remove the optimization flag in the config file for this driver
|
||||
# because '/O2' option is incompatible with Debug mode
|
||||
print('Removing optimization flag for', driver)
|
||||
# Adding linker flags for creating more debugging information in the binaries
|
||||
print('Adding linker flags for', driver)
|
||||
config_file = os.path.join(driver_dir, 'config.w32')
|
||||
if driver == 'sqlsrv':
|
||||
self.update_file_content(config_file, 'ADD_FLAG( "CFLAGS_SQLSRV", "/O2" );', '')
|
||||
self.update_file_content(config_file, 'ADD_FLAG( "LDFLAGS_SQLSRV", "/NXCOMPAT /DYNAMICBASE /debug /guard:cf" );', 'ADD_FLAG( "LDFLAGS_SQLSRV", "/NXCOMPAT /DYNAMICBASE /debug /guard:cf /debugtype:cv,fixup" );')
|
||||
elif driver == 'pdo_sqlsrv':
|
||||
self.update_file_content(config_file, 'ADD_FLAG( "CFLAGS_PDO_SQLSRV", "/O2" );', '')
|
||||
self.update_file_content(config_file, 'ADD_FLAG( "LDFLAGS_PDO_SQLSRV", "/NXCOMPAT /DYNAMICBASE /debug /guard:cf" );', 'ADD_FLAG( "LDFLAGS_PDO_SQLSRV", "/NXCOMPAT /DYNAMICBASE /debug /guard:cf /debugtype:cv,fixup" );')
|
||||
|
||||
# Update Template.rc
|
||||
template_file = os.path.join(driver_dir, 'template.rc')
|
||||
|
|
|
@ -42,13 +42,9 @@ const char ApplicationIntent[] = "ApplicationIntent";
|
|||
const char AttachDBFileName[] = "AttachDbFileName";
|
||||
const char ConnectionPooling[] = "ConnectionPooling";
|
||||
const char Authentication[] = "Authentication";
|
||||
const char ColumnEncryption[] = "ColumnEncryption";
|
||||
const char Driver[] = "Driver";
|
||||
const char CEKeystoreProvider[] = "CEKeystoreProvider";
|
||||
const char CEKeystoreName[] = "CEKeystoreName";
|
||||
const char CEKeystoreEncryptKey[] = "CEKeystoreEncryptKey";
|
||||
|
||||
#ifdef _WIN32
|
||||
const char ColumnEncryption[] = "ColumnEncryption";
|
||||
const char ConnectRetryCount[] = "ConnectRetryCount";
|
||||
const char ConnectRetryInterval[] = "ConnectRetryInterval";
|
||||
#endif // _WIN32
|
||||
|
@ -226,15 +222,6 @@ const connection_option PDO_CONN_OPTS[] = {
|
|||
CONN_ATTR_BOOL,
|
||||
conn_null_func::func
|
||||
},
|
||||
{
|
||||
PDOConnOptionNames::ColumnEncryption,
|
||||
sizeof(PDOConnOptionNames::ColumnEncryption),
|
||||
SQLSRV_CONN_OPTION_COLUMNENCRYPTION,
|
||||
ODBCConnOptions::ColumnEncryption,
|
||||
sizeof(ODBCConnOptions::ColumnEncryption),
|
||||
CONN_ATTR_STRING,
|
||||
column_encryption_set_func::func
|
||||
},
|
||||
{
|
||||
PDOConnOptionNames::Driver,
|
||||
sizeof(PDOConnOptionNames::Driver),
|
||||
|
@ -244,34 +231,16 @@ const connection_option PDO_CONN_OPTS[] = {
|
|||
CONN_ATTR_STRING,
|
||||
driver_set_func::func
|
||||
},
|
||||
{
|
||||
PDOConnOptionNames::CEKeystoreProvider,
|
||||
sizeof(PDOConnOptionNames::CEKeystoreProvider),
|
||||
SQLSRV_CONN_OPTION_CEKEYSTORE_PROVIDER,
|
||||
ODBCConnOptions::CEKeystoreProvider,
|
||||
sizeof(ODBCConnOptions::CEKeystoreProvider),
|
||||
CONN_ATTR_STRING,
|
||||
ce_ksp_provider_set_func::func
|
||||
},
|
||||
{
|
||||
PDOConnOptionNames::CEKeystoreName,
|
||||
sizeof(PDOConnOptionNames::CEKeystoreName),
|
||||
SQLSRV_CONN_OPTION_CEKEYSTORE_NAME,
|
||||
ODBCConnOptions::CEKeystoreName,
|
||||
sizeof(ODBCConnOptions::CEKeystoreName),
|
||||
CONN_ATTR_STRING,
|
||||
ce_ksp_provider_set_func::func
|
||||
},
|
||||
{
|
||||
PDOConnOptionNames::CEKeystoreEncryptKey,
|
||||
sizeof(PDOConnOptionNames::CEKeystoreEncryptKey),
|
||||
SQLSRV_CONN_OPTION_CEKEYSTORE_ENCRYPT_KEY,
|
||||
ODBCConnOptions::CEKeystoreEncryptKey,
|
||||
sizeof(ODBCConnOptions::CEKeystoreEncryptKey),
|
||||
CONN_ATTR_STRING,
|
||||
ce_ksp_provider_set_func::func
|
||||
},
|
||||
#ifdef _WIN32
|
||||
{
|
||||
PDOConnOptionNames::ColumnEncryption,
|
||||
sizeof(PDOConnOptionNames::ColumnEncryption),
|
||||
SQLSRV_CONN_OPTION_COLUMNENCRYPTION,
|
||||
ODBCConnOptions::ColumnEncryption,
|
||||
sizeof(ODBCConnOptions::ColumnEncryption),
|
||||
CONN_ATTR_STRING,
|
||||
column_encryption_set_func::func
|
||||
},
|
||||
{
|
||||
PDOConnOptionNames::ConnectRetryCount,
|
||||
sizeof( PDOConnOptionNames::ConnectRetryCount ),
|
||||
|
|
|
@ -381,22 +381,6 @@ pdo_error PDO_ERRORS[] = {
|
|||
PDO_SQLSRV_ERROR_INVALID_AUTHENTICATION_OPTION,
|
||||
{ IMSSP, (SQLCHAR*) "Invalid option for the Authentication keyword. Only SqlPassword or ActiveDirectoryPassword is supported.", -73, false }
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_KEYSTORE_NAME_MISSING,
|
||||
{ IMSSP, (SQLCHAR*) "The name of the custom keystore provider is missing.", -74, false}
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_KEYSTORE_PATH_MISSING,
|
||||
{ IMSSP, (SQLCHAR*) "The path to the custom keystore provider is missing.", -75, false}
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_KEYSTORE_KEY_MISSING,
|
||||
{ IMSSP, (SQLCHAR*) "The encryption key for the custom keystore provider is missing.", -76, false}
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_KEYSTORE_INVALID_VALUE,
|
||||
{ IMSSP, (SQLCHAR*) "Invalid value for loading a custom keystore provider.", -77, false}
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_CE_DRIVER_REQUIRED,
|
||||
{ IMSSP, (SQLCHAR*) "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.", -78, false }
|
||||
|
|
|
@ -71,7 +71,6 @@ const char* get_processor_arch( void );
|
|||
void get_server_version( _Inout_ sqlsrv_conn* conn, _Outptr_result_buffer_(len) char** server_version, _Out_ SQLSMALLINT& len TSRMLS_DC );
|
||||
connection_option const* get_connection_option( sqlsrv_conn* conn, _In_ const char* key, _In_ SQLULEN key_len TSRMLS_DC );
|
||||
void common_conn_str_append_func( _In_z_ const char* odbc_name, _In_reads_(val_len) const char* val, _Inout_ size_t val_len, _Inout_ std::string& conn_str TSRMLS_DC );
|
||||
void load_configure_ksp( _Inout_ sqlsrv_conn* conn TSRMLS_DC );
|
||||
}
|
||||
|
||||
// core_sqlsrv_connect
|
||||
|
@ -246,8 +245,6 @@ sqlsrv_conn* core_sqlsrv_connect( _In_ sqlsrv_context& henv_cp, _In_ sqlsrv_cont
|
|||
throw core::CoreException();
|
||||
}
|
||||
|
||||
load_configure_ksp( conn );
|
||||
|
||||
// determine the version of the server we're connected to. The server version is left in the
|
||||
// connection upon return.
|
||||
//
|
||||
|
@ -935,66 +932,6 @@ void determine_server_version( _Inout_ sqlsrv_conn* conn TSRMLS_DC )
|
|||
conn->server_version = version_major;
|
||||
}
|
||||
|
||||
// Column Encryption feature: if a custom keystore provider is specified,
|
||||
// load and configure it when column encryption is enabled, but this step has
|
||||
// to be executed after the connection has been established
|
||||
void load_configure_ksp( _Inout_ sqlsrv_conn* conn TSRMLS_DC )
|
||||
{
|
||||
// If column encryption is not enabled simply do nothing. Otherwise, check if a custom keystore provider
|
||||
// is required for encryption or decryption. Note, in order to load and configure a custom keystore provider,
|
||||
// all KSP fields in conn->ce_option must be defined.
|
||||
if ( ! conn->ce_option.enabled || ! conn->ce_option.ksp_required )
|
||||
return;
|
||||
|
||||
// Do something like the following sample
|
||||
// use the KSP related fields in conn->ce_option
|
||||
// CEKEYSTOREDATA is defined in msodbcsql.h
|
||||
// https://docs.microsoft.com/en-us/sql/connect/odbc/custom-keystore-providers
|
||||
|
||||
CHECK_CUSTOM_ERROR( conn->ce_option.ksp_name == NULL, conn, SQLSRV_ERROR_KEYSTORE_NAME_MISSING) {
|
||||
throw core::CoreException();
|
||||
}
|
||||
|
||||
CHECK_CUSTOM_ERROR( conn->ce_option.ksp_path == NULL, conn, SQLSRV_ERROR_KEYSTORE_PATH_MISSING) {
|
||||
throw core::CoreException();
|
||||
}
|
||||
|
||||
CHECK_CUSTOM_ERROR( conn->ce_option.key_size == 0, conn, SQLSRV_ERROR_KEYSTORE_KEY_MISSING) {
|
||||
throw core::CoreException();
|
||||
}
|
||||
|
||||
char* ksp_name = Z_STRVAL_P( conn->ce_option.ksp_name );
|
||||
char* ksp_path = Z_STRVAL_P( conn->ce_option.ksp_path );
|
||||
unsigned int name_len = static_cast<unsigned int>( Z_STRLEN_P( conn->ce_option.ksp_name ));
|
||||
unsigned int key_size = static_cast<unsigned int>( conn->ce_option.key_size );
|
||||
|
||||
sqlsrv_malloc_auto_ptr<unsigned char> ksp_data;
|
||||
|
||||
ksp_data = reinterpret_cast<unsigned char*>( sqlsrv_malloc( sizeof( CEKEYSTOREDATA ) + key_size ) );
|
||||
|
||||
CEKEYSTOREDATA *pKsd = reinterpret_cast<CEKEYSTOREDATA*>( ksp_data.get() );
|
||||
|
||||
pKsd->dataSize = key_size;
|
||||
|
||||
// First, convert conn->ce_option.ksp_name to a WCHAR version
|
||||
unsigned int wname_len = 0;
|
||||
sqlsrv_malloc_auto_ptr<SQLWCHAR> wksp_name;
|
||||
wksp_name = utf16_string_from_mbcs_string( SQLSRV_ENCODING_UTF8, ksp_name, name_len, &wname_len );
|
||||
|
||||
CHECK_CUSTOM_ERROR( wksp_name == 0, conn, SQLSRV_ERROR_CONNECT_STRING_ENCODING_TRANSLATE ) {
|
||||
throw core::CoreException();
|
||||
}
|
||||
|
||||
pKsd->name = (wchar_t *) wksp_name.get();
|
||||
|
||||
// Next, extract the character string from conn->ce_option.ksp_encrypt_key into encrypt_key
|
||||
char* encrypt_key = Z_STRVAL_P( conn->ce_option.ksp_encrypt_key );
|
||||
memcpy_s( pKsd->data, key_size * sizeof( char ) , encrypt_key, key_size );
|
||||
|
||||
core::SQLSetConnectAttr( conn, SQL_COPT_SS_CEKEYSTOREPROVIDER, ksp_path, SQL_NTS );
|
||||
core::SQLSetConnectAttr( conn, SQL_COPT_SS_CEKEYSTOREDATA, reinterpret_cast<SQLPOINTER>( pKsd ), SQL_IS_POINTER );
|
||||
}
|
||||
|
||||
void common_conn_str_append_func( _In_z_ const char* odbc_name, _In_reads_(val_len) const char* val, _Inout_ size_t val_len, _Inout_ std::string& conn_str TSRMLS_DC )
|
||||
{
|
||||
// wrap a connection option in a quote. It is presumed that any character that need to be escaped will
|
||||
|
@ -1068,36 +1005,6 @@ void column_encryption_set_func::func( _In_ connection_option const* option, _In
|
|||
conn_str += ";";
|
||||
}
|
||||
|
||||
void ce_ksp_provider_set_func::func( _In_ connection_option const* option, _In_ zval* value, _Inout_ sqlsrv_conn* conn, _Inout_ std::string& conn_str TSRMLS_DC )
|
||||
{
|
||||
SQLSRV_ASSERT( Z_TYPE_P( value ) == IS_STRING, "Wrong zval type for this keyword" )
|
||||
|
||||
size_t value_len = Z_STRLEN_P( value );
|
||||
|
||||
CHECK_CUSTOM_ERROR( value_len == 0, conn, SQLSRV_ERROR_KEYSTORE_INVALID_VALUE ) {
|
||||
throw core::CoreException();
|
||||
}
|
||||
|
||||
switch ( option->conn_option_key ) {
|
||||
case SQLSRV_CONN_OPTION_CEKEYSTORE_PROVIDER:
|
||||
conn->ce_option.ksp_path = value;
|
||||
conn->ce_option.ksp_required = true;
|
||||
break;
|
||||
case SQLSRV_CONN_OPTION_CEKEYSTORE_NAME:
|
||||
conn->ce_option.ksp_name = value;
|
||||
conn->ce_option.ksp_required = true;
|
||||
break;
|
||||
case SQLSRV_CONN_OPTION_CEKEYSTORE_ENCRYPT_KEY:
|
||||
conn->ce_option.ksp_encrypt_key = value;
|
||||
conn->ce_option.key_size = value_len;
|
||||
conn->ce_option.ksp_required = true;
|
||||
break;
|
||||
default:
|
||||
SQLSRV_ASSERT(false, "ce_ksp_provider_set_func: Invalid KSP option!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// helper function to evaluate whether a string value is true or false.
|
||||
// Values = ("true" or "1") are treated as true values. Everything else is treated as false.
|
||||
// Returns 1 for true and 0 for false.
|
||||
|
|
|
@ -1056,13 +1056,8 @@ struct stmt_option;
|
|||
// This holds the various details of column encryption.
|
||||
struct col_encryption_option {
|
||||
bool enabled; // column encryption enabled, false by default
|
||||
zval_auto_ptr ksp_name; // keystore provider name
|
||||
zval_auto_ptr ksp_path; // keystore provider path to the dynamically linked libary (either a *.dll or *.so)
|
||||
zval_auto_ptr ksp_encrypt_key; // the encryption key used to configure the keystore provider
|
||||
size_t key_size; // the length of ksp_encrypt_key without the NULL terminator
|
||||
bool ksp_required; // a keystore provider is required to enable column encryption, false by default
|
||||
|
||||
col_encryption_option() : enabled( false ), key_size ( 0 ), ksp_required( false )
|
||||
col_encryption_option() : enabled( false )
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -1109,14 +1104,11 @@ const char APP[] = "APP";
|
|||
const char ApplicationIntent[] = "ApplicationIntent";
|
||||
const char AttachDBFileName[] = "AttachDbFileName";
|
||||
const char Authentication[] = "Authentication";
|
||||
const char ColumnEncryption[] = "ColumnEncryption";
|
||||
const char Driver[] = "Driver";
|
||||
const char CEKeystoreProvider[] = "CEKeystoreProvider";
|
||||
const char CEKeystoreName[] = "CEKeystoreName";
|
||||
const char CEKeystoreEncryptKey[] = "CEKeystoreEncryptKey";
|
||||
const char CharacterSet[] = "CharacterSet";
|
||||
const char ConnectionPooling[] = "ConnectionPooling";
|
||||
#ifdef _WIN32
|
||||
const char ColumnEncryption[] = "ColumnEncryption";
|
||||
const char ConnectRetryCount[] = "ConnectRetryCount";
|
||||
const char ConnectRetryInterval[] = "ConnectRetryInterval";
|
||||
#endif // _WIN32
|
||||
|
@ -1709,10 +1701,6 @@ enum SQLSRV_ERROR_CODES {
|
|||
SQLSRV_ERROR_FIELD_INDEX_ERROR,
|
||||
SQLSRV_ERROR_BUFFER_LIMIT_EXCEEDED,
|
||||
SQLSRV_ERROR_INVALID_BUFFER_LIMIT,
|
||||
SQLSRV_ERROR_KEYSTORE_NAME_MISSING,
|
||||
SQLSRV_ERROR_KEYSTORE_PATH_MISSING,
|
||||
SQLSRV_ERROR_KEYSTORE_KEY_MISSING,
|
||||
SQLSRV_ERROR_KEYSTORE_INVALID_VALUE,
|
||||
SQLSRV_ERROR_OUTPUT_PARAM_TYPES_NOT_SUPPORTED,
|
||||
SQLSRV_ERROR_ENCRYPTED_STREAM_FETCH,
|
||||
|
||||
|
|
|
@ -712,9 +712,9 @@ void core_sqlsrv_bind_param( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT param_
|
|||
if ( stmt->conn->ce_option.enabled && sql_type == SQL_TYPE_TIMESTAMP )
|
||||
{
|
||||
if( decimal_digits == 3 )
|
||||
core::SQLSetDescField( stmt, param_num + 1, SQL_CA_SS_SERVER_TYPE, (SQLPOINTER)SQL_SS_TYPE_DATETIME, 0 );
|
||||
core::SQLSetDescField( stmt, param_num + 1, SQL_CA_SS_SERVER_TYPE, (SQLPOINTER)SQL_SS_TYPE_DATETIME, SQL_IS_INTEGER );
|
||||
else if (decimal_digits == 0)
|
||||
core::SQLSetDescField( stmt, param_num + 1, SQL_CA_SS_SERVER_TYPE, (SQLPOINTER)SQL_SS_TYPE_SMALLDATETIME, 0 );
|
||||
core::SQLSetDescField( stmt, param_num + 1, SQL_CA_SS_SERVER_TYPE, (SQLPOINTER)SQL_SS_TYPE_SMALLDATETIME, SQL_IS_INTEGER );
|
||||
}
|
||||
}
|
||||
catch( core::CoreException& e ){
|
||||
|
|
|
@ -187,13 +187,9 @@ const char AttachDBFileName[] = "AttachDbFileName";
|
|||
const char CharacterSet[] = "CharacterSet";
|
||||
const char Authentication[] = "Authentication";
|
||||
const char ConnectionPooling[] = "ConnectionPooling";
|
||||
const char ColumnEncryption[] = "ColumnEncryption";
|
||||
const char Driver[] = "Driver";
|
||||
const char CEKeystoreProvider[] = "CEKeystoreProvider";
|
||||
const char CEKeystoreName[] = "CEKeystoreName";
|
||||
const char CEKeystoreEncryptKey[] = "CEKeystoreEncryptKey";
|
||||
|
||||
#ifdef _WIN32
|
||||
const char ColumnEncryption[] = "ColumnEncryption";
|
||||
const char ConnectRetryCount[] = "ConnectRetryCount";
|
||||
const char ConnectRetryInterval[] = "ConnectRetryInterval";
|
||||
#endif // _WIN32
|
||||
|
@ -307,15 +303,6 @@ const connection_option SS_CONN_OPTS[] = {
|
|||
CONN_ATTR_BOOL,
|
||||
conn_null_func::func
|
||||
},
|
||||
{
|
||||
SSConnOptionNames::ColumnEncryption,
|
||||
sizeof(SSConnOptionNames::ColumnEncryption),
|
||||
SQLSRV_CONN_OPTION_COLUMNENCRYPTION,
|
||||
ODBCConnOptions::ColumnEncryption,
|
||||
sizeof(ODBCConnOptions::ColumnEncryption),
|
||||
CONN_ATTR_STRING,
|
||||
column_encryption_set_func::func
|
||||
},
|
||||
{
|
||||
SSConnOptionNames::Driver,
|
||||
sizeof(SSConnOptionNames::Driver),
|
||||
|
@ -325,34 +312,16 @@ const connection_option SS_CONN_OPTS[] = {
|
|||
CONN_ATTR_STRING,
|
||||
driver_set_func::func
|
||||
},
|
||||
{
|
||||
SSConnOptionNames::CEKeystoreProvider,
|
||||
sizeof(SSConnOptionNames::CEKeystoreProvider),
|
||||
SQLSRV_CONN_OPTION_CEKEYSTORE_PROVIDER,
|
||||
ODBCConnOptions::CEKeystoreProvider,
|
||||
sizeof(ODBCConnOptions::CEKeystoreProvider),
|
||||
CONN_ATTR_STRING,
|
||||
ce_ksp_provider_set_func::func
|
||||
},
|
||||
{
|
||||
SSConnOptionNames::CEKeystoreName,
|
||||
sizeof(SSConnOptionNames::CEKeystoreName),
|
||||
SQLSRV_CONN_OPTION_CEKEYSTORE_NAME,
|
||||
ODBCConnOptions::CEKeystoreName,
|
||||
sizeof(ODBCConnOptions::CEKeystoreName),
|
||||
CONN_ATTR_STRING,
|
||||
ce_ksp_provider_set_func::func
|
||||
},
|
||||
{
|
||||
SSConnOptionNames::CEKeystoreEncryptKey,
|
||||
sizeof(SSConnOptionNames::CEKeystoreEncryptKey),
|
||||
SQLSRV_CONN_OPTION_CEKEYSTORE_ENCRYPT_KEY,
|
||||
ODBCConnOptions::CEKeystoreEncryptKey,
|
||||
sizeof(ODBCConnOptions::CEKeystoreEncryptKey),
|
||||
CONN_ATTR_STRING,
|
||||
ce_ksp_provider_set_func::func
|
||||
},
|
||||
#ifdef _WIN32
|
||||
{
|
||||
SSConnOptionNames::ColumnEncryption,
|
||||
sizeof(SSConnOptionNames::ColumnEncryption),
|
||||
SQLSRV_CONN_OPTION_COLUMNENCRYPTION,
|
||||
ODBCConnOptions::ColumnEncryption,
|
||||
sizeof(ODBCConnOptions::ColumnEncryption),
|
||||
CONN_ATTR_STRING,
|
||||
column_encryption_set_func::func
|
||||
},
|
||||
{
|
||||
SSConnOptionNames::ConnectRetryCount,
|
||||
sizeof( SSConnOptionNames::ConnectRetryCount ),
|
||||
|
|
|
@ -379,22 +379,6 @@ ss_error SS_ERRORS[] = {
|
|||
{
|
||||
SS_SQLSRV_WARNING_FIELD_NAME_EMPTY,
|
||||
{ SSPWARN, (SQLCHAR*)"An empty field name was skipped by sqlsrv_fetch_object.", -100, false }
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_KEYSTORE_NAME_MISSING,
|
||||
{ IMSSP, (SQLCHAR*) "The name of the custom keystore provider is missing.", -101, false}
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_KEYSTORE_PATH_MISSING,
|
||||
{ IMSSP, (SQLCHAR*) "The path to the custom keystore provider is missing.", -102, false}
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_KEYSTORE_KEY_MISSING,
|
||||
{ IMSSP, (SQLCHAR*) "The encryption key for the custom keystore provider is missing.", -103, false}
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_KEYSTORE_INVALID_VALUE,
|
||||
{ IMSSP, (SQLCHAR*) "Invalid value for loading a custom keystore provider.", -104, false}
|
||||
},
|
||||
{
|
||||
SQLSRV_ERROR_CE_DRIVER_REQUIRED,
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
<?php
|
||||
|
||||
function getKSPpath()
|
||||
{
|
||||
$name = 'myKSP';
|
||||
|
||||
$dir_name = realpath(dirname(__FILE__));
|
||||
$ksp = $dir_name . DIRECTORY_SEPARATOR . $name;
|
||||
if ( strtoupper( substr( php_uname( 's' ), 0, 3 ) ) == 'WIN' ) {
|
||||
$arch = 'x64';
|
||||
if ( PHP_INT_SIZE == 4 ) // running 32 bit
|
||||
$arch = '';
|
||||
$ksp .= $arch . '.dll';
|
||||
}
|
||||
else
|
||||
$ksp .= '.so';
|
||||
|
||||
return $ksp;
|
||||
}
|
||||
|
||||
$ksp_name = 'MyCustomKSPName';
|
||||
$encrypt_key = 'LPKCWVD07N3RG98J0MBLG4H2';
|
||||
$ksp_test_table = 'CustomKSPTestTable';
|
||||
|
||||
?>
|
|
@ -16,10 +16,18 @@
|
|||
function IsAEQualified($conn)
|
||||
{
|
||||
$msodbcsql_ver = $conn->getAttribute(PDO::ATTR_CLIENT_VERSION)["DriverVer"];
|
||||
$server_ver = $conn->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
$msodbcsql_maj = explode(".", $msodbcsql_ver)[0];
|
||||
$msodbcsql_min = explode(".", $msodbcsql_ver)[1];
|
||||
if ($msodbcsql_maj < 17 || explode('.', $server_ver)[0] < 13)
|
||||
if ($msodbcsql_maj < 17) {
|
||||
return false;
|
||||
}
|
||||
require 'MsSetup.inc';
|
||||
if ($daasMode) {
|
||||
// running against Azure
|
||||
return true;
|
||||
}
|
||||
// if not Azure, check the server version
|
||||
$server_ver = $conn->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
if (explode('.', $server_ver)[0] < 13)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,11 +20,19 @@ const KSP_TEST_TABLE = 'CustomKSPTestTable';
|
|||
function isAEQualified($conn)
|
||||
{
|
||||
$msodbcsql_ver = $conn->getAttribute(PDO::ATTR_CLIENT_VERSION)["DriverVer"];
|
||||
$server_ver = $conn->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
$msodbcsql_maj = explode(".", $msodbcsql_ver)[0];
|
||||
if ($msodbcsql_maj < 17 || explode('.', $server_ver)[0] < 13) {
|
||||
if ($msodbcsql_maj < 17) {
|
||||
return false;
|
||||
}
|
||||
require 'MsSetup.inc';
|
||||
if ($daasMode) {
|
||||
// running against Azure
|
||||
return true;
|
||||
}
|
||||
// if not Azure, check the server version
|
||||
$server_ver = $conn->getAttribute(PDO::ATTR_SERVER_VERSION);
|
||||
if (explode('.', $server_ver)[0] < 13)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,134 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data from binary types columns using PDO::bindColumn
|
||||
--DESCRIPTION--
|
||||
Test conversion from binary types column to output of PDO::PARAM types
|
||||
With or without AE, conversion works if:
|
||||
1. From any binary type column to PDO::PARAM_STR
|
||||
2. From any binary type column to PDO::PARAM_LOB
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array("binary", "varbinary", "varbinary(max)");
|
||||
$lengths = array(1, 8, 64, 512, 4000);
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
$maxcol = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $m) {
|
||||
if ($maxcol !== false) {
|
||||
$typeFull = $dataType;
|
||||
} else {
|
||||
$typeFull = "$dataType($m)";
|
||||
}
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
//create and populate table containing binary(m) or varbinary(m) columns
|
||||
$tbname = "test_" . str_replace(array('(', ')'), '', $dataType) . $m;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c_det"), new ColumnMeta($typeFull, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$inputValues = array(str_repeat("d", $m), str_repeat("r", $m));
|
||||
insertRow($conn, $tbname, array("c_det" => new BindParamOp(1, $inputValues[0], "PDO::PARAM_LOB", 0, "PDO::SQLSRV_ENCODING_BINARY"),
|
||||
"c_rand" => new BindParamOp(2, $inputValues[1], "PDO::PARAM_LOB", 0, "PDO::SQLSRV_ENCODING_BINARY")), "prepareBindParam");
|
||||
|
||||
// fetch by specifying PDO::PARAM_ types with PDO::bindColumn
|
||||
$query = "SELECT c_det, c_rand FROM $tbname";
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($query);
|
||||
$stmt->execute();
|
||||
$stmt->bindColumn('c_det', $det, constant($pdoParamType));
|
||||
$stmt->bindColumn('c_rand', $rand, constant($pdoParamType));
|
||||
$row = $stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
// check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_NULL or PDO::PARAM_INT
|
||||
// with or without AE: should not work
|
||||
if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_NULL" || $pdoParamType == "PDO::PARAM_INT") {
|
||||
if (!is_null($det) || !is_null($rand)) {
|
||||
echo "Retrieving $typeFull data as $pdoParamType should not be supported\n";
|
||||
}
|
||||
// check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
if (trim($det) == $inputValues[0] && trim($rand) == $inputValues[1]) {
|
||||
echo "****Retrieving $typeFull data as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $typeFull data as $pdoParamType fails\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing binary(1):
|
||||
****Retrieving binary(1) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving binary(1) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing binary(8):
|
||||
****Retrieving binary(8) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving binary(8) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing binary(64):
|
||||
****Retrieving binary(64) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving binary(64) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing binary(512):
|
||||
****Retrieving binary(512) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving binary(512) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing binary(4000):
|
||||
****Retrieving binary(4000) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving binary(4000) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(1):
|
||||
****Retrieving varbinary(1) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(1) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(8):
|
||||
****Retrieving varbinary(8) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(8) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(64):
|
||||
****Retrieving varbinary(64) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(64) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(512):
|
||||
****Retrieving varbinary(512) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(512) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(4000):
|
||||
****Retrieving varbinary(4000) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(4000) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_STR is supported****
|
||||
****Retrieving varbinary(max) data as PDO::PARAM_LOB is supported****
|
|
@ -0,0 +1,144 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data from char types columns using PDO::bindColumn
|
||||
--DESCRIPTION--
|
||||
Test conversion from char types column to output of PDO::PARAM types
|
||||
With or without Always Encrypted, conversion works if:
|
||||
1. From any char type column to PDO::PARAM_STR
|
||||
2. From any char type column to PDO::PARAM_LOB
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array("char", "varchar", "varchar(max)");
|
||||
$lengths = array(1, 8, 64, 512, 4096, 8000);
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
$maxcol = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $m) {
|
||||
if ($maxcol !== false) {
|
||||
$typeFull = $dataType;
|
||||
} else {
|
||||
$typeFull = "$dataType($m)";
|
||||
}
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
//create and populate table containing char(m) or varchar(m) columns
|
||||
$tbname = "test_" . str_replace(array('(', ')'), '', $dataType) . $m;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c1", null, "ramdomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$inputValue = str_repeat("d", $m);
|
||||
insertRow($conn, $tbname, array("c1" => $inputValue));
|
||||
|
||||
// fetch by specifying PDO::PARAM_ types with PDO::bindColumn
|
||||
$query = "SELECT c1 FROM $tbname";
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($query);
|
||||
$stmt->execute();
|
||||
$stmt->bindColumn('c1', $c1, constant($pdoParamType));
|
||||
$row = $stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
// check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_NULL or PDO::PARAM_INT
|
||||
// with or without AE: should not work
|
||||
if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_NULL" || $pdoParamType == "PDO::PARAM_INT") {
|
||||
if (!empty($det) || !empty($rand)) {
|
||||
echo "Retrieving $typeFull data as $pdoParamType should not be supported\n";
|
||||
}
|
||||
// check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
if (strlen($c1) == $m) {
|
||||
echo "****Retrieving $typeFull as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $typeFull as $pdoParamType fails\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing char(1):
|
||||
****Retrieving char(1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving char(1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing char(8):
|
||||
****Retrieving char(8) as PDO::PARAM_STR is supported****
|
||||
****Retrieving char(8) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing char(64):
|
||||
****Retrieving char(64) as PDO::PARAM_STR is supported****
|
||||
****Retrieving char(64) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing char(512):
|
||||
****Retrieving char(512) as PDO::PARAM_STR is supported****
|
||||
****Retrieving char(512) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing char(4096):
|
||||
****Retrieving char(4096) as PDO::PARAM_STR is supported****
|
||||
****Retrieving char(4096) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing char(8000):
|
||||
****Retrieving char(8000) as PDO::PARAM_STR is supported****
|
||||
****Retrieving char(8000) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(1):
|
||||
****Retrieving varchar(1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(8):
|
||||
****Retrieving varchar(8) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(8) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(64):
|
||||
****Retrieving varchar(64) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(64) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(512):
|
||||
****Retrieving varchar(512) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(512) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(4096):
|
||||
****Retrieving varchar(4096) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(4096) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(8000):
|
||||
****Retrieving varchar(8000) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(8000) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Retrieving varchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(max) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Retrieving varchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(max) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Retrieving varchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(max) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Retrieving varchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(max) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Retrieving varchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(max) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Retrieving varchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving varchar(max) as PDO::PARAM_LOB is supported****
|
|
@ -0,0 +1,77 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data from datetime types columns using PDO::bindColumn
|
||||
--DESCRIPTION--
|
||||
Test conversion from datetime types column to output of PDO::PARAM types
|
||||
With or without Always Encrypted, conversion works if:
|
||||
1. From any datetime type column to PDO::PARAM_STR
|
||||
2. From any datetime type column to PDO::PARAM_LOB
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array("date", "datetime", "smalldatetime");
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
echo "\nTesting $dataType:\n";
|
||||
|
||||
// create and populate table containing date, datetime or smalldatetime columns
|
||||
$tbname = "test_" . $dataType;
|
||||
$colMetaArr = array(new ColumnMeta($dataType, "c_det"), new ColumnMeta($dataType, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$inputValues = array_slice(${explode("(", $dataType)[0] . "_params"}, 1, 2);
|
||||
insertRow($conn, $tbname, array("c_det" => $inputValues[0], "c_rand" => $inputValues[1]));
|
||||
|
||||
// fetch by specifying PDO::PARAM_ types with PDO::bindColumn
|
||||
$query = "SELECT c_det, c_rand FROM $tbname";
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($query);
|
||||
$stmt->execute();
|
||||
$stmt->bindColumn('c_det', $det, constant($pdoParamType));
|
||||
$stmt->bindColumn('c_rand', $rand, constant($pdoParamType));
|
||||
$row = $stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
// check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_NULL or PDO::PARAM_INT
|
||||
// with or without AE: should not work
|
||||
if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_NULL" || $pdoParamType == "PDO::PARAM_INT") {
|
||||
if (!is_null($det) || !is_null($rand)) {
|
||||
echo "Retrieving $dataType data as $pdoParamType should not be supported\n";
|
||||
}
|
||||
// check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// only check if input values are part of fetched values because some input values do not contain any deicmal places, the value retrieved however has 3 decimal places if the type is a datetime
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
if (strpos($det, $inputValues[0]) !== false && strpos($rand, $inputValues[1]) !== false) {
|
||||
echo "****Retrieving $dataType as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $dataType as $pdoParamType fails\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing date:
|
||||
****Retrieving date as PDO::PARAM_STR is supported****
|
||||
****Retrieving date as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing datetime:
|
||||
****Retrieving datetime as PDO::PARAM_STR is supported****
|
||||
****Retrieving datetime as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing smalldatetime:
|
||||
****Retrieving smalldatetime as PDO::PARAM_STR is supported****
|
||||
****Retrieving smalldatetime as PDO::PARAM_LOB is supported****
|
|
@ -0,0 +1,150 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data from datetime types columns with different precisions using PDO::bindColumn
|
||||
--DESCRIPTION--
|
||||
Test conversion from datetime types column to output of PDO::PARAM types
|
||||
With or without Always Encrypted, conversion works if:
|
||||
1. From any datetime type column to PDO::PARAM_STR
|
||||
2. From any datetime type column to PDO::PARAM_LOB
|
||||
TODO: cannot insert into a datetime2(0) using the PDO_SQLSRV driver
|
||||
returns operand type clash error between smalldatetime and datetime2(0)
|
||||
to see error, uncomment 0 from the $precision array
|
||||
documented in VSO 2693
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
function compareDate($dtout, $dtin, $dataType) {
|
||||
if ($dataType == "datetimeoffset") {
|
||||
$dtarr = explode(' ', $dtin);
|
||||
if (strpos($dtout, $dtarr[0]) !== false && strpos($dtout, $dtarr[1]) !== false && strpos($dtout, $dtarr[2]) !== false) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (strpos($dtout, $dtin) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$dataTypes = array("datetime2", "datetimeoffset", "time");
|
||||
$precisions = array(/*0,*/ 1, 2, 4, 7);
|
||||
$inputValuesInit = array("datetime2" => array("0001-01-01 00:00:00", "9999-12-31 23:59:59"),
|
||||
"datetimeoffset" => array("0001-01-01 00:00:00 -14:00", "9999-12-31 23:59:59 +14:00"),
|
||||
"time" => array("00:00:00", "23:59:59"));
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
foreach ($precisions as $m) {
|
||||
// add $m number of decimal digits to the some input values
|
||||
$inputValues[0] = $inputValuesInit[$dataType][0];
|
||||
$inputValues[1] = $inputValuesInit[$dataType][1];
|
||||
if ($m != 0) {
|
||||
if ($dataType == "datetime2") {
|
||||
$inputValues[1] .= "." . str_repeat("9", $m);
|
||||
} else if ($dataType == "datetimeoffset") {
|
||||
$dtoffsetPieces = explode(" ", $inputValues[1]);
|
||||
$inputValues[1] = $dtoffsetPieces[0] . " " . $dtoffsetPieces[1] . "." . str_repeat("9", $m) . " " . $dtoffsetPieces[2];
|
||||
} else if ($dataType == "time") {
|
||||
$inputValues[0] .= "." . str_repeat("0", $m);
|
||||
$inputValues[1] .= "." . str_repeat("9", $m);
|
||||
}
|
||||
}
|
||||
$typeFull = "$dataType($m)";
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
//create and populate table containing datetime2(m), datetimeoffset(m) or time(m) columns
|
||||
$tbname = "test_" . $dataType . $m;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c_det"), new ColumnMeta($typeFull, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
insertRow($conn, $tbname, array("c_det" => $inputValues[0], "c_rand" => $inputValues[1]));
|
||||
|
||||
// fetch by specifying PDO::PARAM_ types with PDO:bindColumn
|
||||
$query = "SELECT c_det, c_rand FROM $tbname";
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($query);
|
||||
$stmt->execute();
|
||||
$stmt->bindColumn('c_det', $det, constant($pdoParamType));
|
||||
$stmt->bindColumn('c_rand', $rand, constant($pdoParamType));
|
||||
$row = $stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
// check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_NULL or PDO::PARAM_INT
|
||||
// with or without AE: should not work
|
||||
if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_NULL" || $pdoParamType == "PDO::PARAM_INT") {
|
||||
if (!is_null($det) || !is_null($rand)) {
|
||||
echo "Retrieving $typeFull data as $pdoParamType should not be supported\n";
|
||||
}
|
||||
// check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
if (compareDate($det, $inputValues[0], $dataType) && compareDate($rand, $inputValues[1], $dataType)) {
|
||||
echo "****Retrieving $typeFull as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $typeFull as $pdoParamType fails\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing datetime2(1):
|
||||
****Retrieving datetime2(1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving datetime2(1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing datetime2(2):
|
||||
****Retrieving datetime2(2) as PDO::PARAM_STR is supported****
|
||||
****Retrieving datetime2(2) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing datetime2(4):
|
||||
****Retrieving datetime2(4) as PDO::PARAM_STR is supported****
|
||||
****Retrieving datetime2(4) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing datetime2(7):
|
||||
****Retrieving datetime2(7) as PDO::PARAM_STR is supported****
|
||||
****Retrieving datetime2(7) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing datetimeoffset(1):
|
||||
****Retrieving datetimeoffset(1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving datetimeoffset(1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing datetimeoffset(2):
|
||||
****Retrieving datetimeoffset(2) as PDO::PARAM_STR is supported****
|
||||
****Retrieving datetimeoffset(2) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing datetimeoffset(4):
|
||||
****Retrieving datetimeoffset(4) as PDO::PARAM_STR is supported****
|
||||
****Retrieving datetimeoffset(4) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing datetimeoffset(7):
|
||||
****Retrieving datetimeoffset(7) as PDO::PARAM_STR is supported****
|
||||
****Retrieving datetimeoffset(7) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing time(1):
|
||||
****Retrieving time(1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving time(1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing time(2):
|
||||
****Retrieving time(2) as PDO::PARAM_STR is supported****
|
||||
****Retrieving time(2) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing time(4):
|
||||
****Retrieving time(4) as PDO::PARAM_STR is supported****
|
||||
****Retrieving time(4) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing time(7):
|
||||
****Retrieving time(7) as PDO::PARAM_STR is supported****
|
||||
****Retrieving time(7) as PDO::PARAM_LOB is supported****
|
|
@ -0,0 +1,242 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data from decimal types columns using PDO::bindColumn
|
||||
--DESCRIPTION--
|
||||
Test conversion from decimal types column to output of PDO::PARAM types
|
||||
With or without ALways Encrypted, conversion works if:
|
||||
1. From any decimal type column to PDO::PARAM_STR
|
||||
2. From any decimal type column to PDO::PARAM_LOB
|
||||
TODO: behavior for teching decimals as PARAM_BOOL and PARAM_INT varies depending on the number being fetched
|
||||
1. if the number is less than 1, returns 0 (even though the number being fetched is 0.9)
|
||||
2. if the number is greater than 1 and the number of digits is less than 11, returns the correctly rounded integer (e.g., returns 922 when fetching 922.3)
|
||||
3. if the number is greater than 1 and the number of digits is greater than 11, returns NULL
|
||||
need to investigate which should be the correct behavior
|
||||
for this test, assume to correct behavior is to return NULL
|
||||
documented in VSO 2730
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array("decimal", "numeric");
|
||||
$precisions = array(1 => array(0, 1),
|
||||
4 => array(0, 1, 4),
|
||||
16 => array(0, 1, 4, 16),
|
||||
38 => array(0, 1, 4, 16, 38));
|
||||
$inputValuesInit = array(92233720368547758089223372036854775808, -92233720368547758089223372036854775808);
|
||||
$inputPrecision = 38;
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
foreach ($precisions as $m1 => $scales) {
|
||||
foreach ($scales as $m2) {
|
||||
// change the number of integers in the input values to be $m1 - $m2
|
||||
$precDiff = $inputPrecision - ($m1 - $m2);
|
||||
$inputValues = $inputValuesInit;
|
||||
foreach ($inputValues as &$inputValue) {
|
||||
$inputValue = $inputValue / pow(10, $precDiff);
|
||||
}
|
||||
|
||||
// compute the epsilon for comparing doubles
|
||||
// float in PHP only has a precision of roughtly 14 digits: http://php.net/manual/en/language.types.float.php
|
||||
$epsilon;
|
||||
if ($m1 < 14) {
|
||||
$epsilon = pow(10, $m2 * -1);
|
||||
} else {
|
||||
$numint = $m1 - $m2;
|
||||
if ($numint < 14) {
|
||||
$epsilon = pow(10, (14 - $numint) * -1);
|
||||
} else {
|
||||
$epsilon = pow(10, $numint - 14);
|
||||
}
|
||||
}
|
||||
|
||||
$typeFull = "$dataType($m1, $m2)";
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create and populate table containing decimal(m1, m2) or numeric(m1, m2) columns
|
||||
$tbname = "test_" . $dataType . $m1 . $m2;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c_det"), new ColumnMeta($typeFull, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
insertRow($conn, $tbname, array("c_det" => $inputValues[0], "c_rand" => $inputValues[1]));
|
||||
|
||||
// fetch by specifying PDO::PARAM_ types with PDO::bindColumn
|
||||
$query = "SELECT c_det, c_rand FROM $tbname";
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($query);
|
||||
$stmt->execute();
|
||||
$stmt->bindColumn('c_det', $det, constant($pdoParamType));
|
||||
$stmt->bindColumn('c_rand', $rand, constant($pdoParamType));
|
||||
$row = $stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
// check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_NULL or PDO::PARAM_INT
|
||||
// with or without AE: should not work
|
||||
// assume to correct behavior is to return NULL, see description
|
||||
if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_NULL" || $pdoParamType == "PDO::PARAM_INT") {
|
||||
if (!is_null($det) || !is_null($rand)) {
|
||||
echo "Retrieving $typeFull data as $pdoParamType should return NULL\n";
|
||||
}
|
||||
} else {
|
||||
if (abs($det - $inputValues[0]) < $epsilon &&
|
||||
abs($rand - $inputValues[1]) < $epsilon) {
|
||||
echo "****Retrieving $typeFull as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $typeFull as $pdoParamType fails\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing decimal(1, 0):
|
||||
Retrieving decimal(1, 0) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving decimal(1, 0) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving decimal(1, 0) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(1, 0) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(1, 1):
|
||||
Retrieving decimal(1, 1) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving decimal(1, 1) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving decimal(1, 1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(1, 1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(4, 0):
|
||||
Retrieving decimal(4, 0) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving decimal(4, 0) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving decimal(4, 0) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(4, 0) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(4, 1):
|
||||
Retrieving decimal(4, 1) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving decimal(4, 1) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving decimal(4, 1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(4, 1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(4, 4):
|
||||
Retrieving decimal(4, 4) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving decimal(4, 4) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving decimal(4, 4) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(4, 4) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(16, 0):
|
||||
****Retrieving decimal(16, 0) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(16, 0) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(16, 1):
|
||||
****Retrieving decimal(16, 1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(16, 1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(16, 4):
|
||||
****Retrieving decimal(16, 4) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(16, 4) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(16, 16):
|
||||
Retrieving decimal(16, 16) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving decimal(16, 16) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving decimal(16, 16) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(16, 16) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(38, 0):
|
||||
****Retrieving decimal(38, 0) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(38, 0) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(38, 1):
|
||||
****Retrieving decimal(38, 1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(38, 1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(38, 4):
|
||||
****Retrieving decimal(38, 4) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(38, 4) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(38, 16):
|
||||
****Retrieving decimal(38, 16) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(38, 16) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing decimal(38, 38):
|
||||
Retrieving decimal(38, 38) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving decimal(38, 38) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving decimal(38, 38) as PDO::PARAM_STR is supported****
|
||||
****Retrieving decimal(38, 38) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(1, 0):
|
||||
Retrieving numeric(1, 0) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving numeric(1, 0) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving numeric(1, 0) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(1, 0) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(1, 1):
|
||||
Retrieving numeric(1, 1) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving numeric(1, 1) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving numeric(1, 1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(1, 1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(4, 0):
|
||||
Retrieving numeric(4, 0) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving numeric(4, 0) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving numeric(4, 0) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(4, 0) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(4, 1):
|
||||
Retrieving numeric(4, 1) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving numeric(4, 1) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving numeric(4, 1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(4, 1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(4, 4):
|
||||
Retrieving numeric(4, 4) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving numeric(4, 4) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving numeric(4, 4) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(4, 4) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(16, 0):
|
||||
****Retrieving numeric(16, 0) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(16, 0) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(16, 1):
|
||||
****Retrieving numeric(16, 1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(16, 1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(16, 4):
|
||||
****Retrieving numeric(16, 4) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(16, 4) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(16, 16):
|
||||
Retrieving numeric(16, 16) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving numeric(16, 16) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving numeric(16, 16) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(16, 16) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(38, 0):
|
||||
****Retrieving numeric(38, 0) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(38, 0) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(38, 1):
|
||||
****Retrieving numeric(38, 1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(38, 1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(38, 4):
|
||||
****Retrieving numeric(38, 4) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(38, 4) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(38, 16):
|
||||
****Retrieving numeric(38, 16) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(38, 16) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing numeric(38, 38):
|
||||
Retrieving numeric(38, 38) data as PDO::PARAM_BOOL should return NULL
|
||||
Retrieving numeric(38, 38) data as PDO::PARAM_INT should return NULL
|
||||
****Retrieving numeric(38, 38) as PDO::PARAM_STR is supported****
|
||||
****Retrieving numeric(38, 38) as PDO::PARAM_LOB is supported****
|
|
@ -0,0 +1,94 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data from float types columns using PDO::bindColumn
|
||||
--DESCRIPTION--
|
||||
Test conversion from float types column to output of PDO::PARAM types
|
||||
With or without Always Encrypted, conversion works if:
|
||||
1. From any float type column to PDO::PARAM_STR
|
||||
2. From any float type column to PDO::PARAM_LOB
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataType = "float";
|
||||
$bits = array(1, 12, 24, 36, 53);
|
||||
$inputValues = array(9223372036854775808.9223372036854775808, -9223372036854775808.9223372036854775808);
|
||||
$numint = 19;
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($bits as $m) {
|
||||
// compute the epsilon for comparing doubles
|
||||
// when $m <= 24, the precision is 7 digits
|
||||
// when $m > 24, the precision is 15 digits, but PHP float only supports up to 14 digits
|
||||
$epsilon;
|
||||
if ($m <= 24) {
|
||||
$epsilon = pow(10, $numint - 7);
|
||||
} else {
|
||||
$epsilon = pow(10, $numint - 14);
|
||||
}
|
||||
|
||||
$typeFull = "$dataType($m)";
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
//create and populate table containing float(m) columns
|
||||
$tbname = "test_" . $dataType . $m;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c_det"), new ColumnMeta($typeFull, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
insertRow($conn, $tbname, array("c_det" => $inputValues[0], "c_rand" => $inputValues[1]));
|
||||
|
||||
// fetchby specifying PDO::PARAM_ types with PDO::bindColumn
|
||||
$query = "SELECT c_det, c_rand FROM $tbname";
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($query);
|
||||
$stmt->execute();
|
||||
$stmt->bindColumn('c_det', $det, constant($pdoParamType));
|
||||
$stmt->bindColumn('c_rand', $rand, constant($pdoParamType));
|
||||
$row = $stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
// check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_NULL or PDO::PARAM_INT
|
||||
// with or without AE: should not work
|
||||
if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_NULL" || $pdoParamType == "PDO::PARAM_INT") {
|
||||
if (!is_null($det) || !is_null($rand)) {
|
||||
echo "Retriving $typeFull data as $pdoParamType should return NULL\n";
|
||||
}
|
||||
} else {
|
||||
if (abs($det - $inputValues[0]) < $epsilon && abs($rand - $inputValues[1]) < $epsilon) {
|
||||
echo "****Retrieving $typeFull as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $typeFull as $pdoParamType fails\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing float(1):
|
||||
****Retrieving float(1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving float(1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing float(12):
|
||||
****Retrieving float(12) as PDO::PARAM_STR is supported****
|
||||
****Retrieving float(12) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing float(24):
|
||||
****Retrieving float(24) as PDO::PARAM_STR is supported****
|
||||
****Retrieving float(24) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing float(36):
|
||||
****Retrieving float(36) as PDO::PARAM_STR is supported****
|
||||
****Retrieving float(36) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing float(53):
|
||||
****Retrieving float(53) as PDO::PARAM_STR is supported****
|
||||
****Retrieving float(53) as PDO::PARAM_LOB is supported****
|
|
@ -0,0 +1,132 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data from nchar types columns using PDO::bindColumn
|
||||
--DESCRIPTION--
|
||||
Test conversion from nchar types column to output of PDO::PARAM types
|
||||
With or without Always Encrypted, conversion works if:
|
||||
1. From any nchar type column to PDO::PARAM_STR
|
||||
2. From any nchar type column to PDO::PARAM_LOB
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array("nchar", "nvarchar", "nvarchar(max)");
|
||||
$lengths = array(1, 8, 64, 512, 4000);
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
$maxcol = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $m) {
|
||||
if ($maxcol !== false) {
|
||||
$typeFull = $dataType;
|
||||
} else {
|
||||
$typeFull = "$dataType($m)";
|
||||
}
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
//create and populate table containing nchar(m) or nvarchar(m) columns
|
||||
$tbname = "test_" . str_replace(array('(', ')'), '', $dataType) . $m;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c1"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$inputValue = str_repeat("d", $m);
|
||||
insertRow($conn, $tbname, array("c1" => $inputValue));
|
||||
|
||||
// fetch by specifying PDO::PARAM_ types with PDO::bindColumn
|
||||
$query = "SELECT c1 FROM $tbname";
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($query);
|
||||
$stmt->execute();
|
||||
$stmt->bindColumn('c1', $c1, constant($pdoParamType));
|
||||
$row = $stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
// check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_NULL or PDO::PARAM_INT
|
||||
// with or without AE: should not work
|
||||
if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_NULL" || $pdoParamType == "PDO::PARAM_INT") {
|
||||
if (!empty($det) || !empty($rand)) {
|
||||
echo "Retrieving $typeFull data as $pdoParamType should not be supported\n";
|
||||
}
|
||||
// check the case when fetching as PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
if (strlen($c1) == $m) {
|
||||
echo "****Retrieving $typeFull as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $typeFull as $pdoParamType fails\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing nchar(1):
|
||||
****Retrieving nchar(1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nchar(1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nchar(8):
|
||||
****Retrieving nchar(8) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nchar(8) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nchar(64):
|
||||
****Retrieving nchar(64) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nchar(64) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nchar(512):
|
||||
****Retrieving nchar(512) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nchar(512) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nchar(4000):
|
||||
****Retrieving nchar(4000) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nchar(4000) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(1):
|
||||
****Retrieving nvarchar(1) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(1) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(8):
|
||||
****Retrieving nvarchar(8) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(8) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(64):
|
||||
****Retrieving nvarchar(64) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(64) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(512):
|
||||
****Retrieving nvarchar(512) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(512) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(4000):
|
||||
****Retrieving nvarchar(4000) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(4000) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_STR is supported****
|
||||
****Retrieving nvarchar(max) as PDO::PARAM_LOB is supported****
|
|
@ -0,0 +1,128 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data from numeric types columns using PDO::bindColumn
|
||||
--DESCRIPTION--
|
||||
Test conversion from numeric types column to output of PDO::PARAM types
|
||||
With or without Always Encrypted, conversion works if:
|
||||
1. From any numeric type except for bigint column to PDO::PARAM_BOOL
|
||||
2. From any numeric type except for bigint column to PDO::PARAM_INT
|
||||
3. From any numeric type column to PDO::PARAM_STR
|
||||
4. From any numeric type column to PDO::PARAM_LOB
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array( "bit", "tinyint", "smallint", "int", "bigint", "real");
|
||||
$epsilon = 1;
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
echo "\nTesting $dataType:\n";
|
||||
|
||||
// create and populate table containing bit, tinyint, smallint, int, bigint, or real columns
|
||||
$tbname = "test_" . $dataType;
|
||||
$colMetaArr = array(new ColumnMeta($dataType, "c_det"), new ColumnMeta($dataType, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$inputValues = array_slice(${explode("(", $dataType)[0] . "_params"}, 1, 2);
|
||||
insertRow($conn, $tbname, array("c_det" => $inputValues[0], "c_rand" => $inputValues[1]));
|
||||
|
||||
// fetch by specifying PDO::PARAM_ types with PDO::bindColumn
|
||||
$query = "SELECT c_det, c_rand FROM $tbname";
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($query);
|
||||
$stmt->execute();
|
||||
$stmt->bindColumn('c_det', $det, constant($pdoParamType));
|
||||
$stmt->bindColumn('c_rand', $rand, constant($pdoParamType));
|
||||
$row = $stmt->fetch(PDO::FETCH_BOUND);
|
||||
|
||||
// check the case when fetching as PDO::PARAM_NULL
|
||||
// with or without AE: should not work
|
||||
if ($pdoParamType == "PDO::PARAM_NULL") {
|
||||
if (!is_null($det) || !is_null($rand)) {
|
||||
echo "Retrieving $dataType data as $pdoParamType should not be supported\n";
|
||||
}
|
||||
// check the case when fetching as PDO::PARAM_BOOL or PDO::PARAM_INT
|
||||
// with or without AE: should only not work with bigint
|
||||
} else if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_INT") {
|
||||
if ($dataType == "bigint") {
|
||||
if (!is_null($det) || !is_null($rand)) {
|
||||
echo "Retrieving $dataType data as $pdoParamType should not be supported\n";
|
||||
}
|
||||
} else if ($dataType == "real") {
|
||||
if (abs($det - $inputValues[0]) < $epsilon && abs($rand - $inputValues[1]) < $epsilon) {
|
||||
echo "****Retrieving $dataType as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $dataType as $pdoParamType fails\n";
|
||||
}
|
||||
} else {
|
||||
if ($det == $inputValues[0] && $rand == $inputValues[1]) {
|
||||
echo "****Retrieving $dataType as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $dataType as $pdoParamType fails\n";
|
||||
}
|
||||
}
|
||||
// check the case when fetching as PDO::PARAM_BOOL, PDO::PARAM_INT, PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
if ($dataType == "real") {
|
||||
if (abs($det - $inputValues[0]) < $epsilon && abs($rand - $inputValues[1]) < $epsilon) {
|
||||
echo "****Retrieving $dataType as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $dataType as $pdoParamType fails\n";
|
||||
}
|
||||
} else {
|
||||
if ($det == $inputValues[0] && $rand == $inputValues[1]) {
|
||||
echo "****Retrieving $dataType as $pdoParamType is supported****\n";
|
||||
} else {
|
||||
echo "Retrieving $dataType as $pdoParamType fails\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing bit:
|
||||
****Retrieving bit as PDO::PARAM_BOOL is supported****
|
||||
****Retrieving bit as PDO::PARAM_INT is supported****
|
||||
****Retrieving bit as PDO::PARAM_STR is supported****
|
||||
****Retrieving bit as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing tinyint:
|
||||
****Retrieving tinyint as PDO::PARAM_BOOL is supported****
|
||||
****Retrieving tinyint as PDO::PARAM_INT is supported****
|
||||
****Retrieving tinyint as PDO::PARAM_STR is supported****
|
||||
****Retrieving tinyint as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing smallint:
|
||||
****Retrieving smallint as PDO::PARAM_BOOL is supported****
|
||||
****Retrieving smallint as PDO::PARAM_INT is supported****
|
||||
****Retrieving smallint as PDO::PARAM_STR is supported****
|
||||
****Retrieving smallint as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing int:
|
||||
****Retrieving int as PDO::PARAM_BOOL is supported****
|
||||
****Retrieving int as PDO::PARAM_INT is supported****
|
||||
****Retrieving int as PDO::PARAM_STR is supported****
|
||||
****Retrieving int as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing bigint:
|
||||
****Retrieving bigint as PDO::PARAM_STR is supported****
|
||||
****Retrieving bigint as PDO::PARAM_LOB is supported****
|
||||
|
||||
Testing real:
|
||||
****Retrieving real as PDO::PARAM_BOOL is supported****
|
||||
****Retrieving real as PDO::PARAM_INT is supported****
|
||||
****Retrieving real as PDO::PARAM_STR is supported****
|
||||
****Retrieving real as PDO::PARAM_LOB is supported****
|
|
@ -0,0 +1,159 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data into binary types columns with different sizes
|
||||
--DESCRIPTION--
|
||||
Test conversions between different binary types of different sizes
|
||||
With or without Always Encrypted, implicit conversion works if:
|
||||
1. From input of PDO::PARAM_STR to a any binary column
|
||||
2. From input of PDO::PARAM_LOB to a any binary column
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array("binary", "varbinary", "varbinary(max)");
|
||||
$lengths = array(2, 8, 64, 512, 4000);
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
$maxcol = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $m) {
|
||||
if ($maxcol !== false) {
|
||||
$typeFull = $dataType;
|
||||
} else {
|
||||
$typeFull = "$dataType($m)";
|
||||
}
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing binary(m) or varbinary(m) columns
|
||||
$tbname = "test_" . str_replace(array('(', ')'), '', $dataType) . $m;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c_det"), new ColumnMeta($typeFull, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$inputValues = array(str_repeat("d", $m), str_repeat("r", $m));
|
||||
|
||||
// insert by specifying PDO::PARAM_ types
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$r;
|
||||
if ($pdoParamType == 'PDO::PARAM_STR' || $pdoParamType == 'PDO::PARAM_LOB') {
|
||||
$stmt = insertRow($conn, $tbname, array("c_det" => new BindParamOp(1, $inputValues[0], $pdoParamType, 0, "PDO::SQLSRV_ENCODING_BINARY"),
|
||||
"c_rand" => new BindParamOp(2, $inputValues[1], $pdoParamType, 0, "PDO::SQLSRV_ENCODING_BINARY")), "prepareBindParam", $r);
|
||||
} else {
|
||||
$stmt = insertRow($conn, $tbname, array("c_det" => new BindParamOp(1, $inputValues[0], $pdoParamType), "c_rand" => new BindParamOp(2, $inputValues[1], $pdoParamType)), "prepareBindParam", $r);
|
||||
}
|
||||
|
||||
// check the case when inserting as PDO::PARAM_BOOL or PDO::PARAM_INT
|
||||
// with or without AE: should not work
|
||||
if ($pdoParamType == "PDO::PARAM_BOOL" || $pdoParamType == "PDO::PARAM_INT") {
|
||||
if ($r !== false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should not be supported\n";
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_NULL
|
||||
// with AE: NULL is inserted
|
||||
// without AE: insertion fails
|
||||
} elseif ($pdoParamType == "PDO::PARAM_NULL") {
|
||||
if (isAEConnected()) {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!is_null($row['c_det']) && !is_null($row['c_rand'])) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should insert NULL\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($r !== false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should not be supported\n";
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (trim($row['c_det']) == $inputValues[0] && trim($row['c_rand']) == $inputValues[1]) {
|
||||
echo "****Conversion from $pdoParamType to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
$conn->query("TRUNCATE TABLE $tbname");
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing binary(2):
|
||||
****Conversion from PDO::PARAM_STR to binary(2) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to binary(2) is supported****
|
||||
|
||||
Testing binary(8):
|
||||
****Conversion from PDO::PARAM_STR to binary(8) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to binary(8) is supported****
|
||||
|
||||
Testing binary(64):
|
||||
****Conversion from PDO::PARAM_STR to binary(64) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to binary(64) is supported****
|
||||
|
||||
Testing binary(512):
|
||||
****Conversion from PDO::PARAM_STR to binary(512) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to binary(512) is supported****
|
||||
|
||||
Testing binary(4000):
|
||||
****Conversion from PDO::PARAM_STR to binary(4000) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to binary(4000) is supported****
|
||||
|
||||
Testing varbinary(2):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(2) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(2) is supported****
|
||||
|
||||
Testing varbinary(8):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(8) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(8) is supported****
|
||||
|
||||
Testing varbinary(64):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(64) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(64) is supported****
|
||||
|
||||
Testing varbinary(512):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(512) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(512) is supported****
|
||||
|
||||
Testing varbinary(4000):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(4000) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(4000) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(max) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(max) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(max) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(max) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from PDO::PARAM_STR to varbinary(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varbinary(max) is supported****
|
190
test/functional/pdo_sqlsrv/pdo_ae_insert_pdoparam_char_size.phpt
Normal file
190
test/functional/pdo_sqlsrv/pdo_ae_insert_pdoparam_char_size.phpt
Normal file
|
@ -0,0 +1,190 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data into char types columns with different sizes
|
||||
--DESCRIPTION--
|
||||
Test conversions between different char types of different sizes
|
||||
With or without Always Encrypted, implicit conversion works if:
|
||||
1. From input of PDO::PARAM_BOOL to any char column
|
||||
2. From input of PDO::PARAM_INT to any char column
|
||||
3. From input of PDO::PARAM_STR to any char column
|
||||
4. From input of PDO::PARAM_LOB to any char column
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array("char", "varchar", "varchar(max)");
|
||||
$lengths = array(1, 8, 64, 512, 4096, 8000);
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
foreach ($dataTypes as $dataType) {
|
||||
$maxcol = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $m) {
|
||||
if ($maxcol !== false) {
|
||||
$typeFull = $dataType;
|
||||
} else {
|
||||
$typeFull = "$dataType($m)";
|
||||
}
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing a char(m) or varchar(m) column
|
||||
// only one column is created because a row has a limitation of 8060 bytes
|
||||
// for lengths 4096 and 8000, cannot create 2 columns as it will exceed the maximum row sizes
|
||||
// for AE, only testing randomized here, deterministic is tested in the nchar test
|
||||
$tbname = getTableName("test_" . str_replace(array('(', ')'), '', $dataType) . $m);
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c1", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$input = str_repeat("d", $m);
|
||||
|
||||
// insert by specifying PDO::PARAM_ types
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$r;
|
||||
$stmt = insertRow($conn, $tbname, array( "c1" => new BindParamOp(1, $input, $pdoParamType)), "prepareBindParam", $r);
|
||||
|
||||
// check the case when inserting as PDO::PARAM_NULL
|
||||
// with or without AE: NULL is inserted
|
||||
if ($pdoParamType == "PDO::PARAM_NULL") {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c1 FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!is_null($row['c1'])) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should insert NULL\n";
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_BOOL, PDO::PARAM_INT, PDO::PARAM_STR or PDO{{PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
$sql = "SELECT c1 FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (strlen($row['c1']) == $m) {
|
||||
echo "****Conversion from $pdoParamType to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
$conn->query("TRUNCATE TABLE $tbname");
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing char(1):
|
||||
****Conversion from PDO::PARAM_BOOL to char(1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to char(1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to char(1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to char(1) is supported****
|
||||
|
||||
Testing char(8):
|
||||
****Conversion from PDO::PARAM_BOOL to char(8) is supported****
|
||||
****Conversion from PDO::PARAM_INT to char(8) is supported****
|
||||
****Conversion from PDO::PARAM_STR to char(8) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to char(8) is supported****
|
||||
|
||||
Testing char(64):
|
||||
****Conversion from PDO::PARAM_BOOL to char(64) is supported****
|
||||
****Conversion from PDO::PARAM_INT to char(64) is supported****
|
||||
****Conversion from PDO::PARAM_STR to char(64) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to char(64) is supported****
|
||||
|
||||
Testing char(512):
|
||||
****Conversion from PDO::PARAM_BOOL to char(512) is supported****
|
||||
****Conversion from PDO::PARAM_INT to char(512) is supported****
|
||||
****Conversion from PDO::PARAM_STR to char(512) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to char(512) is supported****
|
||||
|
||||
Testing char(4096):
|
||||
****Conversion from PDO::PARAM_BOOL to char(4096) is supported****
|
||||
****Conversion from PDO::PARAM_INT to char(4096) is supported****
|
||||
****Conversion from PDO::PARAM_STR to char(4096) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to char(4096) is supported****
|
||||
|
||||
Testing char(8000):
|
||||
****Conversion from PDO::PARAM_BOOL to char(8000) is supported****
|
||||
****Conversion from PDO::PARAM_INT to char(8000) is supported****
|
||||
****Conversion from PDO::PARAM_STR to char(8000) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to char(8000) is supported****
|
||||
|
||||
Testing varchar(1):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(1) is supported****
|
||||
|
||||
Testing varchar(8):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(8) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(8) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(8) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(8) is supported****
|
||||
|
||||
Testing varchar(64):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(64) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(64) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(64) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(64) is supported****
|
||||
|
||||
Testing varchar(512):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(512) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(512) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(512) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(512) is supported****
|
||||
|
||||
Testing varchar(4096):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(4096) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(4096) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(4096) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(4096) is supported****
|
||||
|
||||
Testing varchar(8000):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(8000) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(8000) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(8000) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(8000) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to varchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to varchar(max) is supported****
|
|
@ -1,7 +1,12 @@
|
|||
--TEST--
|
||||
Test for inserting and retrieving encrypted data of datetime types
|
||||
Test for inserting encrypted data into datetime types columns
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
Test conversions between different datetime types
|
||||
With or without Always Encrypted, implicit conversion works if:
|
||||
1. From input of PDO::PARAM_BOOL to a any datetime column
|
||||
2. From input of PDO::PARAM_INT to a any datetime column
|
||||
3. From input of PDO::PARAM_STR to a any datetime column
|
||||
4. From input of PDO::PARAM_LOB to a any datetime column
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
|
@ -9,28 +14,48 @@ Use PDOstatement::bindParam with all PDO::PARAM_ types
|
|||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array( "date", "datetime", "datetime2", "smalldatetime", "time", "datetimeoffset" );
|
||||
$dataTypes = array( "date", "datetime", "smalldatetime");
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
foreach ($dataTypes as $dataType) {
|
||||
echo "\nTesting $dataType:\n";
|
||||
|
||||
// create table
|
||||
$tbname = getTableName();
|
||||
// create table containing date, datetime or smalldatetime columns
|
||||
$tbname = "test_" . $dataType;
|
||||
$colMetaArr = array( new ColumnMeta($dataType, "c_det"), new ColumnMeta($dataType, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// prepare statement for inserting into table
|
||||
// insert by specifying PDO::PARAM_ types
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
// insert a row
|
||||
$inputValues = array_slice(${explode("(", $dataType)[0] . "_params"}, 1, 2);
|
||||
$r;
|
||||
$stmt = insertRow($conn, $tbname, array( "c_det" => new BindParamOp(1, $inputValues[0], $pdoParamType), "c_rand" => new BindParamOp(2, $inputValues[1], $pdoParamType)), "prepareBindParam", $r);
|
||||
if ($r === false) {
|
||||
isIncompatibleTypesError($stmt, $dataType, $pdoParamType);
|
||||
|
||||
// check the case when inserting as PDO::PARAM_NULL
|
||||
// with or without AE: NULL is inserted
|
||||
if ($pdoParamType == "PDO::PARAM_NULL") {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $dataType should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!is_null($row['c_det']) || !is_null($row['c_rand'])) {
|
||||
echo "Conversion from $pdoParamType to $dataType should insert NULL\n";
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_BOOL, PDO::PARAM_INT, PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
echo "****PDO param type $pdoParamType is compatible with encrypted $dataType****\n";
|
||||
fetchAll($conn, $tbname);
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (strpos($row['c_det'], $inputValues[0]) !== false && strpos($row['c_rand'], $inputValues[1]) !== false) {
|
||||
echo "****Conversion from $pdoParamType to $dataType is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $dataType causes data corruption\n";
|
||||
}
|
||||
}
|
||||
$conn->query("TRUNCATE TABLE $tbname");
|
||||
}
|
||||
|
@ -43,105 +68,20 @@ try {
|
|||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
|
||||
Testing date:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted date****
|
||||
c_det: 0001-01-01
|
||||
c_rand: 9999-12-31
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted date****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted date****
|
||||
c_det: 0001-01-01
|
||||
c_rand: 9999-12-31
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted date****
|
||||
c_det: 0001-01-01
|
||||
c_rand: 9999-12-31
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted date****
|
||||
c_det: 0001-01-01
|
||||
c_rand: 9999-12-31
|
||||
****Conversion from PDO::PARAM_BOOL to date is supported****
|
||||
****Conversion from PDO::PARAM_INT to date is supported****
|
||||
****Conversion from PDO::PARAM_STR to date is supported****
|
||||
****Conversion from PDO::PARAM_LOB to date is supported****
|
||||
|
||||
Testing datetime:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted datetime****
|
||||
c_det: 1753-01-01 00:00:00.000
|
||||
c_rand: 9999-12-31 23:59:59.997
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted datetime****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted datetime****
|
||||
c_det: 1753-01-01 00:00:00.000
|
||||
c_rand: 9999-12-31 23:59:59.997
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted datetime****
|
||||
c_det: 1753-01-01 00:00:00.000
|
||||
c_rand: 9999-12-31 23:59:59.997
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted datetime****
|
||||
c_det: 1753-01-01 00:00:00.000
|
||||
c_rand: 9999-12-31 23:59:59.997
|
||||
|
||||
Testing datetime2:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted datetime2****
|
||||
c_det: 0001-01-01 00:00:00.0000000
|
||||
c_rand: 9999-12-31 23:59:59.9999999
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted datetime2****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted datetime2****
|
||||
c_det: 0001-01-01 00:00:00.0000000
|
||||
c_rand: 9999-12-31 23:59:59.9999999
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted datetime2****
|
||||
c_det: 0001-01-01 00:00:00.0000000
|
||||
c_rand: 9999-12-31 23:59:59.9999999
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted datetime2****
|
||||
c_det: 0001-01-01 00:00:00.0000000
|
||||
c_rand: 9999-12-31 23:59:59.9999999
|
||||
****Conversion from PDO::PARAM_BOOL to datetime is supported****
|
||||
****Conversion from PDO::PARAM_INT to datetime is supported****
|
||||
****Conversion from PDO::PARAM_STR to datetime is supported****
|
||||
****Conversion from PDO::PARAM_LOB to datetime is supported****
|
||||
|
||||
Testing smalldatetime:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted smalldatetime****
|
||||
c_det: 1900-01-01 00:00:00
|
||||
c_rand: 2079-06-05 23:59:00
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted smalldatetime****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted smalldatetime****
|
||||
c_det: 1900-01-01 00:00:00
|
||||
c_rand: 2079-06-05 23:59:00
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted smalldatetime****
|
||||
c_det: 1900-01-01 00:00:00
|
||||
c_rand: 2079-06-05 23:59:00
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted smalldatetime****
|
||||
c_det: 1900-01-01 00:00:00
|
||||
c_rand: 2079-06-05 23:59:00
|
||||
|
||||
Testing time:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted time****
|
||||
c_det: 00:00:00.0000000
|
||||
c_rand: 23:59:59.9999999
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted time****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted time****
|
||||
c_det: 00:00:00.0000000
|
||||
c_rand: 23:59:59.9999999
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted time****
|
||||
c_det: 00:00:00.0000000
|
||||
c_rand: 23:59:59.9999999
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted time****
|
||||
c_det: 00:00:00.0000000
|
||||
c_rand: 23:59:59.9999999
|
||||
|
||||
Testing datetimeoffset:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted datetimeoffset****
|
||||
c_det: 0001-01-01 00:00:00.0000000 -14:00
|
||||
c_rand: 9999-12-31 23:59:59.9999999 +14:00
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted datetimeoffset****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted datetimeoffset****
|
||||
c_det: 0001-01-01 00:00:00.0000000 -14:00
|
||||
c_rand: 9999-12-31 23:59:59.9999999 +14:00
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted datetimeoffset****
|
||||
c_det: 0001-01-01 00:00:00.0000000 -14:00
|
||||
c_rand: 9999-12-31 23:59:59.9999999 +14:00
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted datetimeoffset****
|
||||
c_det: 0001-01-01 00:00:00.0000000 -14:00
|
||||
c_rand: 9999-12-31 23:59:59.9999999 +14:00
|
||||
****Conversion from PDO::PARAM_BOOL to smalldatetime is supported****
|
||||
****Conversion from PDO::PARAM_INT to smalldatetime is supported****
|
||||
****Conversion from PDO::PARAM_STR to smalldatetime is supported****
|
||||
****Conversion from PDO::PARAM_LOB to smalldatetime is supported****
|
|
@ -0,0 +1,175 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data into datetime types with different precisions columns
|
||||
--DESCRIPTION--
|
||||
Test conversions between different datetime types
|
||||
With or without Always Encrypted, implicit conversion works if:
|
||||
1. From input of PDO::PARAM_BOOL to a any datetime column
|
||||
2. From input of PDO::PARAM_INT to a any datetime column
|
||||
3. From input of PDO::PARAM_STR to a any datetime column
|
||||
4. From input of PDO::PARAM_LOB to a any datetime column
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
function compareDate($dtout, $dtin, $dataType) {
|
||||
if ($dataType == "datetimeoffset") {
|
||||
$dtarr = explode(' ', $dtin);
|
||||
if (strpos($dtout, $dtarr[0]) !== false && strpos($dtout, $dtarr[1]) !== false && strpos($dtout, $dtarr[2]) !== false) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (strpos($dtout, $dtin) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$dataTypes = array("datetime2", "datetimeoffset", "time");
|
||||
$precisions = array(/*0,*/ 1, 2, 4, 7);
|
||||
$inputValuesInit = array("datetime2" => array("0001-01-01 00:00:00", "9999-12-31 23:59:59"),
|
||||
"datetimeoffset" => array("0001-01-01 00:00:00 -14:00", "9999-12-31 23:59:59 +14:00"),
|
||||
"time" => array("00:00:00", "23:59:59"));
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
foreach ($precisions as $m) {
|
||||
// add $m number of decimal digits to the some input values
|
||||
$inputValues[0] = $inputValuesInit[$dataType][0];
|
||||
$inputValues[1] = $inputValuesInit[$dataType][1];
|
||||
if ($m != 0) {
|
||||
if ($dataType == "datetime2") {
|
||||
$inputValues[1] .= "." . str_repeat("9", $m);
|
||||
} else if ($dataType == "datetimeoffset") {
|
||||
$dtoffsetPieces = explode(" ", $inputValues[1]);
|
||||
$inputValues[1] = $dtoffsetPieces[0] . " " . $dtoffsetPieces[1] . "." . str_repeat("9", $m) . " " . $dtoffsetPieces[2];
|
||||
} else if ($dataType == "time") {
|
||||
$inputValues[0] .= "." . str_repeat("0", $m);
|
||||
$inputValues[1] .= "." . str_repeat("9", $m);
|
||||
}
|
||||
}
|
||||
$typeFull = "$dataType($m)";
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
//create table containing datetime2(m), datetimeoffset(m), or time(m) columns
|
||||
$tbname = "test_" . $dataType . $m;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c_det"), new ColumnMeta($typeFull, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying PDO::PARAM_ types
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$r;
|
||||
$stmt = insertRow($conn, $tbname, array( "c_det" => new BindParamOp(1, $inputValues[0], $pdoParamType), "c_rand" => new BindParamOp(2, $inputValues[1], $pdoParamType)), "prepareBindParam", $r);
|
||||
|
||||
// check the case when inserting as PDO::PARAM_NULL
|
||||
// with or without AE: NULL is inserted
|
||||
if ($pdoParamType == "PDO::PARAM_NULL") {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!is_null($row['c_det']) || !is_null($row['c_rand'])) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should insert NULL\n";
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_BOOL, PDO::PARAM_INT, PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (compareDate($row['c_det'], $inputValues[0], $dataType) && compareDate($row['c_rand'], $inputValues[1], $dataType)) {
|
||||
echo "****Conversion from $pdoParamType to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
$conn->query("TRUNCATE TABLE $tbname");
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing datetime2(1):
|
||||
****Conversion from PDO::PARAM_BOOL to datetime2(1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to datetime2(1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to datetime2(1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to datetime2(1) is supported****
|
||||
|
||||
Testing datetime2(2):
|
||||
****Conversion from PDO::PARAM_BOOL to datetime2(2) is supported****
|
||||
****Conversion from PDO::PARAM_INT to datetime2(2) is supported****
|
||||
****Conversion from PDO::PARAM_STR to datetime2(2) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to datetime2(2) is supported****
|
||||
|
||||
Testing datetime2(4):
|
||||
****Conversion from PDO::PARAM_BOOL to datetime2(4) is supported****
|
||||
****Conversion from PDO::PARAM_INT to datetime2(4) is supported****
|
||||
****Conversion from PDO::PARAM_STR to datetime2(4) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to datetime2(4) is supported****
|
||||
|
||||
Testing datetime2(7):
|
||||
****Conversion from PDO::PARAM_BOOL to datetime2(7) is supported****
|
||||
****Conversion from PDO::PARAM_INT to datetime2(7) is supported****
|
||||
****Conversion from PDO::PARAM_STR to datetime2(7) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to datetime2(7) is supported****
|
||||
|
||||
Testing datetimeoffset(1):
|
||||
****Conversion from PDO::PARAM_BOOL to datetimeoffset(1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to datetimeoffset(1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to datetimeoffset(1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to datetimeoffset(1) is supported****
|
||||
|
||||
Testing datetimeoffset(2):
|
||||
****Conversion from PDO::PARAM_BOOL to datetimeoffset(2) is supported****
|
||||
****Conversion from PDO::PARAM_INT to datetimeoffset(2) is supported****
|
||||
****Conversion from PDO::PARAM_STR to datetimeoffset(2) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to datetimeoffset(2) is supported****
|
||||
|
||||
Testing datetimeoffset(4):
|
||||
****Conversion from PDO::PARAM_BOOL to datetimeoffset(4) is supported****
|
||||
****Conversion from PDO::PARAM_INT to datetimeoffset(4) is supported****
|
||||
****Conversion from PDO::PARAM_STR to datetimeoffset(4) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to datetimeoffset(4) is supported****
|
||||
|
||||
Testing datetimeoffset(7):
|
||||
****Conversion from PDO::PARAM_BOOL to datetimeoffset(7) is supported****
|
||||
****Conversion from PDO::PARAM_INT to datetimeoffset(7) is supported****
|
||||
****Conversion from PDO::PARAM_STR to datetimeoffset(7) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to datetimeoffset(7) is supported****
|
||||
|
||||
Testing time(1):
|
||||
****Conversion from PDO::PARAM_BOOL to time(1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to time(1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to time(1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to time(1) is supported****
|
||||
|
||||
Testing time(2):
|
||||
****Conversion from PDO::PARAM_BOOL to time(2) is supported****
|
||||
****Conversion from PDO::PARAM_INT to time(2) is supported****
|
||||
****Conversion from PDO::PARAM_STR to time(2) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to time(2) is supported****
|
||||
|
||||
Testing time(4):
|
||||
****Conversion from PDO::PARAM_BOOL to time(4) is supported****
|
||||
****Conversion from PDO::PARAM_INT to time(4) is supported****
|
||||
****Conversion from PDO::PARAM_STR to time(4) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to time(4) is supported****
|
||||
|
||||
Testing time(7):
|
||||
****Conversion from PDO::PARAM_BOOL to time(7) is supported****
|
||||
****Conversion from PDO::PARAM_INT to time(7) is supported****
|
||||
****Conversion from PDO::PARAM_STR to time(7) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to time(7) is supported****
|
|
@ -0,0 +1,294 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data into decimal types columns
|
||||
--DESCRIPTION--
|
||||
Test conversions between different decimal types
|
||||
With Always Encrypted, implicit conversion works if:
|
||||
1. From input of PDO::PARAM_BOOL to a any decimal column
|
||||
2. From input of PDO::PARAM_INT to a any decimal column
|
||||
3. From input of PDO::PARAM_STR to a any decimal column
|
||||
4. From input of PDO::PARAM_LOB to a any decimal column
|
||||
Without Always Encrypted, all of the above should work except for:
|
||||
1. From input of PDO::PARAM_STR to a decimal column and the input has more than 14 digits to the left of the decimal
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array("decimal", "numeric");
|
||||
$precisions = array(1 => array(0, 1),
|
||||
4 => array(0, 1, 4),
|
||||
16 => array(0, 1, 4, 16),
|
||||
38 => array(0, 1, 4, 16, 38));
|
||||
$inputValuesInit = array(92233720368547758089223372036854775808, -92233720368547758089223372036854775808);
|
||||
$inputPrecision = 38;
|
||||
|
||||
try {
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
foreach ($precisions as $m1 => $scales) {
|
||||
foreach ($scales as $m2) {
|
||||
// change the number of integers in the input values to be $m1 - $m2
|
||||
$precDiff = $inputPrecision - ($m1 - $m2);
|
||||
$inputValues = $inputValuesInit;
|
||||
foreach ($inputValues as &$inputValue) {
|
||||
$inputValue = $inputValue / pow(10, $precDiff);
|
||||
}
|
||||
|
||||
// compute the epsilon for comparing doubles
|
||||
// float in PHP only has a precision of roughtly 14 digits: http://php.net/manual/en/language.types.float.php
|
||||
$epsilon;
|
||||
if ($m1 < 14) {
|
||||
$epsilon = pow(10, $m2 * -1);
|
||||
} else {
|
||||
$numint = $m1 - $m2;
|
||||
if ($numint < 14) {
|
||||
$epsilon = pow(10, (14 - $numint) * -1);
|
||||
} else {
|
||||
$epsilon = pow(10, $numint - 14);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$typeFull = "$dataType($m1, $m2)";
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing decimal(m1, m2) or numeric(m1, m2) columns
|
||||
$tbname = "test_" . $dataType . $m1 . $m2;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c_det"), new ColumnMeta($typeFull, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying PDO::PARAM_ types
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$r;
|
||||
$stmt = insertRow($conn, $tbname, array("c_det" => new BindParamOp(1, $inputValues[0], $pdoParamType), "c_rand" => new BindParamOp(2, $inputValues[1], $pdoParamType)), "prepareBindParam", $r);
|
||||
|
||||
// check the case when inserting as PDO::PARAM_NULL
|
||||
// with or without AE: NULL is inserted
|
||||
if ($pdoParamType == "PDO::PARAM_NULL") {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!is_null($row['c_det']) || !is_null($row['c_rand'])) {
|
||||
echo "NULL should have been inserted with $pdoParamType\n";
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_STR and the input has more than 14 digits to the left of the decimal
|
||||
// with AE: should work
|
||||
// without AE: should not work
|
||||
// when the input has greater than 14 digits to the left of the decimal, the double is translated by PHP to scientific notation
|
||||
// inserting a scientific notation string fails
|
||||
} elseif ($pdoParamType == "PDO::PARAM_STR" && $m1 - $m2 > 14) {
|
||||
if (!isAEConnected()) {
|
||||
if ($r !== false) {
|
||||
echo "PDO param type $pdoParamType should not be compatible with $typeFull when the number of integers is greater than 14\n";
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should be supported\n";
|
||||
}
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (abs($row['c_det'] - $inputValues[0]) > $epsilon ||
|
||||
abs($row['c_rand'] - $inputValues[1]) > $epsilon) {
|
||||
echo "Conversion from $pdoParamType to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_STR with input less than 14 digits to the left of the decimal
|
||||
// and PDO::PARAM_BOOL, PDO::PARAM_INT or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should be supported\n";
|
||||
}
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (abs($row['c_det'] - $inputValues[0]) > $epsilon ||
|
||||
abs($row['c_rand'] - $inputValues[1]) > $epsilon) {
|
||||
// TODO: this is a workaround for the test to pass!!!!!
|
||||
// with AE, doubles cannot be inserted into a decimal(38, 38) column
|
||||
// remove the following if block to see the bug
|
||||
// for more information see VSO task 2723
|
||||
if (isAEConnected() && $m1 == 38 && $m2 == 38) {
|
||||
echo "****Conversion from $pdoParamType to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $typeFull causes data corruption\n";
|
||||
}
|
||||
} else {
|
||||
echo "****Conversion from $pdoParamType to $typeFull is supported****\n";
|
||||
}
|
||||
}
|
||||
$conn->query("TRUNCATE TABLE $tbname");
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing decimal(1, 0):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(1, 0) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(1, 0) is supported****
|
||||
****Conversion from PDO::PARAM_STR to decimal(1, 0) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(1, 0) is supported****
|
||||
|
||||
Testing decimal(1, 1):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(1, 1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(1, 1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to decimal(1, 1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(1, 1) is supported****
|
||||
|
||||
Testing decimal(4, 0):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(4, 0) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(4, 0) is supported****
|
||||
****Conversion from PDO::PARAM_STR to decimal(4, 0) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(4, 0) is supported****
|
||||
|
||||
Testing decimal(4, 1):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(4, 1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(4, 1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to decimal(4, 1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(4, 1) is supported****
|
||||
|
||||
Testing decimal(4, 4):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(4, 4) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(4, 4) is supported****
|
||||
****Conversion from PDO::PARAM_STR to decimal(4, 4) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(4, 4) is supported****
|
||||
|
||||
Testing decimal(16, 0):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(16, 0) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(16, 0) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(16, 0) is supported****
|
||||
|
||||
Testing decimal(16, 1):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(16, 1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(16, 1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(16, 1) is supported****
|
||||
|
||||
Testing decimal(16, 4):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(16, 4) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(16, 4) is supported****
|
||||
****Conversion from PDO::PARAM_STR to decimal(16, 4) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(16, 4) is supported****
|
||||
|
||||
Testing decimal(16, 16):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(16, 16) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(16, 16) is supported****
|
||||
****Conversion from PDO::PARAM_STR to decimal(16, 16) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(16, 16) is supported****
|
||||
|
||||
Testing decimal(38, 0):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(38, 0) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(38, 0) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(38, 0) is supported****
|
||||
|
||||
Testing decimal(38, 1):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(38, 1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(38, 1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(38, 1) is supported****
|
||||
|
||||
Testing decimal(38, 4):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(38, 4) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(38, 4) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(38, 4) is supported****
|
||||
|
||||
Testing decimal(38, 16):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(38, 16) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(38, 16) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(38, 16) is supported****
|
||||
|
||||
Testing decimal(38, 38):
|
||||
****Conversion from PDO::PARAM_BOOL to decimal(38, 38) is supported****
|
||||
****Conversion from PDO::PARAM_INT to decimal(38, 38) is supported****
|
||||
****Conversion from PDO::PARAM_STR to decimal(38, 38) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to decimal(38, 38) is supported****
|
||||
|
||||
Testing numeric(1, 0):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(1, 0) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(1, 0) is supported****
|
||||
****Conversion from PDO::PARAM_STR to numeric(1, 0) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(1, 0) is supported****
|
||||
|
||||
Testing numeric(1, 1):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(1, 1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(1, 1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to numeric(1, 1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(1, 1) is supported****
|
||||
|
||||
Testing numeric(4, 0):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(4, 0) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(4, 0) is supported****
|
||||
****Conversion from PDO::PARAM_STR to numeric(4, 0) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(4, 0) is supported****
|
||||
|
||||
Testing numeric(4, 1):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(4, 1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(4, 1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to numeric(4, 1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(4, 1) is supported****
|
||||
|
||||
Testing numeric(4, 4):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(4, 4) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(4, 4) is supported****
|
||||
****Conversion from PDO::PARAM_STR to numeric(4, 4) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(4, 4) is supported****
|
||||
|
||||
Testing numeric(16, 0):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(16, 0) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(16, 0) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(16, 0) is supported****
|
||||
|
||||
Testing numeric(16, 1):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(16, 1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(16, 1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(16, 1) is supported****
|
||||
|
||||
Testing numeric(16, 4):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(16, 4) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(16, 4) is supported****
|
||||
****Conversion from PDO::PARAM_STR to numeric(16, 4) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(16, 4) is supported****
|
||||
|
||||
Testing numeric(16, 16):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(16, 16) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(16, 16) is supported****
|
||||
****Conversion from PDO::PARAM_STR to numeric(16, 16) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(16, 16) is supported****
|
||||
|
||||
Testing numeric(38, 0):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(38, 0) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(38, 0) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(38, 0) is supported****
|
||||
|
||||
Testing numeric(38, 1):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(38, 1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(38, 1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(38, 1) is supported****
|
||||
|
||||
Testing numeric(38, 4):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(38, 4) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(38, 4) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(38, 4) is supported****
|
||||
|
||||
Testing numeric(38, 16):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(38, 16) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(38, 16) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(38, 16) is supported****
|
||||
|
||||
Testing numeric(38, 38):
|
||||
****Conversion from PDO::PARAM_BOOL to numeric(38, 38) is supported****
|
||||
****Conversion from PDO::PARAM_INT to numeric(38, 38) is supported****
|
||||
****Conversion from PDO::PARAM_STR to numeric(38, 38) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to numeric(38, 38) is supported****
|
|
@ -0,0 +1,113 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data into float types columns
|
||||
--DESCRIPTION--
|
||||
Test conversions between different float types
|
||||
With or without Always Encrypted, implicit conversion works if:
|
||||
1. From input of PDO::PARAM_BOOL to a float column
|
||||
2. From input of PDO::PARAM_INT to a float column
|
||||
3. From input of PDO::PARAM_STR to a float column
|
||||
4. From input of PDO::PARAM_LOB to a float column
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataType = "float";
|
||||
$bits = array(1, 12, 24, 36, 53);
|
||||
$inputValues = array(9223372036854775808.9223372036854775808, -9223372036854775808.9223372036854775808);
|
||||
$numint = 19;
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
foreach ($bits as $m) {
|
||||
// compute the epsilon for comparing doubles
|
||||
// when $m <= 24, the precision is 7 digits
|
||||
// when $m > 24, the precision is 15 digits, but PHP float only supports up to 14 digits
|
||||
$epsilon;
|
||||
if ($m <= 24) {
|
||||
$epsilon = pow(10, $numint - 7);
|
||||
} else {
|
||||
$epsilon = pow(10, $numint - 14);
|
||||
}
|
||||
|
||||
$typeFull = "$dataType($m)";
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
//create table containing float(m) columns
|
||||
$tbname = "test_" . $dataType . $m;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c_det"), new ColumnMeta($typeFull, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying PDO::PARAM_ types
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$r;
|
||||
$stmt = insertRow($conn, $tbname, array( "c_det" => new BindParamOp(1, $inputValues[0], $pdoParamType), "c_rand" => new BindParamOp(2, $inputValues[1], $pdoParamType)), "prepareBindParam", $r);
|
||||
|
||||
// check the case when inserting as PDO::PARAM_NULL
|
||||
// with or without AE: NULL is inserted
|
||||
if ($pdoParamType == "PDO::PARAM_NULL") {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!is_null($row['c_det']) || !is_null($row['c_rand'])) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should insert NULL\n";
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_BOOL, PDO::PARAM_INT, PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (abs($row['c_det'] - $inputValues[0]) < $epsilon && abs($row['c_rand'] - $inputValues[1]) < $epsilon) {
|
||||
echo "****Conversion from $pdoParamType to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
$conn->query("TRUNCATE TABLE $tbname");
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing float(1):
|
||||
****Conversion from PDO::PARAM_BOOL to float(1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to float(1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to float(1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to float(1) is supported****
|
||||
|
||||
Testing float(12):
|
||||
****Conversion from PDO::PARAM_BOOL to float(12) is supported****
|
||||
****Conversion from PDO::PARAM_INT to float(12) is supported****
|
||||
****Conversion from PDO::PARAM_STR to float(12) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to float(12) is supported****
|
||||
|
||||
Testing float(24):
|
||||
****Conversion from PDO::PARAM_BOOL to float(24) is supported****
|
||||
****Conversion from PDO::PARAM_INT to float(24) is supported****
|
||||
****Conversion from PDO::PARAM_STR to float(24) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to float(24) is supported****
|
||||
|
||||
Testing float(36):
|
||||
****Conversion from PDO::PARAM_BOOL to float(36) is supported****
|
||||
****Conversion from PDO::PARAM_INT to float(36) is supported****
|
||||
****Conversion from PDO::PARAM_STR to float(36) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to float(36) is supported****
|
||||
|
||||
Testing float(53):
|
||||
****Conversion from PDO::PARAM_BOOL to float(53) is supported****
|
||||
****Conversion from PDO::PARAM_INT to float(53) is supported****
|
||||
****Conversion from PDO::PARAM_STR to float(53) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to float(53) is supported****
|
|
@ -0,0 +1,172 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data into nchar types columns with different sizes
|
||||
--DESCRIPTION--
|
||||
Test conversions between different nchar types of different sizes
|
||||
With or without Always Encrypted, implicit conversion works if:
|
||||
1. From input of PDO::PARAM_BOOL to any nchar column
|
||||
2. From input of PDO::PARAM_INT to any nchar column
|
||||
3. From input of PDO::PARAM_STR to any nchar column
|
||||
4. From input of PDO::PARAM_LOB to any nchar column
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
|
||||
$dataTypes = array("nchar", "nvarchar", "nvarchar(max)");
|
||||
$lengths = array(1, 8, 64, 512, 4000);
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
foreach ($dataTypes as $dataType) {
|
||||
$maxcol = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $m) {
|
||||
if ($maxcol !== false) {
|
||||
$typeFull = $dataType;
|
||||
} else {
|
||||
$typeFull = "$dataType($m)";
|
||||
}
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing nchar(m) or nvarchar(m) columns
|
||||
// only one column is created because a row has a limitation of 8060 bytes
|
||||
// for lengths 4096 and 8000, cannot create 2 columns as it will exceed the maximum row sizes
|
||||
// for AE, only testing deterministic here, randomized is tested in the char test
|
||||
$tbname = "test_" . str_replace(array('(', ')'), '', $dataType) . $m;
|
||||
$colMetaArr = array(new ColumnMeta($typeFull, "c1"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$input = str_repeat("d", $m);
|
||||
|
||||
// insert by specifying PDO::PARAM_ types
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$r;
|
||||
$stmt = insertRow($conn, $tbname, array( "c1" => new BindParamOp(1, $input, $pdoParamType)), "prepareBindParam", $r);
|
||||
|
||||
// check the case when inserting as PDO::PARAM_NULL
|
||||
// with or without AE: NULL is inserted
|
||||
if ($pdoParamType == "PDO::PARAM_NULL") {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c1 FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!is_null($row['c1'])) {
|
||||
echo "Conversion from $pdoParamType to $typeFull should insert NULL\n";
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_BOOL, PDO::PARAM_INT, PDO::PARAM_STR or PDO{{PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
$sql = "SELECT c1 FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (strlen($row['c1']) == $m) {
|
||||
echo "****Conversion from $pdoParamType to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
$conn->query("TRUNCATE TABLE $tbname");
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing nchar(1):
|
||||
****Conversion from PDO::PARAM_BOOL to nchar(1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nchar(1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nchar(1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nchar(1) is supported****
|
||||
|
||||
Testing nchar(8):
|
||||
****Conversion from PDO::PARAM_BOOL to nchar(8) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nchar(8) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nchar(8) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nchar(8) is supported****
|
||||
|
||||
Testing nchar(64):
|
||||
****Conversion from PDO::PARAM_BOOL to nchar(64) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nchar(64) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nchar(64) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nchar(64) is supported****
|
||||
|
||||
Testing nchar(512):
|
||||
****Conversion from PDO::PARAM_BOOL to nchar(512) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nchar(512) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nchar(512) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nchar(512) is supported****
|
||||
|
||||
Testing nchar(4000):
|
||||
****Conversion from PDO::PARAM_BOOL to nchar(4000) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nchar(4000) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nchar(4000) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nchar(4000) is supported****
|
||||
|
||||
Testing nvarchar(1):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(1) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(1) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(1) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(1) is supported****
|
||||
|
||||
Testing nvarchar(8):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(8) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(8) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(8) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(8) is supported****
|
||||
|
||||
Testing nvarchar(64):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(64) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(64) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(64) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(64) is supported****
|
||||
|
||||
Testing nvarchar(512):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(512) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(512) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(512) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(512) is supported****
|
||||
|
||||
Testing nvarchar(4000):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(4000) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(4000) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(4000) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(4000) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(max) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(max) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(max) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(max) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from PDO::PARAM_BOOL to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_INT to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_STR to nvarchar(max) is supported****
|
||||
****Conversion from PDO::PARAM_LOB to nvarchar(max) is supported****
|
|
@ -1,39 +1,123 @@
|
|||
--TEST--
|
||||
Test for inserting and retrieving encrypted data of numeric types
|
||||
Test for inserting encrypted data into numeric types columns
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
Test conversions between different numeric types
|
||||
With Always Encrypted, implicit conversion works if:
|
||||
1. From input of PDO::PARAM_BOOL to a real column
|
||||
2. From input of PDO::PARAM_INT to any numeric column
|
||||
3. From input of PDO::PARAM_STR to any numeric column
|
||||
4. From input of PDO::PARAM_LOB to any numeric column
|
||||
Without Always Encrypted, all of the above work except for input of PDO::PARAM_STR to a bigint column in a x86 platform
|
||||
PDO::PARAM_STR does not work for bigint in a x86 platform because the maximum value of an int is about 2147483647
|
||||
Whereas in a x64 platform, the maximum value is about 9E18
|
||||
In a x86 platform, when an integer is > 2147483647, PHP implicitly changees it to a float, represented by scientific notation
|
||||
When inserting a scientific notation form numeric string, SQL Server returns a converting data type nvarchar to bigint error
|
||||
Works for with AE because the sqltype used for binding parameter is determined by SQLDescribeParam,
|
||||
unlike without AE, the sqltype is predicted to be nvarchar or varchar when the input is a string
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
$dataTypes = array( "bit", "tinyint", "smallint", "int", "decimal(18,5)", "numeric(10,5)", "float", "real" );
|
||||
|
||||
$dataTypes = array("bit", "tinyint", "smallint", "int", "bigint", "real");
|
||||
$epsilon = 1;
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
$conn = connect("", array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
echo "\nTesting $dataType:\n";
|
||||
|
||||
// create table
|
||||
$tbname = getTableName();
|
||||
// create table containing bit, tinyint, smallint, int, bigint, or real columns
|
||||
$tbname = "test_" . $dataType;
|
||||
$colMetaArr = array(new ColumnMeta($dataType, "c_det"), new ColumnMeta($dataType, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// test each PDO::PARAM_ type
|
||||
// insert by specifying PDO::PARAM_ types
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
// insert a row
|
||||
$inputValues = array_slice(${explode("(", $dataType)[0] . "_params"}, 1, 2);
|
||||
$r;
|
||||
if ($dataType == "decimal(18,5)") {
|
||||
$stmt = insertRow($conn, $tbname, array( "c_det" => new BindParamOp(1, (string)$inputValues[0], $pdoParamType), "c_rand" => new BindParamOp(2, (string)$inputValues[1], $pdoParamType)), "prepareBindParam", $r);
|
||||
$stmt = insertRow($conn, $tbname, array( "c_det" => new BindParamOp(1, $inputValues[0], $pdoParamType), "c_rand" => new BindParamOp(2, $inputValues[1], $pdoParamType)), "prepareBindParam", $r);
|
||||
|
||||
// check the case when inserting as PDO::PARAM_NULL
|
||||
// with or without AE: NULL is inserted
|
||||
if ($pdoParamType == "PDO::PARAM_NULL") {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $dataType should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!is_null($row['c_det']) || !is_null($row['c_rand'])) {
|
||||
echo "Conversion from $pdoParamType to $dataType should insert NULL\n";
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_BOOL
|
||||
// with or without AE: 1 or 0 should be inserted when inserting into an integer column
|
||||
// double is inserted when inserting into a real column
|
||||
} else if ($pdoParamType == "PDO::PARAM_BOOL") {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $dataType should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if ($dataType == "real") {
|
||||
if (abs($row['c_det'] - $inputValues[0]) < $epsilon && abs($row['c_rand'] - $inputValues[1]) < $epsilon) {
|
||||
echo "****Conversion from $pdoParamType to $dataType is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $dataType causes data corruption\n";
|
||||
}
|
||||
} else {
|
||||
if ($row['c_det'] != ($inputValues[0] != 0) && $row['c_rand'] != ($inputValues[1] != 0)) {
|
||||
echo "Conversion from $pdoParamType to $dataType insert a boolean\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_STR into a bigint column
|
||||
// with AE: should work
|
||||
// without AE: should not work on a x86 platform
|
||||
} else if ($dataType == "bigint" && $pdoParamType == "PDO::PARAM_STR") {
|
||||
if (!isAEConnected() && PHP_INT_SIZE == 4) {
|
||||
if ($r !== false) {
|
||||
echo "Conversion from $pdoParamType to $dataType should not be supported\n";
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $dataType should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if ($row['c_det'] != $inputValues[0] && $row['c_rand'] != $inputValues[1]) {
|
||||
echo "Conversion from $pdoParamType to $dataType causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// check the case when inserting as PDO::PARAM_INT, PDO::PARAM_STR or PDO::PARAM_LOB
|
||||
// with or without AE: should work
|
||||
} else {
|
||||
$stmt = insertRow($conn, $tbname, array( "c_det" => new BindParamOp(1, $inputValues[0], $pdoParamType), "c_rand" => new BindParamOp(2, $inputValues[1], $pdoParamType)), "prepareBindParam", $r);
|
||||
}
|
||||
if ($r === false) {
|
||||
isIncompatibleTypesError($stmt, $dataType, $pdoParamType);
|
||||
} else {
|
||||
echo "****PDO param type $pdoParamType is compatible with encrypted $dataType****\n";
|
||||
fetchAll($conn, $tbname);
|
||||
if ($r === false) {
|
||||
echo "Conversion from $pdoParamType to $dataType should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = $conn->query($sql);
|
||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if ($dataType == "real") {
|
||||
if (abs($row['c_det'] - $inputValues[0]) < $epsilon && abs($row['c_rand'] - $inputValues[1]) < $epsilon) {
|
||||
echo "****Conversion from $pdoParamType to $dataType is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $dataType causes data corruption\n";
|
||||
}
|
||||
} else {
|
||||
if ($row['c_det'] == $inputValues[0] && $row['c_rand'] == $inputValues[1]) {
|
||||
echo "****Conversion from $pdoParamType to $dataType is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $pdoParamType to $dataType causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$conn->query("TRUNCATE TABLE $tbname");
|
||||
}
|
||||
|
@ -46,139 +130,32 @@ try {
|
|||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
|
||||
Testing bit:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted bit****
|
||||
c_det: 1
|
||||
c_rand: 0
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted bit****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted bit****
|
||||
c_det: 1
|
||||
c_rand: 0
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted bit****
|
||||
c_det: 1
|
||||
c_rand: 0
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted bit****
|
||||
c_det: 1
|
||||
c_rand: 0
|
||||
****Conversion from PDO::PARAM_INT to bit is supported****
|
||||
****Conversion from PDO::PARAM_STR to bit is supported****
|
||||
****Conversion from PDO::PARAM_LOB to bit is supported****
|
||||
|
||||
Testing tinyint:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted tinyint****
|
||||
c_det: 0
|
||||
c_rand: 1
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted tinyint****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted tinyint****
|
||||
c_det: 0
|
||||
c_rand: 255
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted tinyint****
|
||||
c_det: 0
|
||||
c_rand: 255
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted tinyint****
|
||||
c_det: 0
|
||||
c_rand: 255
|
||||
****Conversion from PDO::PARAM_INT to tinyint is supported****
|
||||
****Conversion from PDO::PARAM_STR to tinyint is supported****
|
||||
****Conversion from PDO::PARAM_LOB to tinyint is supported****
|
||||
|
||||
Testing smallint:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted smallint****
|
||||
c_det: 1
|
||||
c_rand: 1
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted smallint****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted smallint****
|
||||
c_det: -32767
|
||||
c_rand: 32767
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted smallint****
|
||||
c_det: -32767
|
||||
c_rand: 32767
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted smallint****
|
||||
c_det: -32767
|
||||
c_rand: 32767
|
||||
****Conversion from PDO::PARAM_INT to smallint is supported****
|
||||
****Conversion from PDO::PARAM_STR to smallint is supported****
|
||||
****Conversion from PDO::PARAM_LOB to smallint is supported****
|
||||
|
||||
Testing int:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted int****
|
||||
c_det: 1
|
||||
c_rand: 1
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted int****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted int****
|
||||
c_det: -2147483647
|
||||
c_rand: 2147483647
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted int****
|
||||
c_det: -2147483647
|
||||
c_rand: 2147483647
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted int****
|
||||
c_det: -2147483647
|
||||
c_rand: 2147483647
|
||||
****Conversion from PDO::PARAM_INT to int is supported****
|
||||
****Conversion from PDO::PARAM_STR to int is supported****
|
||||
****Conversion from PDO::PARAM_LOB to int is supported****
|
||||
|
||||
Testing decimal(18,5):
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted decimal(18,5)****
|
||||
c_det: -9223372036854.80000
|
||||
c_rand: 9223372036854.80000
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted decimal(18,5)****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted decimal(18,5)****
|
||||
c_det: -9223372036854.80000
|
||||
c_rand: 9223372036854.80000
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted decimal(18,5)****
|
||||
c_det: -9223372036854.80000
|
||||
c_rand: 9223372036854.80000
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted decimal(18,5)****
|
||||
c_det: -9223372036854.80000
|
||||
c_rand: 9223372036854.80000
|
||||
|
||||
Testing numeric(10,5):
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted numeric(10,5)****
|
||||
c_det: -21474.83647
|
||||
c_rand: 21474.83647
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted numeric(10,5)****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted numeric(10,5)****
|
||||
c_det: -21474.83647
|
||||
c_rand: 21474.83647
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted numeric(10,5)****
|
||||
c_det: -21474.83647
|
||||
c_rand: 21474.83647
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted numeric(10,5)****
|
||||
c_det: -21474.83647
|
||||
c_rand: 21474.83647
|
||||
|
||||
Testing float:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted float****
|
||||
c_det: -9223372036.8547993
|
||||
c_rand: 9223372036.8547993
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted float****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted float****
|
||||
c_det: -9223372036.8547993
|
||||
c_rand: 9223372036.8547993
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted float****
|
||||
c_det: -9223372036.8547993
|
||||
c_rand: 9223372036.8547993
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted float****
|
||||
c_det: -9223372036.8547993
|
||||
c_rand: 9223372036.8547993
|
||||
Testing bigint:
|
||||
****Conversion from PDO::PARAM_INT to bigint is supported****
|
||||
****Conversion from PDO::PARAM_LOB to bigint is supported****
|
||||
|
||||
Testing real:
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted real****
|
||||
c_det: -2147.4829
|
||||
c_rand: 2147.4829
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted real****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted real****
|
||||
c_det: -2147.4829
|
||||
c_rand: 2147.4829
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted real****
|
||||
c_det: -2147.4829
|
||||
c_rand: 2147.4829
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted real****
|
||||
c_det: -2147.4829
|
||||
c_rand: 2147.4829
|
||||
****Conversion from PDO::PARAM_BOOL to real is supported****
|
||||
****Conversion from PDO::PARAM_INT to real is supported****
|
||||
****Conversion from PDO::PARAM_STR to real is supported****
|
||||
****Conversion from PDO::PARAM_LOB to real is supported****
|
|
@ -1,112 +0,0 @@
|
|||
--TEST--
|
||||
Test for inserting and retrieving encrypted data of string types
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
require_once("AEData.inc");
|
||||
$dataTypes = array("char(5)", "varchar(max)", "nchar(5)", "nvarchar(max)");
|
||||
try {
|
||||
$conn = connect('', array(), PDO::ERRMODE_SILENT);
|
||||
foreach ($dataTypes as $dataType) {
|
||||
echo "\nTesting $dataType:\n";
|
||||
|
||||
// create table
|
||||
$tbname = getTableName();
|
||||
$colMetaArr = array(new ColumnMeta($dataType, "c_det"), new ColumnMeta($dataType, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// prepare statement for inserting into table
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
// insert a row
|
||||
$inputValues = array_slice(${explode("(", $dataType)[0] . "_params"}, 1, 2);
|
||||
$r;
|
||||
$stmt = insertRow($conn, $tbname, array( "c_det" => new BindParamOp(1, $inputValues[0], $pdoParamType),"c_rand" => new BindParamOp(2, $inputValues[1], $pdoParamType)), "prepareBindParam", $r);
|
||||
if ($r === false) {
|
||||
isIncompatibleTypesError($stmt, $dataType, $pdoParamType);
|
||||
} else {
|
||||
echo "****PDO param type $pdoParamType is compatible with encrypted $dataType****\n";
|
||||
fetchAll($conn, $tbname);
|
||||
}
|
||||
$conn->query("TRUNCATE TABLE $tbname");
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
--EXPECT--
|
||||
|
||||
Testing char(5):
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted char(5)****
|
||||
c_det: -leng
|
||||
c_rand: th, n
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted char(5)****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted char(5)****
|
||||
c_det: -leng
|
||||
c_rand: th, n
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted char(5)****
|
||||
c_det: -leng
|
||||
c_rand: th, n
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted char(5)****
|
||||
c_det: -leng
|
||||
c_rand: th, n
|
||||
|
||||
Testing varchar(max):
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted varchar(max)****
|
||||
c_det: Use varchar(max) when the sizes of the column data entries vary considerably, and the size might exceed 8,000 bytes.
|
||||
c_rand: Each non-null varchar(max) or nvarchar(max) column requires 24 bytes of additional fixed allocation which counts against the 8,060 byte row limit during a sort operation.
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted varchar(max)****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted varchar(max)****
|
||||
c_det: Use varchar(max) when the sizes of the column data entries vary considerably, and the size might exceed 8,000 bytes.
|
||||
c_rand: Each non-null varchar(max) or nvarchar(max) column requires 24 bytes of additional fixed allocation which counts against the 8,060 byte row limit during a sort operation.
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted varchar(max)****
|
||||
c_det: Use varchar(max) when the sizes of the column data entries vary considerably, and the size might exceed 8,000 bytes.
|
||||
c_rand: Each non-null varchar(max) or nvarchar(max) column requires 24 bytes of additional fixed allocation which counts against the 8,060 byte row limit during a sort operation.
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted varchar(max)****
|
||||
c_det: Use varchar(max) when the sizes of the column data entries vary considerably, and the size might exceed 8,000 bytes.
|
||||
c_rand: Each non-null varchar(max) or nvarchar(max) column requires 24 bytes of additional fixed allocation which counts against the 8,060 byte row limit during a sort operation.
|
||||
|
||||
Testing nchar(5):
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted nchar(5)****
|
||||
c_det: -leng
|
||||
c_rand: th Un
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted nchar(5)****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted nchar(5)****
|
||||
c_det: -leng
|
||||
c_rand: th Un
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted nchar(5)****
|
||||
c_det: -leng
|
||||
c_rand: th Un
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted nchar(5)****
|
||||
c_det: -leng
|
||||
c_rand: th Un
|
||||
|
||||
Testing nvarchar(max):
|
||||
****PDO param type PDO::PARAM_BOOL is compatible with encrypted nvarchar(max)****
|
||||
c_det: When prefixing a string constant with the letter N, the implicit conversion will result in a Unicode string if the constant to convert does not exceed the max length for a Unicode string data type (4,000).
|
||||
c_rand: Otherwise, the implicit conversion will result in a Unicode large-value (max).
|
||||
****PDO param type PDO::PARAM_NULL is compatible with encrypted nvarchar(max)****
|
||||
c_det:
|
||||
c_rand:
|
||||
****PDO param type PDO::PARAM_INT is compatible with encrypted nvarchar(max)****
|
||||
c_det: When prefixing a string constant with the letter N, the implicit conversion will result in a Unicode string if the constant to convert does not exceed the max length for a Unicode string data type (4,000).
|
||||
c_rand: Otherwise, the implicit conversion will result in a Unicode large-value (max).
|
||||
****PDO param type PDO::PARAM_STR is compatible with encrypted nvarchar(max)****
|
||||
c_det: When prefixing a string constant with the letter N, the implicit conversion will result in a Unicode string if the constant to convert does not exceed the max length for a Unicode string data type (4,000).
|
||||
c_rand: Otherwise, the implicit conversion will result in a Unicode large-value (max).
|
||||
****PDO param type PDO::PARAM_LOB is compatible with encrypted nvarchar(max)****
|
||||
c_det: When prefixing a string constant with the letter N, the implicit conversion will result in a Unicode string if the constant to convert does not exceed the max length for a Unicode string data type (4,000).
|
||||
c_rand: Otherwise, the implicit conversion will result in a Unicode large-value (max).
|
210
test/functional/pdo_sqlsrv/pdo_ae_output_param_binary_size.phpt
Normal file
210
test/functional/pdo_sqlsrv/pdo_ae_output_param_binary_size.phpt
Normal file
|
@ -0,0 +1,210 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data of binary types of various sizes as output parameters
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
--ENV--
|
||||
PHPT_EXEC=true
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
$dataTypes = array("binary", "varbinary", "varbinary(max)");
|
||||
$lengths = array(1, 2, 4, 8, 64, 512, 4000);
|
||||
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.", "07006" => "Restricted data type attribute violation");
|
||||
|
||||
$pdoParamTypes = array(
|
||||
PDO::PARAM_BOOL, // 5
|
||||
PDO::PARAM_NULL, // 0
|
||||
PDO::PARAM_INT, // 1
|
||||
PDO::PARAM_STR, // 2
|
||||
PDO::PARAM_LOB // 3
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
function printValues($msg, $det, $rand, $input0, $input1)
|
||||
{
|
||||
echo $msg;
|
||||
echo "input 0: "; var_dump($input0);
|
||||
echo "fetched: "; var_dump($det);
|
||||
echo "input 1: "; var_dump($input1);
|
||||
echo "fetched: "; var_dump($rand);
|
||||
}
|
||||
|
||||
function convert2Hex($ch, $length)
|
||||
{
|
||||
// Without AE, the binary values returned as integers will
|
||||
// have lengths no more than 4 times the original hex string value
|
||||
// (e.g. string(8) "65656565") - limited by the buffer sizes
|
||||
if (!isAEConnected()) {
|
||||
$count = ($length <= 2) ? $length : 4;
|
||||
} else {
|
||||
$count = $length;
|
||||
}
|
||||
|
||||
return str_repeat(bin2hex($ch), $count);
|
||||
}
|
||||
|
||||
function testOutputBinary($inout)
|
||||
{
|
||||
global $pdoParamTypes, $dataTypes, $lengths, $errors;
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
$tbname = "test_binary_types";
|
||||
$spname = "test_binary_proc";
|
||||
$ch0 = 'd';
|
||||
$ch1 = 'e';
|
||||
|
||||
foreach ($dataTypes as $dataType) {
|
||||
$maxtype = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $length) {
|
||||
if ($maxtype !== false) {
|
||||
$type = $dataType;
|
||||
} else {
|
||||
$type = "$dataType($length)";
|
||||
}
|
||||
trace("\nTesting $type:\n");
|
||||
|
||||
//create and populate table
|
||||
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$input0 = str_repeat($ch0, $length);
|
||||
$input1 = str_repeat($ch1, $length);
|
||||
$ord0 = convert2Hex($ch0, $length);
|
||||
$ord1 = convert2Hex($ch1, $length);
|
||||
insertRow($conn, $tbname, array("c_det" => new BindParamOp(1, $input0, "PDO::PARAM_LOB", 0, "PDO::SQLSRV_ENCODING_BINARY"),
|
||||
"c_rand" => new BindParamOp(2, $input1, "PDO::PARAM_LOB", 0, "PDO::SQLSRV_ENCODING_BINARY")), "prepareBindParam");
|
||||
|
||||
// fetch with PDO::bindParam using a stored procedure
|
||||
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||
createProc($conn, $spname, $procArgs, $procCode);
|
||||
|
||||
// call stored procedure
|
||||
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$stmt = $conn->prepare($outSql);
|
||||
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||
|
||||
if ($inout && $pdoParamType != PDO::PARAM_STR) {
|
||||
// Currently do not support getting binary as strings + INOUT param
|
||||
// See VSO 2829 for details
|
||||
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||
} else {
|
||||
$paramType = $pdoParamType;
|
||||
}
|
||||
|
||||
$det = "";
|
||||
$rand = "";
|
||||
if ($pdoParamType == PDO::PARAM_STR || $pdoParamType == PDO::PARAM_LOB) {
|
||||
$stmt->bindParam(1, $det, $paramType, $length, PDO::SQLSRV_ENCODING_BINARY);
|
||||
$stmt->bindParam(2, $rand, $paramType, $length, PDO::SQLSRV_ENCODING_BINARY);
|
||||
} elseif ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||
$det = $rand = 0;
|
||||
$stmt->bindParam(1, $det, $paramType, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
|
||||
$stmt->bindParam(2, $rand, $paramType, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
|
||||
} else {
|
||||
$stmt->bindParam(1, $det, $paramType, $length);
|
||||
$stmt->bindParam(2, $rand, $paramType, $length);
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
|
||||
$errMsg = "****$dataType as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($pdoParamType == PDO::PARAM_STR) {
|
||||
if ($det !== $input0 || $rand !== $input1) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} elseif ($pdoParamType == PDO::PARAM_BOOL) {
|
||||
// for boolean values, they should all be bool(true)
|
||||
// because all floats are non-zeroes
|
||||
// This only occurs without AE
|
||||
// With AE enabled, this would have caused an exception
|
||||
if (!$det || !$rand) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} else {
|
||||
// $pdoParamType is PDO::PARAM_INT
|
||||
// This only occurs without AE -- likely a rare use case
|
||||
// With AE enabled, this would have caused an exception
|
||||
if (strval($det) != $ord0 || strval($rand) != $ord1) {
|
||||
printValues($errMsg, $det, $rand, $ord0, $ord1);
|
||||
}
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$message = $e->getMessage();
|
||||
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||
// Expected error IMSSP: "An invalid PHP type was specified
|
||||
// as an output parameter. DateTime objects, NULL values, and
|
||||
// streams cannot be specified as output parameters."
|
||||
$found = strpos($message, $errors['IMSSP']);
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} elseif ($pdoParamType == PDO::PARAM_BOOL || PDO::PARAM_INT) {
|
||||
if (isAEConnected()) {
|
||||
if ($pdoParamType == PDO::PARAM_INT) {
|
||||
// Expected to fail with this message
|
||||
$error = "String data, right truncated for output parameter";
|
||||
$found = strpos($message, $error);
|
||||
} else {
|
||||
// PDO::PARAM_BOOL -
|
||||
// Expected error 07006 with AE enabled:
|
||||
// "Restricted data type attribute violation"
|
||||
// The data value returned for a parameter bound as
|
||||
// SQL_PARAM_INPUT_OUTPUT or SQL_PARAM_OUTPUT could not
|
||||
// be converted to the data type identified by the
|
||||
// ValueType argument in SQLBindParameter.
|
||||
$found = strpos($message, $errors['07006']);
|
||||
}
|
||||
} else {
|
||||
// When not AE enabled, expected to fail with something like this message
|
||||
// "Implicit conversion from data type nvarchar(max) to binary is not allowed. Use the CONVERT function to run this query."
|
||||
// Sometimes it's about nvarchar too
|
||||
$error = "to $dataType is not allowed. Use the CONVERT function to run this query.";
|
||||
$found = strpos($message, $error);
|
||||
}
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} else {
|
||||
// catch all
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
}
|
||||
}
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
testOutputBinary(false);
|
||||
testOutputBinary(true);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
// drop the temporary table and stored procedure in case
|
||||
// the test failed without dropping them
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
$tbname = "test_binary_types";
|
||||
$spname = "test_binary_proc";
|
||||
$conn = connect();
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
unset($conn);
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
171
test/functional/pdo_sqlsrv/pdo_ae_output_param_char_size.phpt
Normal file
171
test/functional/pdo_sqlsrv/pdo_ae_output_param_char_size.phpt
Normal file
|
@ -0,0 +1,171 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data of char types of various sizes as output parameters
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
--ENV--
|
||||
PHPT_EXEC=true
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
$dataTypes = array("char", "varchar", "varchar(max)");
|
||||
$lengths = array(1, 8, 64, 512, 4000);
|
||||
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.",
|
||||
"22003" => "Numeric value out of range");
|
||||
|
||||
$pdoParamTypes = array(
|
||||
PDO::PARAM_BOOL, // 5
|
||||
PDO::PARAM_NULL, // 0
|
||||
PDO::PARAM_INT, // 1
|
||||
PDO::PARAM_STR, // 2
|
||||
PDO::PARAM_LOB // 3
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
function printValues($msg, $det, $rand, $input0, $input1)
|
||||
{
|
||||
echo $msg;
|
||||
echo "input 0: "; var_dump($input0);
|
||||
echo "fetched: "; var_dump($det);
|
||||
echo "input 1: "; var_dump($input1);
|
||||
echo "fetched: "; var_dump($rand);
|
||||
}
|
||||
|
||||
function testOutputChars($inout)
|
||||
{
|
||||
global $pdoParamTypes, $dataTypes, $lengths, $errors;
|
||||
|
||||
try {
|
||||
|
||||
$conn = connect();
|
||||
$tbname = "test_char_types";
|
||||
$spname = "test_char_proc";
|
||||
|
||||
foreach ($dataTypes as $dataType) {
|
||||
$maxtype = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $length) {
|
||||
if ($maxtype !== false) {
|
||||
$type = $dataType;
|
||||
} else {
|
||||
$type = "$dataType($length)";
|
||||
}
|
||||
trace("\nTesting $type:\n");
|
||||
|
||||
//create and populate table
|
||||
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$input0 = str_repeat("1", $length);
|
||||
$input1 = str_repeat("2", $length);
|
||||
insertRow($conn, $tbname, array("c_det" => $input0,
|
||||
"c_rand" => $input1));
|
||||
|
||||
// fetch with PDO::bindParam using a stored procedure
|
||||
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||
createProc($conn, $spname, $procArgs, $procCode);
|
||||
|
||||
// call stored procedure
|
||||
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($outSql);
|
||||
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||
|
||||
if ($inout) {
|
||||
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||
} else {
|
||||
$paramType = $pdoParamType;
|
||||
}
|
||||
|
||||
$len = $length;
|
||||
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||
$det = $rand = 0;
|
||||
}
|
||||
|
||||
$stmt->bindParam(1, $det, $paramType, $len);
|
||||
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($length < 64 && $pdoParamType != PDO::PARAM_STR) {
|
||||
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||
// For boolean values, they should all be bool(true)
|
||||
// because all "string literals" are non-zeroes
|
||||
if (!$det || !$rand) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} else {
|
||||
// $pdoParamType = PDO::PARAM_INT
|
||||
// Expect numeric values
|
||||
if ($det != intval($input0) || $rand != intval($input1)) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
}
|
||||
} elseif ($det !== $input0 || $rand !== $input1) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$message = $e->getMessage();
|
||||
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||
// Expected error IMSSP: "An invalid PHP type was specified
|
||||
// as an output parameter. DateTime objects, NULL values, and
|
||||
// streams cannot be specified as output parameters."
|
||||
$found = strpos($message, $errors['IMSSP']);
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} elseif ($pdoParamType == PDO::PARAM_BOOL) {
|
||||
if (isAEConnected()) {
|
||||
// Expected error 22003: "Numeric value out of range"
|
||||
$found = strpos($message, $errors['22003']);
|
||||
} else {
|
||||
// When not AE enabled, expected to fail to convert
|
||||
// whatever char type to integers
|
||||
$error = "Error converting data type $dataType to int";
|
||||
$found = strpos($message, $error);
|
||||
}
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} else {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
}
|
||||
}
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
testOutputChars(false);
|
||||
testOutputChars(true);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
// drop the temporary table and stored procedure in case
|
||||
// the test failed without dropping them
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
$tbname = "test_char_types";
|
||||
$spname = "test_char_proc";
|
||||
$conn = connect();
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
unset($conn);
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
204
test/functional/pdo_sqlsrv/pdo_ae_output_param_datetimes.phpt
Normal file
204
test/functional/pdo_sqlsrv/pdo_ae_output_param_datetimes.phpt
Normal file
|
@ -0,0 +1,204 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data of datetimes as output parameters
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
--ENV--
|
||||
PHPT_EXEC=true
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
$dataTypes = array("datetime2", "datetimeoffset", "time");
|
||||
$precisions = array(/*0, */1, 2, 4, 7);
|
||||
$inputValuesInit = array("datetime2" => array("0001-01-01 00:00:00", "9999-12-31 23:59:59"),
|
||||
"datetimeoffset" => array("0001-01-01 00:00:00 -14:00", "9999-12-31 23:59:59 +14:00"),
|
||||
"time" => array("00:00:00", "23:59:59"));
|
||||
|
||||
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.", "07006" => "Restricted data type attribute violation");
|
||||
|
||||
$pdoParamTypes = array(
|
||||
PDO::PARAM_BOOL, // 5
|
||||
PDO::PARAM_NULL, // 0
|
||||
PDO::PARAM_INT, // 1
|
||||
PDO::PARAM_STR, // 2
|
||||
PDO::PARAM_LOB // 3
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// compareDate() returns true when the date/time values are basically the same
|
||||
// e.g. 00:00:00.000 is the same as 00:00:00
|
||||
function compareDate($dtout, $dtin, $dataType)
|
||||
{
|
||||
if ($dataType == "datetimeoffset") {
|
||||
$dtarr = explode(' ', $dtin);
|
||||
if (strpos($dtout, $dtarr[0]) !== false && strpos($dtout, $dtarr[1]) !== false && strpos($dtout, $dtarr[2]) !== false) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (strpos($dtout, $dtin) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function printValues($msg, $det, $rand, $inputValues)
|
||||
{
|
||||
echo $msg;
|
||||
echo "input 0: "; var_dump($inputValues[0]);
|
||||
echo "fetched: "; var_dump($det);
|
||||
echo "input 1: "; var_dump($inputValues[1]);
|
||||
echo "fetched: "; var_dump($rand);
|
||||
}
|
||||
|
||||
function testOutputDatetimes($inout)
|
||||
{
|
||||
global $pdoParamTypes, $dataTypes, $precisions, $inputValuesInit, $errors;
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
|
||||
$tbname = "test_datetimes_types";
|
||||
$spname = "test_datetimes_proc";
|
||||
|
||||
foreach ($dataTypes as $dataType) {
|
||||
foreach ($precisions as $precision) {
|
||||
// change the input values depending on the precision
|
||||
$inputValues[0] = $inputValuesInit[$dataType][0];
|
||||
$inputValues[1] = $inputValuesInit[$dataType][1];
|
||||
if ($precision != 0) {
|
||||
if ($dataType == "datetime2") {
|
||||
$inputValues[1] .= "." . str_repeat("9", $precision);
|
||||
} else if ($dataType == "datetimeoffset") {
|
||||
$inputPieces = explode(" ", $inputValues[1]);
|
||||
$inputValues[1] = $inputPieces[0] . " " . $inputPieces[1] . "." . str_repeat("9", $precision) . " " . $inputPieces[2];
|
||||
} else if ($dataType == "time") {
|
||||
$inputValues[0] .= "." . str_repeat("0", $precision);
|
||||
$inputValues[1] .= "." . str_repeat("9", $precision);
|
||||
}
|
||||
}
|
||||
|
||||
$type = "$dataType($precision)";
|
||||
trace("\nTesting $type:\n");
|
||||
|
||||
//create and populate table
|
||||
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
$stmt = insertRow($conn, $tbname, array("c_det" => $inputValues[0], "c_rand" => $inputValues[1]));
|
||||
|
||||
// fetch with PDO::bindParam using a stored procedure
|
||||
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||
createProc($conn, $spname, $procArgs, $procCode);
|
||||
|
||||
// call stored procedure
|
||||
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = 0;
|
||||
$rand = 0;
|
||||
$stmt = $conn->prepare($outSql);
|
||||
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||
|
||||
if ($inout) {
|
||||
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||
} else {
|
||||
$paramType = $pdoParamType;
|
||||
}
|
||||
|
||||
$len = 2048;
|
||||
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||
}
|
||||
|
||||
$stmt->bindParam(1, $det, $paramType, $len);
|
||||
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
// What follows only happens with OUTPUT parameter
|
||||
if ($inout) {
|
||||
echo "Any datetime type as INOUT param should have caused an exception!\n";
|
||||
}
|
||||
if ($pdoParamType == PDO::PARAM_INT) {
|
||||
// Expect an integer, the first part of the date time string
|
||||
$ch = ($dataType == "time")? ':' : '-';
|
||||
$tmp0 = explode($ch, $inputValues[0]);
|
||||
$tmp1 = explode($ch, $inputValues[1]);
|
||||
|
||||
if ($det != intval($tmp0[0]) || $rand != intval($tmp1[0])) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} elseif (!compareDate($det, $inputValues[0], $dataType) ||
|
||||
!compareDate($rand, $inputValues[1], $dataType)) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$message = $e->getMessage();
|
||||
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:\n$message****\n";
|
||||
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||
// Expected error IMSSP: "An invalid PHP type was specified
|
||||
// as an output parameter. DateTime objects, NULL values, and
|
||||
// streams cannot be specified as output parameters."
|
||||
$found = strpos($message, $errors['IMSSP']);
|
||||
} elseif (isAEConnected()) {
|
||||
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||
// Expected error 07006: "Restricted data type attribute violation"
|
||||
// What does this error mean?
|
||||
// The data value returned for a parameter bound as
|
||||
// SQL_PARAM_INPUT_OUTPUT or SQL_PARAM_OUTPUT could not
|
||||
// be converted to the data type identified by the
|
||||
// ValueType argument in SQLBindParameter.
|
||||
$found = strpos($message, $errors['07006']);
|
||||
} else {
|
||||
$error = "Invalid character value for cast specification";
|
||||
$found = strpos($message, $error);
|
||||
}
|
||||
} else {
|
||||
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||
$error = "Operand type clash: int is incompatible with $dataType";
|
||||
} else {
|
||||
$error = "Error converting data type nvarchar to $dataType";
|
||||
}
|
||||
$found = strpos($message, $error);
|
||||
}
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
testOutputDatetimes(false);
|
||||
testOutputDatetimes(true);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
// drop the temporary table and stored procedure in case
|
||||
// the test failed without dropping them
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
$tbname = "test_datetimes_types";
|
||||
$spname = "test_datetimes_proc";
|
||||
$conn = connect();
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
unset($conn);
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
242
test/functional/pdo_sqlsrv/pdo_ae_output_param_decimals.phpt
Normal file
242
test/functional/pdo_sqlsrv/pdo_ae_output_param_decimals.phpt
Normal file
|
@ -0,0 +1,242 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data of decimals/numerics as output parameters
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
--ENV--
|
||||
PHPT_EXEC=true
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
$dataTypes = array("decimal", "numeric");
|
||||
$precisions = array(1 => array(0, 1),
|
||||
4 => array(0, 1, 4),
|
||||
16 => array(0, 1, 4, 16),
|
||||
38 => array(0, 1, 4, 16, 38));
|
||||
$inputValuesInit = array(92233720368547758089223372036854775808, -92233720368547758089223372036854775808);
|
||||
$inputPrecision = 38;
|
||||
|
||||
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.");
|
||||
|
||||
$pdoParamTypes = array(
|
||||
PDO::PARAM_BOOL, // 5
|
||||
PDO::PARAM_NULL, // 0
|
||||
PDO::PARAM_INT, // 1
|
||||
PDO::PARAM_STR, // 2
|
||||
PDO::PARAM_LOB // 3
|
||||
);
|
||||
|
||||
function printValues($msg, $det, $rand, $inputValues)
|
||||
{
|
||||
echo $msg;
|
||||
echo "input 0: "; var_dump($inputValues[0]);
|
||||
echo "fetched: "; var_dump($det);
|
||||
echo "input 1: "; var_dump($inputValues[1]);
|
||||
echo "fetched: "; var_dump($rand);
|
||||
}
|
||||
|
||||
// this function returns true if the floats are more different than expected
|
||||
function compareFloats($actual, $expected)
|
||||
{
|
||||
$epsilon = 0.00001;
|
||||
$diff = abs(($actual - $expected) / $expected);
|
||||
return ($diff > $epsilon);
|
||||
}
|
||||
|
||||
// function compareIntegers() returns false when the fetched values
|
||||
// are different from the expected inputs
|
||||
function compareIntegers($det, $rand, $inputValues, $pdoParamType)
|
||||
{
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// See GitHub issue 707 - Fix this method when the problem is addressed
|
||||
//
|
||||
// Assume $pdoParamType is PDO::PARAM_BOOL or PDO::PARAM_INT
|
||||
if (is_string($det)) {
|
||||
return (!compareFloats(floatval($det), $inputValues[0])
|
||||
&& !compareFloats(floatval($rand), $inputValues[1]));
|
||||
} elseif ($pdoParamType == PDO::PARAM_INT) {
|
||||
$input0 = floor($inputValues[0]); // the positive float
|
||||
$input1 = ceil($inputValues[1]); // the negative float
|
||||
|
||||
return ($det == $input0 && $rand == $input1);
|
||||
} else {
|
||||
// $pdoParamType == PDO::PARAM_BOOL
|
||||
// Expect bool(true) or bool(false) depending on the rounded input values
|
||||
// But with AE enabled (aforementioned GitHub issue), the fetched values
|
||||
// are floats instead, which should be fixed
|
||||
$input0 = floor($inputValues[0]); // the positive float
|
||||
$input1 = ceil($inputValues[1]); // the negative float
|
||||
if (isAEConnected()) {
|
||||
$det = boolval(floor($det));
|
||||
$rand = boolval(ceil($rand));
|
||||
}
|
||||
|
||||
return ($det == boolval($input0) && $rand == boolval($input1));
|
||||
}
|
||||
}
|
||||
|
||||
// function compareDecimals() returns false when the fetched values
|
||||
// are different from the inputs, based on precision, scale
|
||||
function compareDecimals($det, $rand, $inputValues, $pdoParamType, $precision, $scale)
|
||||
{
|
||||
// Assume $pdoParamType is PDO::PARAM_STR
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$inputStr = strval($inputValues[$i]);
|
||||
$fetchedStr = ($i == 0) ? strval(floatval($det)) : strval(floatval($rand));
|
||||
|
||||
if ($precision == $scale) {
|
||||
// compare up to $precision + digits left if radix point ('.') +
|
||||
// 1 digit ('.') + possibly the negative sign
|
||||
$len = $precision + 2 + $i;
|
||||
} elseif ($scale > 0) {
|
||||
// compare up to $precision + 1 digit ('.')
|
||||
// + possibly the negative sign
|
||||
$len = $precision + 1 + $i;
|
||||
} else {
|
||||
// in this case, $scale = 0
|
||||
// compare up to $precision + possibly the negative sign
|
||||
$len = $precision + $i;
|
||||
}
|
||||
|
||||
trace("Comparing $len...");
|
||||
$result = substr_compare($inputStr, $fetchedStr, 0, $len);
|
||||
if ($result != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function testOutputDecimals($inout)
|
||||
{
|
||||
global $pdoParamTypes, $dataTypes, $inputValuesInit, $precisions, $inputPrecision, $errors;
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
|
||||
$tbname = "test_decimals_types";
|
||||
$spname = "test_decimals_proc";
|
||||
|
||||
foreach ($dataTypes as $dataType) {
|
||||
foreach ($precisions as $precision => $scales) {
|
||||
foreach ($scales as $scale) {
|
||||
// construct the input values depending on the precision and scale
|
||||
$precDiff = $inputPrecision - ($precision - $scale);
|
||||
$inputValues = $inputValuesInit;
|
||||
foreach ($inputValues as &$inputValue) {
|
||||
$inputValue = $inputValue / pow(10, $precDiff);
|
||||
}
|
||||
|
||||
$type = "$dataType($precision, $scale)";
|
||||
trace("\nTesting $type:\n");
|
||||
|
||||
//create and populate table
|
||||
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
$stmt = insertRow($conn, $tbname, array("c_det" => $inputValues[0], "c_rand" => $inputValues[1]));
|
||||
|
||||
// fetch with PDO::bindParam using a stored procedure
|
||||
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||
createProc($conn, $spname, $procArgs, $procCode);
|
||||
|
||||
// call stored procedure
|
||||
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = $rand = 0.0;
|
||||
$stmt = $conn->prepare($outSql);
|
||||
|
||||
$len = 2048;
|
||||
// Do not initialize $det or $rand as empty strings
|
||||
// See VSO 2915 for details
|
||||
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||
$det = $rand = 0;
|
||||
}
|
||||
|
||||
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||
if ($inout) {
|
||||
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||
} else {
|
||||
$paramType = $pdoParamType;
|
||||
}
|
||||
|
||||
$stmt->bindParam(1, $det, $paramType, $len);
|
||||
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
|
||||
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||
if (!compareIntegers($det, $rand, $inputValues, $pdoParamType)) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} else {
|
||||
// When $pdoParamType is PDO::PARAM_STR, the accuracies
|
||||
// should have been preserved based on the original
|
||||
// precision and scale, so compare the retrieved values
|
||||
// against the input values with more details
|
||||
if (!compareDecimals($det, $rand, $inputValues, $pdoParamType, $precision, $scale)) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$message = $e->getMessage();
|
||||
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||
// Expected error IMSSP: "An invalid PHP type was specified
|
||||
// as an output parameter. DateTime objects, NULL values, and
|
||||
// streams cannot be specified as output parameters."
|
||||
$found = strpos($message, $errors['IMSSP']);
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} elseif (!isAEConnected() && $precision >= 16 && $pdoParamType == PDO::PARAM_BOOL) {
|
||||
// When not AE enabled, large numbers are expected to
|
||||
// fail when converting to booleans
|
||||
$error = "Error converting data type $dataType to int";
|
||||
$found = strpos($message, $error);
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} else {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
testOutputDecimals(false);
|
||||
testOutputDecimals(true);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
// drop the temporary table and stored procedure in case
|
||||
// the test failed without dropping them
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
$tbname = "test_decimals_types";
|
||||
$spname = "test_decimals_proc";
|
||||
$conn = connect();
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
unset($conn);
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
181
test/functional/pdo_sqlsrv/pdo_ae_output_param_floats.phpt
Normal file
181
test/functional/pdo_sqlsrv/pdo_ae_output_param_floats.phpt
Normal file
|
@ -0,0 +1,181 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data of floats as output parameters
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
--ENV--
|
||||
PHPT_EXEC=true
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.");
|
||||
|
||||
$pdoParamTypes = array(
|
||||
PDO::PARAM_BOOL, // 5
|
||||
PDO::PARAM_NULL, // 0
|
||||
PDO::PARAM_INT, // 1
|
||||
PDO::PARAM_STR, // 2
|
||||
PDO::PARAM_LOB // 3
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// this function returns true if the floats are more different than expected
|
||||
function compareFloats($actual, $expected)
|
||||
{
|
||||
$epsilon = 0.00001;
|
||||
$diff = abs(($actual - $expected) / $expected);
|
||||
return ($diff > $epsilon);
|
||||
}
|
||||
|
||||
function printValues($msg, $det, $rand, $inputValues)
|
||||
{
|
||||
echo $msg;
|
||||
echo "input 0: "; var_dump($inputValues[0]);
|
||||
echo "fetched: "; var_dump($det);
|
||||
echo "input 1: "; var_dump($inputValues[1]);
|
||||
echo "fetched: "; var_dump($rand);
|
||||
}
|
||||
|
||||
function testOutputFloats($fetchNumeric, $inout)
|
||||
{
|
||||
global $pdoParamTypes, $inputValues, $errors;
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
$conn->setAttribute(PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE, $fetchNumeric);
|
||||
|
||||
$tbname = "test_floats_types";
|
||||
$spname = "test_floats_proc";
|
||||
|
||||
$bits = array(1, 12, 24, 36, 53);
|
||||
|
||||
foreach ($bits as $bit) {
|
||||
$type = "float($bit)";
|
||||
trace("\nTesting $type:\n");
|
||||
|
||||
$inputValues = array();
|
||||
// create random input values
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$mantissa = rand(1, 100000000);
|
||||
$decimals = rand(1, 100000000);
|
||||
$floatNum = $mantissa + $decimals / 10000000;
|
||||
if ($i > 0) {
|
||||
// make the second input negative
|
||||
$floatNum *= -1;
|
||||
}
|
||||
array_push($inputValues, $floatNum);
|
||||
}
|
||||
//create and populate table
|
||||
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
insertRow($conn,
|
||||
$tbname,
|
||||
array("c_det" => new BindParamOp(1, $inputValues[0], 'PDO::PARAM_INT'),
|
||||
"c_rand" => new BindParamOp(2, $inputValues[1], 'PDO::PARAM_INT')),
|
||||
"prepareBindParam");
|
||||
|
||||
// fetch with PDO::bindParam using a stored procedure
|
||||
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||
createProc($conn, $spname, $procArgs, $procCode);
|
||||
|
||||
// call stored procedure
|
||||
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
if ($pdoParamType == PDO::PARAM_INT && strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
|
||||
// Bug 2876 in VSO: Linux - when retrieving a float as OUTPUT
|
||||
// or INOUT parameter with PDO::PARAM_INT, the returned values
|
||||
// are always single digits, regardless of the original floats
|
||||
continue;
|
||||
}
|
||||
|
||||
$det = 0.0;
|
||||
$rand = 0.0;
|
||||
$stmt = $conn->prepare($outSql);
|
||||
|
||||
$len = 2048;
|
||||
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||
$det = 0;
|
||||
$rand = 0;
|
||||
}
|
||||
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||
|
||||
if ($inout) {
|
||||
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||
} else {
|
||||
$paramType = $pdoParamType;
|
||||
}
|
||||
$stmt->bindParam(1, $det, $paramType, $len);
|
||||
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
|
||||
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||
// for boolean values, they should all be bool(true)
|
||||
// because all floats are non-zeroes
|
||||
if (!$det || !$rand) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} else {
|
||||
// Compare the retrieved values against the input values
|
||||
// if either of them is very different, print them all
|
||||
if (compareFloats(floatval($det), $inputValues[0]) ||
|
||||
compareFloats(floatval($rand), $inputValues[1])) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$message = $e->getMessage();
|
||||
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
|
||||
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||
// Expected error IMSSP: "An invalid PHP type was specified
|
||||
// as an output parameter. DateTime objects, NULL values, and
|
||||
// streams cannot be specified as output parameters."
|
||||
$found = strpos($message, $errors['IMSSP']);
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} else {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
testOutputFloats(false, false);
|
||||
testOutputFloats(true, false);
|
||||
testOutputFloats(false, true);
|
||||
testOutputFloats(true, true);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
// drop the temporary table and stored procedure in case
|
||||
// the test failed without dropping them
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
$tbname = "test_floats_types";
|
||||
$spname = "test_floats_proc";
|
||||
$conn = connect();
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
unset($conn);
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
193
test/functional/pdo_sqlsrv/pdo_ae_output_param_integers.phpt
Normal file
193
test/functional/pdo_sqlsrv/pdo_ae_output_param_integers.phpt
Normal file
|
@ -0,0 +1,193 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data of integral types as output parameters
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
--ENV--
|
||||
PHPT_EXEC=true
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
$dataTypes = array("bit", "tinyint", "smallint", "int", "bigint");
|
||||
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.", "22003" => "Numeric value out of range", "42000" => "Error converting data type bigint to int");
|
||||
|
||||
$pdoParamTypes = array(
|
||||
PDO::PARAM_BOOL, // 5
|
||||
PDO::PARAM_NULL, // 0
|
||||
PDO::PARAM_INT, // 1
|
||||
PDO::PARAM_STR, // 2
|
||||
PDO::PARAM_LOB // 3
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
function printValues($msg, $det, $rand, $inputValues)
|
||||
{
|
||||
echo $msg;
|
||||
echo "input 0: "; var_dump($inputValues[0]);
|
||||
echo "fetched: "; var_dump($det);
|
||||
echo "input 1: "; var_dump($inputValues[1]);
|
||||
echo "fetched: "; var_dump($rand);
|
||||
}
|
||||
|
||||
function generateInputs($dataType)
|
||||
{
|
||||
// create random input values based on data types
|
||||
// make the second input negative but only for some data types
|
||||
if ($dataType == "bit") {
|
||||
$inputValues = array(0, 1);
|
||||
} elseif ($dataType == "tinyint") {
|
||||
$inputValues = array();
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$randomNum = rand(0, 255);
|
||||
array_push($inputValues, $randomNum);
|
||||
}
|
||||
} else {
|
||||
switch ($dataType) {
|
||||
case "smallint":
|
||||
$max = 32767;
|
||||
break;
|
||||
case "int":
|
||||
$max = 2147483647;
|
||||
break;
|
||||
default:
|
||||
$max = getrandmax();
|
||||
}
|
||||
|
||||
$inputValues = array();
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$randomNum = rand(0, $max);
|
||||
if ($i > 0) {
|
||||
// make the second input negative but only for some data types
|
||||
$randomNum *= -1;
|
||||
}
|
||||
array_push($inputValues, $randomNum);
|
||||
if (traceMode()) {
|
||||
echo "input: "; var_dump($inputValues[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $inputValues;
|
||||
}
|
||||
|
||||
function testOutputInts($inout)
|
||||
{
|
||||
global $pdoParamTypes, $dataTypes, $errors;
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
$tbname = "test_integers_types";
|
||||
$spname = "test_integers_proc";
|
||||
|
||||
foreach ($dataTypes as $dataType) {
|
||||
trace("\nTesting $dataType:\n");
|
||||
|
||||
//create and populate table
|
||||
$colMetaArr = array(new ColumnMeta($dataType, "c_det"), new ColumnMeta($dataType, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$inputValues = generateInputs($dataType);
|
||||
insertRow($conn, $tbname, array("c_det" => $inputValues[0],
|
||||
"c_rand" => $inputValues[1]));
|
||||
|
||||
// fetch with PDO::bindParam using a stored procedure
|
||||
$procArgs = "@c_det $dataType OUTPUT, @c_rand $dataType OUTPUT";
|
||||
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||
createProc($conn, $spname, $procArgs, $procCode);
|
||||
|
||||
// call stored procedure
|
||||
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = 0;
|
||||
$rand = 0;
|
||||
$stmt = $conn->prepare($outSql);
|
||||
|
||||
$len = 2048;
|
||||
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||
}
|
||||
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||
|
||||
if ($inout) {
|
||||
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||
} else {
|
||||
$paramType = $pdoParamType;
|
||||
}
|
||||
$stmt->bindParam(1, $det, $paramType, $len);
|
||||
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
$errMsg = "****$dataType as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($pdoParamType == PDO::PARAM_STR) {
|
||||
if ($det !== strval($inputValues[0]) || $rand !== strval($inputValues[1])) {
|
||||
// comparisons between strings, use '!=='
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} elseif ($pdoParamType == PDO::PARAM_INT || $pdoParamType == PDO::PARAM_BOOL) {
|
||||
// comparisons between integers and booleans, do not use '!=='
|
||||
if ($det != $inputValues[0] || $rand != $inputValues[1]) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} else {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$message = $e->getMessage();
|
||||
$errMsg = "EXCEPTION: ****$dataType as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||
// Expected error IMSSP: "An invalid PHP type was specified
|
||||
// as an output parameter. DateTime objects, NULL values, and
|
||||
// streams cannot be specified as output parameters."
|
||||
$found = strpos($message, $errors['IMSSP']);
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} elseif ($dataType == "bigint" && ($pdoParamType == PDO::PARAM_INT || $pdoParamType == PDO::PARAM_BOOL)) {
|
||||
if (isAEConnected()) {
|
||||
// Expected error 22003: "Numeric value out of range"
|
||||
// This is expected when converting big integer to integer or bool
|
||||
$found = strpos($message, $errors['22003']);
|
||||
} elseif ($pdoParamType == PDO::PARAM_BOOL) {
|
||||
// Expected error 42000: "Error converting data type bigint to int"
|
||||
// This is expected when not AE connected and converting big integer to bool
|
||||
$found = strpos($message, $errors['42000']);
|
||||
}
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
} else {
|
||||
printValues($errMsg, $det, $rand, $inputValues);
|
||||
}
|
||||
}
|
||||
}
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
testOutputInts(false);
|
||||
testOutputInts(true);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
// drop the temporary table and stored procedure in case
|
||||
// the test failed without dropping them
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
$tbname = "test_integers_types";
|
||||
$spname = "test_integers_proc";
|
||||
$conn = connect();
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
unset($conn);
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
172
test/functional/pdo_sqlsrv/pdo_ae_output_param_nchar_size.phpt
Normal file
172
test/functional/pdo_sqlsrv/pdo_ae_output_param_nchar_size.phpt
Normal file
|
@ -0,0 +1,172 @@
|
|||
--TEST--
|
||||
Test for retrieving encrypted data of nchar types of various sizes as output parameters
|
||||
--DESCRIPTION--
|
||||
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||
Note: Because the maximum allowable table row size is 8060 bytes, 7 bytes of which are reserved for internal overhead. In other words, this allows up to two nvarchar() columns with length slightly
|
||||
more than 2000 wide characters. Therefore, the max length in this test is 2010.
|
||||
--ENV--
|
||||
PHPT_EXEC=true
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
$dataTypes = array("nchar", "nvarchar", "nvarchar(max)");
|
||||
$lengths = array(1, 8, 64, 512, 2010);
|
||||
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.", "22003" => "Numeric value out of range");
|
||||
|
||||
$pdoParamTypes = array(
|
||||
PDO::PARAM_BOOL, // 5
|
||||
PDO::PARAM_NULL, // 0
|
||||
PDO::PARAM_INT, // 1
|
||||
PDO::PARAM_STR, // 2
|
||||
PDO::PARAM_LOB // 3
|
||||
);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
function printValues($msg, $det, $rand, $input0, $input1)
|
||||
{
|
||||
echo $msg;
|
||||
echo "input 0: "; var_dump($input0);
|
||||
echo "fetched: "; var_dump($det);
|
||||
echo "input 1: "; var_dump($input1);
|
||||
echo "fetched: "; var_dump($rand);
|
||||
}
|
||||
|
||||
function testOutputNChars($inout)
|
||||
{
|
||||
global $pdoParamTypes, $dataTypes, $lengths, $errors;
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
$tbname = "test_nchar_types";
|
||||
$spname = "test_nchar_proc";
|
||||
|
||||
foreach ($dataTypes as $dataType) {
|
||||
$maxtype = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $length) {
|
||||
if ($maxtype !== false) {
|
||||
$type = $dataType;
|
||||
} else {
|
||||
$type = "$dataType($length)";
|
||||
}
|
||||
trace("\nTesting $type:\n");
|
||||
|
||||
//create and populate table
|
||||
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||
createTable($conn, $tbname, $colMetaArr);
|
||||
$input0 = str_repeat("1", $length);
|
||||
$input1 = str_repeat("2", $length);
|
||||
insertRow($conn, $tbname, array("c_det" => $input0,
|
||||
"c_rand" => $input1));
|
||||
|
||||
// fetch with PDO::bindParam using a stored procedure
|
||||
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||
createProc($conn, $spname, $procArgs, $procCode);
|
||||
|
||||
// call stored procedure
|
||||
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||
foreach ($pdoParamTypes as $pdoParamType) {
|
||||
$det = "";
|
||||
$rand = "";
|
||||
$stmt = $conn->prepare($outSql);
|
||||
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||
|
||||
if ($inout) {
|
||||
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||
} else {
|
||||
$paramType = $pdoParamType;
|
||||
}
|
||||
|
||||
$len = $length;
|
||||
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||
$det = $rand = 0;
|
||||
}
|
||||
|
||||
$stmt->bindParam(1, $det, $paramType, $len);
|
||||
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||
|
||||
try {
|
||||
$stmt->execute();
|
||||
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
// When $length >= 64, a string is returned regardless of $pdoParamType
|
||||
if ($length < 64 && $pdoParamType != PDO::PARAM_STR) {
|
||||
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||
// For boolean values, they should all be bool(true)
|
||||
// because all "string literals" are non-zeroes
|
||||
if (!$det || !$rand) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} else {
|
||||
// $pdoParamType = PDO::PARAM_INT
|
||||
// Expect numeric values
|
||||
if ($det != intval($input0) || $rand != intval($input1)) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
}
|
||||
} elseif ($det !== $input0 || $rand !== $input1) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
$message = $e->getMessage();
|
||||
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||
// Expected error IMSSP: "An invalid PHP type was specified
|
||||
// as an output parameter. DateTime objects, NULL values, and
|
||||
// streams cannot be specified as output parameters."
|
||||
$found = strpos($message, $errors['IMSSP']);
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} elseif ($pdoParamType == PDO::PARAM_BOOL) {
|
||||
if (isAEConnected()) {
|
||||
// Expected error 22003: "Numeric value out of range"
|
||||
$found = strpos($message, $errors['22003']);
|
||||
} else {
|
||||
// When not AE enabled, expected to fail to convert
|
||||
// whatever char type to integers
|
||||
$error = "Error converting data type $dataType to int";
|
||||
$found = strpos($message, $error);
|
||||
}
|
||||
if ($found === false) {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
} else {
|
||||
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||
}
|
||||
}
|
||||
}
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
testOutputNChars(false);
|
||||
testOutputNChars(true);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
// drop the temporary table and stored procedure in case
|
||||
// the test failed without dropping them
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
$tbname = "test_nchar_types";
|
||||
$spname = "test_nchar_proc";
|
||||
$conn = connect();
|
||||
dropProc($conn, $spname);
|
||||
dropTable($conn, $tbname);
|
||||
unset($conn);
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
|
@ -1,160 +1,138 @@
|
|||
--TEST--
|
||||
Test new connection keyword Driver with valid and invalid values
|
||||
--SKIPIF--
|
||||
<?php require('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once('MsSetup.inc');
|
||||
|
||||
try {
|
||||
$conn = new PDO("sqlsrv:server = $server", $uid, $pwd);
|
||||
$msodbcsqlVer = $conn->getAttribute(PDO::ATTR_CLIENT_VERSION)['DriverVer'];
|
||||
$msodbcsqlMaj = explode(".", $msodbcsqlVer)[0];
|
||||
} catch(PDOException $e) {
|
||||
echo "Failed to connect\n";
|
||||
print_r($e->getMessage());
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
$conn = null;
|
||||
|
||||
// start test
|
||||
testValidValues();
|
||||
testInvalidValues();
|
||||
testEncryptedWithODBC();
|
||||
testWrongODBC();
|
||||
echo "Done";
|
||||
// end test
|
||||
|
||||
///////////////////////////
|
||||
function connectVerifyOutput($connectionOptions, $expected = '')
|
||||
{
|
||||
global $server, $uid, $pwd;
|
||||
|
||||
try {
|
||||
$conn = new PDO("sqlsrv:server = $server ; $connectionOptions", $uid, $pwd);
|
||||
} catch(PDOException $e) {
|
||||
if (strpos($e->getMessage(), $expected) === false) {
|
||||
print_r($e->getMessage());
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testValidValues()
|
||||
{
|
||||
global $msodbcsqlMaj;
|
||||
|
||||
$value = "";
|
||||
// The major version number of ODBC 11 can be 11 or 12
|
||||
// Test with {}
|
||||
switch ($msodbcsqlMaj) {
|
||||
case 17:
|
||||
$value = "{ODBC Driver 17 for SQL Server}";
|
||||
break;
|
||||
case 14:
|
||||
case 13:
|
||||
$value = "{ODBC Driver 13 for SQL Server}";
|
||||
break;
|
||||
case 12:
|
||||
case 11:
|
||||
$value = "{ODBC Driver 11 for SQL Server}";
|
||||
break;
|
||||
default:
|
||||
$value = "invalid value $msodbcsqlMaj";
|
||||
}
|
||||
$connectionOptions = "Driver = $value";
|
||||
connectVerifyOutput($connectionOptions);
|
||||
|
||||
// Test without {}
|
||||
switch ($msodbcsqlMaj) {
|
||||
case 17:
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
break;
|
||||
case 14:
|
||||
case 13:
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
break;
|
||||
case 12:
|
||||
case 11:
|
||||
$value = "ODBC Driver 11 for SQL Server";
|
||||
break;
|
||||
default:
|
||||
$value = "invalid value $msodbcsqlMaj";
|
||||
}
|
||||
|
||||
$connectionOptions = "Driver = $value";
|
||||
connectVerifyOutput($connectionOptions);
|
||||
}
|
||||
|
||||
function testInvalidValues()
|
||||
{
|
||||
$values = array("{SQL Server Native Client 11.0}",
|
||||
"SQL Server Native Client 11.0",
|
||||
"ODBC Driver 00 for SQL Server",
|
||||
123,
|
||||
false);
|
||||
|
||||
foreach ($values as $value) {
|
||||
$connectionOptions = "Driver = $value";
|
||||
$expected = "Invalid value $value was specified for Driver option.";
|
||||
connectVerifyOutput($connectionOptions, $expected);
|
||||
}
|
||||
}
|
||||
|
||||
function testEncryptedWithODBC()
|
||||
{
|
||||
global $msodbcsqlMaj, $server, $uid, $pwd;
|
||||
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
$connectionOptions = "Driver = $value; ColumnEncryption = Enabled;";
|
||||
$expected = "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.";
|
||||
|
||||
connectVerifyOutput($connectionOptions, $expected);
|
||||
|
||||
// TODO: the following block will change once ODBC 17 is officially released
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
$connectionOptions = "Driver = $value; ColumnEncryption = Enabled;";
|
||||
|
||||
$success = "Successfully connected with column encryption.";
|
||||
$expected = "The specified ODBC Driver is not found.";
|
||||
$message = $success;
|
||||
try {
|
||||
$conn = new PDO("sqlsrv:server = $server ; $connectionOptions", $uid, $pwd);
|
||||
} catch(PDOException $e) {
|
||||
$message = $e->getMessage();
|
||||
}
|
||||
|
||||
if ($msodbcsqlMaj == 17) {
|
||||
// this indicates that OCBC 17 is the only available driver
|
||||
if (strcmp($message, $success)) {
|
||||
print_r($message);
|
||||
}
|
||||
} else {
|
||||
// OCBC 17 might or might not exist
|
||||
if (strcmp($message, $success)) {
|
||||
if (strpos($message, $expected) === false) {
|
||||
print_r($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testWrongODBC()
|
||||
{
|
||||
global $msodbcsqlMaj;
|
||||
|
||||
// TODO: this will change once ODBC 17 is officially released
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
if ($msodbcsqlMaj == 17 || $msodbcsqlMaj < 13) {
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
}
|
||||
$connectionOptions = "Driver = $value;";
|
||||
$expected = "The specified ODBC Driver is not found.";
|
||||
|
||||
connectVerifyOutput($connectionOptions, $expected);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
--TEST--
|
||||
Test new connection keyword Driver with valid and invalid values
|
||||
--SKIPIF--
|
||||
<?php require('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once('MsSetup.inc');
|
||||
|
||||
try {
|
||||
$conn = new PDO("sqlsrv:server = $server", $uid, $pwd);
|
||||
$msodbcsqlVer = $conn->getAttribute(PDO::ATTR_CLIENT_VERSION)['DriverVer'];
|
||||
$msodbcsqlMaj = explode(".", $msodbcsqlVer)[0];
|
||||
} catch(PDOException $e) {
|
||||
echo "Failed to connect\n";
|
||||
print_r($e->getMessage());
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
$conn = null;
|
||||
|
||||
// start test
|
||||
testValidValues();
|
||||
testInvalidValues();
|
||||
testEncryptedWithODBC();
|
||||
testWrongODBC();
|
||||
echo "Done";
|
||||
// end test
|
||||
|
||||
///////////////////////////
|
||||
function connectVerifyOutput($connectionOptions, $expected = '')
|
||||
{
|
||||
global $server, $uid, $pwd;
|
||||
|
||||
try {
|
||||
$conn = new PDO("sqlsrv:server = $server ; $connectionOptions", $uid, $pwd);
|
||||
} catch(PDOException $e) {
|
||||
if (strpos($e->getMessage(), $expected) === false) {
|
||||
print_r($e->getMessage());
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testValidValues()
|
||||
{
|
||||
global $msodbcsqlMaj;
|
||||
|
||||
$value = "";
|
||||
// The major version number of ODBC 11 can be 11 or 12
|
||||
// Test with {}
|
||||
switch ($msodbcsqlMaj) {
|
||||
case 17:
|
||||
$value = "{ODBC Driver 17 for SQL Server}";
|
||||
break;
|
||||
case 14:
|
||||
case 13:
|
||||
$value = "{ODBC Driver 13 for SQL Server}";
|
||||
break;
|
||||
case 12:
|
||||
case 11:
|
||||
$value = "{ODBC Driver 11 for SQL Server}";
|
||||
break;
|
||||
default:
|
||||
$value = "invalid value $msodbcsqlMaj";
|
||||
}
|
||||
$connectionOptions = "Driver = $value";
|
||||
connectVerifyOutput($connectionOptions);
|
||||
|
||||
// Test without {}
|
||||
switch ($msodbcsqlMaj) {
|
||||
case 17:
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
break;
|
||||
case 14:
|
||||
case 13:
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
break;
|
||||
case 12:
|
||||
case 11:
|
||||
$value = "ODBC Driver 11 for SQL Server";
|
||||
break;
|
||||
default:
|
||||
$value = "invalid value $msodbcsqlMaj";
|
||||
}
|
||||
|
||||
$connectionOptions = "Driver = $value";
|
||||
connectVerifyOutput($connectionOptions);
|
||||
}
|
||||
|
||||
function testInvalidValues()
|
||||
{
|
||||
$values = array("{SQL Server Native Client 11.0}",
|
||||
"SQL Server Native Client 11.0",
|
||||
"ODBC Driver 00 for SQL Server",
|
||||
123,
|
||||
false);
|
||||
|
||||
foreach ($values as $value) {
|
||||
$connectionOptions = "Driver = $value";
|
||||
$expected = "Invalid value $value was specified for Driver option.";
|
||||
connectVerifyOutput($connectionOptions, $expected);
|
||||
}
|
||||
}
|
||||
|
||||
function testEncryptedWithODBC()
|
||||
{
|
||||
global $msodbcsqlMaj, $server, $uid, $pwd;
|
||||
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
$connectionOptions = "Driver = $value; ColumnEncryption = Enabled;";
|
||||
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
||||
$expected = "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.";
|
||||
} else {
|
||||
$expected = "An invalid keyword 'ColumnEncryption' was specified in the DSN string.";
|
||||
}
|
||||
|
||||
connectVerifyOutput($connectionOptions, $expected);
|
||||
}
|
||||
|
||||
function testWrongODBC()
|
||||
{
|
||||
global $msodbcsqlMaj;
|
||||
|
||||
// TODO: this will change once ODBC 17 is officially released
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
if ($msodbcsqlMaj == 17 || $msodbcsqlMaj < 13) {
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
}
|
||||
$connectionOptions = "Driver = $value;";
|
||||
$expected = "The specified ODBC Driver is not found.";
|
||||
|
||||
connectVerifyOutput($connectionOptions, $expected);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
|
@ -1,7 +1,7 @@
|
|||
--TEST--
|
||||
Test new connection keyword ColumnEncryption
|
||||
--SKIPIF--
|
||||
<?php require('skipif.inc'); ?>
|
||||
<?php require('skipif_unix.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsSetup.inc");
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
--TEST--
|
||||
Fetch data from a prepopulated test table given a custom keystore provider
|
||||
--SKIPIF--
|
||||
<?php require('skipif_not_ksp.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
try
|
||||
{
|
||||
$conn = connect();
|
||||
echo "Connected successfully with ColumnEncryption enabled and KSP specified.\n";
|
||||
}
|
||||
catch( PDOException $e )
|
||||
{
|
||||
echo "Failed to connect.\n";
|
||||
print_r( $e->getMessage() );
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
$tbname = KSP_TEST_TABLE;
|
||||
$tsql = "SELECT * FROM $tbname";
|
||||
$stmt = $conn->query($tsql);
|
||||
while ($row = $stmt->fetch(PDO::FETCH_NUM))
|
||||
{
|
||||
echo "c1=" . $row[0] . "\tc2=" . $row[1] . "\tc3=" . $row[2] . "\tc4=" . $row[3] . "\n";
|
||||
}
|
||||
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Connected successfully with ColumnEncryption enabled and KSP specified.
|
||||
c1=1 c2=Sample data 0 for column 2 c3=abc c4=2017-08-10
|
||||
c1=12 c2=Sample data 1 for column 2 c3=bcd c4=2017-08-11
|
||||
c1=23 c2=Sample data 2 for column 2 c3=cde c4=2017-08-12
|
||||
c1=34 c2=Sample data 3 for column 2 c3=def c4=2017-08-13
|
||||
c1=45 c2=Sample data 4 for column 2 c3=efg c4=2017-08-14
|
||||
c1=56 c2=Sample data 5 for column 2 c3=fgh c4=2017-08-15
|
||||
c1=67 c2=Sample data 6 for column 2 c3=ghi c4=2017-08-16
|
||||
c1=78 c2=Sample data 7 for column 2 c3=hij c4=2017-08-17
|
||||
c1=89 c2=Sample data 8 for column 2 c3=ijk c4=2017-08-18
|
||||
c1=100 c2=Sample data 9 for column 2 c3=jkl c4=2017-08-19
|
||||
Done
|
|
@ -1,51 +0,0 @@
|
|||
--TEST--
|
||||
Fetch encrypted data from a prepopulated test table given a custom keystore provider
|
||||
--SKIPIF--
|
||||
<?php require('skipif_not_ksp.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
try
|
||||
{
|
||||
$conn = connect();
|
||||
echo "Connected successfully with ColumnEncryption disabled and KSP specified.\n";
|
||||
}
|
||||
catch( PDOException $e )
|
||||
{
|
||||
echo "Failed to connect.\n";
|
||||
print_r( $e->getMessage() );
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
$tbname = KSP_TEST_TABLE;
|
||||
$tsql = "SELECT * FROM $tbname";
|
||||
$stmt = $conn->query($tsql);
|
||||
while ($row = $stmt->fetch(PDO::FETCH_NUM))
|
||||
{
|
||||
echo "c1=" . $row[0];
|
||||
echo "\tc2=" . bin2hex($row[1]);
|
||||
echo "\tc3=" . bin2hex($row[2]);
|
||||
echo "\tc4=" . bin2hex($row[3]);
|
||||
echo "\n" ;
|
||||
}
|
||||
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
|
||||
echo "Done\n";
|
||||
|
||||
?>
|
||||
--EXPECTREGEX--
|
||||
Connected successfully with ColumnEncryption disabled and KSP specified.
|
||||
c1=1 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=12 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=23 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=34 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=45 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=56 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=67 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=78 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=89 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=100 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
Done
|
|
@ -1,102 +0,0 @@
|
|||
--TEST--
|
||||
Connect using a custom keystore provider with some required inputs missing
|
||||
--SKIPIF--
|
||||
<?php require('skipif_not_ksp.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require("MsSetup.inc");
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
function kspConnect( $connectionInfo )
|
||||
{
|
||||
global $server, $uid, $pwd;
|
||||
|
||||
try
|
||||
{
|
||||
$conn = new PDO( "sqlsrv:server = $server ; $connectionInfo", $uid, $pwd );
|
||||
echo "Connected successfully with ColumnEncryption enabled and KSP specified.\n";
|
||||
}
|
||||
catch( PDOException $e )
|
||||
{
|
||||
echo "Failed to connect.\n";
|
||||
print_r( $e->getMessage() );
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$ksp_path = getKSPpath();
|
||||
$ksp_name = KSP_NAME;
|
||||
$encrypt_key = ENCRYPT_KEY;
|
||||
|
||||
echo("Connecting... with column encryption\n");
|
||||
$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled; ";
|
||||
kspConnect( $connectionInfo );
|
||||
|
||||
echo("\nConnecting... with an invalid input to CEKeystoreProvider\n");
|
||||
$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled; ";
|
||||
$connectionInfo .= "CEKeystoreName = 1; ";
|
||||
$connectionInfo .= "CEKeystoreProvider = $ksp_path; ";
|
||||
$connectionInfo .= "CEKeystoreEncryptKey = $encrypt_key; ";
|
||||
kspConnect( $connectionInfo );
|
||||
|
||||
echo("\nConnecting... with an empty path\n");
|
||||
$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled; ";
|
||||
$connectionInfo .= "CEKeystoreName = $ksp_name; ";
|
||||
$connectionInfo .= "CEKeystoreProvider = ; ";
|
||||
$connectionInfo .= "CEKeystoreEncryptKey = $encrypt_key; ";
|
||||
kspConnect( $connectionInfo );
|
||||
|
||||
echo("\nConnecting... without a path\n");
|
||||
$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled; ";
|
||||
$connectionInfo .= "CEKeystoreName = $ksp_name; ";
|
||||
$connectionInfo .= "CEKeystoreEncryptKey = $encrypt_key;";
|
||||
kspConnect( $connectionInfo );
|
||||
|
||||
echo("\nConnecting... without a name\n");
|
||||
$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled; ";
|
||||
$connectionInfo .= "CEKeystoreProvider = $ksp_path; ";
|
||||
$connectionInfo .= "CEKeystoreEncryptKey = $encrypt_key; ";
|
||||
kspConnect( $connectionInfo );
|
||||
|
||||
echo("\nConnecting... without a key\n");
|
||||
$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled; ";
|
||||
$connectionInfo .= "CEKeystoreProvider = $ksp_path; ";
|
||||
$connectionInfo .= "CEKeystoreName = $ksp_name; ";
|
||||
kspConnect( $connectionInfo );
|
||||
|
||||
echo("\nConnecting... with all required inputs\n");
|
||||
$connectionInfo = "Database = $databaseName; ColumnEncryption = Enabled; ";
|
||||
$connectionInfo .= "CEKeystoreProvider = $ksp_path; ";
|
||||
$connectionInfo .= "CEKeystoreName = $ksp_name; ";
|
||||
$connectionInfo .= "CEKeystoreEncryptKey = $encrypt_key; ";
|
||||
kspConnect( $connectionInfo );
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTREGEX--
|
||||
Connecting\.\.\. with column encryption
|
||||
Connected successfully with ColumnEncryption enabled and KSP specified\.
|
||||
|
||||
Connecting\.\.\. with an invalid input to CEKeystoreProvider
|
||||
Failed to connect.
|
||||
SQLSTATE\[HY024\]: \[Microsoft\]\[ODBC Driver 1[1-9] for SQL Server\]Invalid attribute value
|
||||
|
||||
Connecting\.\.\. with an empty path
|
||||
Failed to connect.
|
||||
SQLSTATE\[IMSSP\]: Invalid value for loading a custom keystore provider\.
|
||||
|
||||
Connecting\.\.\. without a path
|
||||
Failed to connect.
|
||||
SQLSTATE\[IMSSP\]: The path to the custom keystore provider is missing\.
|
||||
|
||||
Connecting\.\.\. without a name
|
||||
Failed to connect.
|
||||
SQLSTATE\[IMSSP\]: The name of the custom keystore provider is missing\.
|
||||
|
||||
Connecting\.\.\. without a key
|
||||
Failed to connect.
|
||||
SQLSTATE\[IMSSP\]: The encryption key for the custom keystore provider is missing\.
|
||||
|
||||
Connecting\.\.\. with all required inputs
|
||||
Connected successfully with ColumnEncryption enabled and KSP specified\.
|
||||
Done
|
|
@ -1,16 +1,21 @@
|
|||
<?php
|
||||
if (!extension_loaded("pdo") || !extension_loaded('pdo_sqlsrv')) {
|
||||
die("PDO driver cannot be loaded; skipping test.\n");
|
||||
}
|
||||
|
||||
require_once("MsSetup.inc");
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
|
||||
$dsn = getDSN($server, null);
|
||||
$conn = new PDO($dsn, $uid, $pwd);
|
||||
if (! $conn) {
|
||||
echo("Error: could not connect during SKIPIF!");
|
||||
} elseif (isColEncrypted() && !isAEQualified($conn)) {
|
||||
die("skip - AE feature not supported in the current environment.");
|
||||
}
|
||||
<?php
|
||||
if (!extension_loaded("pdo") || !extension_loaded('pdo_sqlsrv')) {
|
||||
die("PDO driver cannot be loaded; skipping test.\n");
|
||||
}
|
||||
|
||||
require_once("MsSetup.inc");
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
$dsn = getDSN($server, null);
|
||||
$conn = new PDO($dsn, $uid, $pwd);
|
||||
if (! $conn) {
|
||||
echo("Error: could not connect during SKIPIF!");
|
||||
} elseif (isColEncrypted()) {
|
||||
if (!(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')) {
|
||||
die( "Skip, AE test on windows only." );
|
||||
}
|
||||
|
||||
if (!isAEQualified($conn)) {
|
||||
die("skip - AE feature not supported in the current environment.");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
if (! extension_loaded( 'pdo' ) || ! extension_loaded( 'pdo_sqlsrv' ))
|
||||
die( "PDO driver cannot be loaded; skipping test.\n" );
|
||||
|
||||
require_once( "MsSetup.inc" );
|
||||
|
||||
if ($keystore != 'ksp')
|
||||
die ( 'skip - this test requires a custom keystore provider.' );
|
||||
|
||||
require_once( "MsCommon.inc" );
|
||||
|
||||
$conn = new PDO( "sqlsrv:server = $server;", $uid, $pwd );
|
||||
if( ! $conn )
|
||||
{
|
||||
echo( "Error: could not connect during SKIPIF!" );
|
||||
}
|
||||
else if(! IsAEQualified($conn))
|
||||
{
|
||||
die( "skip - AE feature not supported in the current environment." );
|
||||
}
|
||||
?>
|
|
@ -1,6 +1,3 @@
|
|||
USE $(dbname)
|
||||
GO
|
||||
|
||||
/* DROP Column Encryption Key first, Column Master Key cannot be dropped until no encryption depends on it */
|
||||
IF EXISTS (SELECT * FROM sys.column_encryption_keys WHERE [name] LIKE '%AEColumnKey%')
|
||||
|
||||
|
|
|
@ -45,13 +45,14 @@ def executeBulkCopy(conn_options, dbname, tblname, datafile):
|
|||
inst_command = redirect_string.format(dbname, tblname, datafile) + conn_options
|
||||
executeCommmand(inst_command)
|
||||
|
||||
def setupAE( conn_options, dbname, azure ):
|
||||
if (platform.system() == 'Windows' and azure.lower() == 'no'):
|
||||
def setupAE(conn_options, dbname):
|
||||
if (platform.system() == 'Windows'):
|
||||
# import self signed certificate
|
||||
inst_command = "certutil -user -p '' -importPFX My PHPcert.pfx NoRoot"
|
||||
executeCommmand(inst_command)
|
||||
# create Column Master Key and Column Encryption Key
|
||||
executeSQLscript('ae_keys.sql', conn_options, dbname)
|
||||
script_command = 'sqlcmd ' + conn_options + ' -i ae_keys.sql -d ' + dbname
|
||||
executeCommmand(script_command)
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
|
@ -84,7 +85,7 @@ if __name__ == '__main__':
|
|||
# populate these tables
|
||||
populateTables(conn_options, args.DBNAME)
|
||||
# setup AE (certificate, column master key and column encryption key)
|
||||
setupAE(conn_options, args.DBNAME, args.AZURE)
|
||||
setupAE(conn_options, args.DBNAME)
|
||||
|
||||
os.chdir(current_working_dir)
|
||||
|
||||
|
|
|
@ -22,10 +22,6 @@ const INSERT_PREPARE = 2;
|
|||
const INSERT_QUERY_PARAMS = 3;
|
||||
const INSERT_PREPARE_PARAMS = 4;
|
||||
|
||||
const KSP_NAME = 'MyCustomKSPName';
|
||||
const ENCRYPT_KEY = 'LPKCWVD07N3RG98J0MBLG4H2';
|
||||
const KSP_TEST_TABLE = 'CustomKSPTestTable';
|
||||
|
||||
/**
|
||||
* class for encapsulating column metadata needed for creating a table
|
||||
*/
|
||||
|
@ -161,13 +157,16 @@ class BindParamOption
|
|||
$type_size = explode("(", $this->sqlType);
|
||||
$type = $type_size[0];
|
||||
if (count($type_size) > 1) {
|
||||
$size = $type_size[1];
|
||||
$size = rtrim($type_size[1], ")");
|
||||
$prec_scal = explode(",", $size);
|
||||
if (count($prec_scal) > 1) {
|
||||
$prec = $prec_scal[0];
|
||||
$scal = rtrim($prec_scal[1], ")");
|
||||
$scal = $prec_scal[1];
|
||||
$size = null;
|
||||
}
|
||||
if (strpos($size, "max") !== false) {
|
||||
$size = trim($size, "'");
|
||||
}
|
||||
}
|
||||
// get the sqlType constant
|
||||
try {
|
||||
|
@ -214,29 +213,6 @@ function getCekName()
|
|||
return $cekName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the path to the KSP dll/so file
|
||||
*/
|
||||
function getKSPpath()
|
||||
{
|
||||
$name = 'myKSP';
|
||||
|
||||
$dir_name = realpath(dirname(__FILE__));
|
||||
$ksp = $dir_name . DIRECTORY_SEPARATOR . $name;
|
||||
if (strtoupper(substr(php_uname('s'), 0, 3)) == 'WIN') {
|
||||
$arch = 'x64';
|
||||
if (PHP_INT_SIZE == 4) {
|
||||
// running 32 bit
|
||||
$arch = '';
|
||||
}
|
||||
$ksp .= $arch . '.dll';
|
||||
} else {
|
||||
$ksp .= '.so';
|
||||
}
|
||||
|
||||
return $ksp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string default column name when a name is not provided in the ColumnMeta class
|
||||
*/
|
||||
|
@ -353,6 +329,12 @@ function isQualified($conn)
|
|||
if (explode(".", $msodbcsql_ver)[0] < 17) {
|
||||
return false;
|
||||
}
|
||||
global $daasMode;
|
||||
if ($daasMode) {
|
||||
// running against Azure
|
||||
return true;
|
||||
}
|
||||
// if not Azure, check the server version
|
||||
$server_ver = sqlsrv_server_info($conn)['SQLServerVersion'];
|
||||
if (explode('.', $server_ver)[0] < 13) {
|
||||
return false;
|
||||
|
@ -377,13 +359,6 @@ function connect($options = array(), $disableCE = false)
|
|||
if (isColEncrypted()) {
|
||||
$connectionOptions = array_merge($connectionOptions, array("ColumnEncryption" => "Enabled"));
|
||||
}
|
||||
if ($keystore == "ksp") {
|
||||
$ksp_path = getKSPPath();
|
||||
$ksp_options = array("CEKeystoreProvider"=>$ksp_path,
|
||||
"CEKeystoreName"=>KSP_NAME,
|
||||
"CEKeystoreEncryptKey"=>ENCRYPT_KEY);
|
||||
$connectionOptions = array_merge($connectionOptions, $ksp_options);
|
||||
}
|
||||
}
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
if (!extension_loaded("sqlsrv"))
|
||||
die("skip extension not loaded");
|
||||
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
if ($keystore != AE\KEYSTORE_KSP) {
|
||||
die('skip - this test requires a custom keystore provider.');
|
||||
}
|
||||
|
||||
$conn = AE\connect();
|
||||
if (! $conn) {
|
||||
echo("Error: could not connect during SKIPIF!");
|
||||
} elseif (AE\isColEncrypted() && !AE\isQualified($conn)) {
|
||||
die("skip - AE feature not supported in the current environment.");
|
||||
}
|
||||
?>
|
|
@ -1,15 +1,21 @@
|
|||
<?php
|
||||
|
||||
if (! extension_loaded("sqlsrv")) {
|
||||
die("skip extension not loaded");
|
||||
}
|
||||
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
$conn = AE\connect();
|
||||
if (! $conn) {
|
||||
echo("Error: could not connect during SKIPIF!");
|
||||
} elseif (AE\isColEncrypted() && !AE\isQualified($conn)) {
|
||||
die("skip - AE feature not supported in the current environment.");
|
||||
}
|
||||
<?php
|
||||
|
||||
if (! extension_loaded("sqlsrv")) {
|
||||
die("skip extension not loaded");
|
||||
}
|
||||
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
$conn = AE\connect();
|
||||
if (! $conn) {
|
||||
echo("Error: could not connect during SKIPIF!");
|
||||
} elseif (AE\isColEncrypted()) {
|
||||
if (!isWindows()) {
|
||||
die( "Skip, AE test on windows only." );
|
||||
}
|
||||
|
||||
if (!AE\isQualified($conn)) {
|
||||
die("skip - AE feature not supported in the current environment.");
|
||||
}
|
||||
}
|
||||
?>
|
271
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_binary_size.phpt
Normal file
271
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_binary_size.phpt
Normal file
|
@ -0,0 +1,271 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data into binary types columns with different sizes
|
||||
--DESCRIPTION--
|
||||
Test implicit conversions between different binary types of different sizes
|
||||
With Always Encrypted, implicit conversion works if:
|
||||
1. From input of SQLSRV_SQLTYPE_BINARY(n) to a larger binary(m) column where n <= m
|
||||
2. From input of SQLSRV_SQLTYPE_BINARY(n) to a larger varbinary(m) column where n <= m (m can be max)
|
||||
3. From input of SQLSRV_SQLTYPE_VARBINARY(n) to a larger binary(m) column where n <= m
|
||||
4. From input of SQLSRV_SQLTYPE_VARBINARY(n) to a larger varbinary(m) column where n <= m (m can be max)
|
||||
Without AlwaysEncrypted, implicit conversion between different binary types and sizes works
|
||||
--SKIPIF--
|
||||
<?php require('skipif_versions_old.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
$dataTypes = array("binary", "varbinary", "varbinary(max)");
|
||||
$lengths = array(1, 8, 64, 512, 4000);
|
||||
$sqlTypes = array("SQLSRV_SQLTYPE_BINARY", "SQLSRV_SQLTYPE_VARBINARY", "SQLSRV_SQLTYPE_VARBINARY('max')");
|
||||
$sqltypeLengths = $lengths;
|
||||
$inputValues = array("d", "f");
|
||||
|
||||
$conn = AE\connect();
|
||||
foreach($dataTypes as $dataType) {
|
||||
$maxcol = strpos($dataType, "(max)");
|
||||
foreach ($lengths as $m) {
|
||||
if ($maxcol !== false) {
|
||||
$typeFull = $dataType;
|
||||
} else {
|
||||
$typeFull = "$dataType($m)";
|
||||
}
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing binary(m) or varbinary(m) columns
|
||||
$tbname = "test_" . str_replace(array('(', ')'), '', $dataType) . $m;
|
||||
$colMetaArr = array(new AE\ColumnMeta($typeFull, "c_det"), new AE\ColumnMeta($typeFull, "c_rand", null, false));
|
||||
AE\createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying SQLSRV_SQLTYPE_BINARY(n) or SQLSRV_SQLTYPE_VARBINARY(n)
|
||||
// with AE, should be successful as long as the SQLSRV_SQLTYPE length (n) is smaller than the column length (m)
|
||||
foreach($sqlTypes as $sqlType) {
|
||||
$maxsqltype = strpos($sqlType, "max");
|
||||
foreach($sqltypeLengths as $n) {
|
||||
if ($maxsqltype !== false) {
|
||||
$sqltypeFull = $sqlType;
|
||||
} else {
|
||||
$sqltypeFull = "$sqlType($n)";
|
||||
}
|
||||
|
||||
//insert a row
|
||||
$inputs = array(new AE\BindParamOption($inputValues[0], null, "SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY)", $sqltypeFull),
|
||||
new AE\BindParamOption($inputValues[1], null, "SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY)", $sqltypeFull));
|
||||
$r;
|
||||
$stmt = AE\insertRow($conn, $tbname, array("c_det" => $inputs[0], "c_rand" => $inputs[1]), $r, AE\INSERT_PREPARE_PARAMS);
|
||||
|
||||
// check the case when SQLSRV_SQLTYPE length (n) is greater than the column length (m)
|
||||
// with AE: should not work
|
||||
// without AE: should work
|
||||
if (($n > $m || $maxsqltype) && !$maxcol) {
|
||||
if (AE\isDataEncrypted()) {
|
||||
if ($r !== false) {
|
||||
echo "AE: Conversion from $sqltypeFull to $typeFull should not be supported\n";
|
||||
} else {
|
||||
if (sqlsrv_errors()[0]['SQLSTATE'] != "22018") {
|
||||
echo "AE: Conversion from $sqltypeFull to $typeFull expects an operand type clash error, actual error is incorrect\n";
|
||||
var_dump(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull should be supported\n";
|
||||
}
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (trim($row['c_det']) != $inputValues[0] || trim($row['c_rand']) != $inputValues[1]) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
// check the case when SQLSRV_SQLTYPE length (n) is less than or equal to the column length (m)
|
||||
// should work with AE or non AE
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (trim($row['c_det']) == $inputValues[0] || trim($row['c_rand']) == $inputValues[1]) {
|
||||
echo "****Conversion from $sqltypeFull to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $sqltypeFull to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
sqlsrv_free_stmt($stmt);
|
||||
sqlsrv_query($conn, "TRUNCATE TABLE $tbname");
|
||||
}
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
sqlsrv_close($conn);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing binary(1):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to binary(1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to binary(1) is supported****
|
||||
|
||||
Testing binary(8):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to binary(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to binary(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to binary(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to binary(8) is supported****
|
||||
|
||||
Testing binary(64):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to binary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to binary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to binary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to binary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to binary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to binary(64) is supported****
|
||||
|
||||
Testing binary(512):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to binary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to binary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to binary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(512) to binary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to binary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to binary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to binary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(512) to binary(512) is supported****
|
||||
|
||||
Testing binary(4000):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to binary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to binary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to binary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(512) to binary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(4000) to binary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to binary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to binary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to binary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(512) to binary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(4000) to binary(4000) is supported****
|
||||
|
||||
Testing varbinary(1):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(1) is supported****
|
||||
|
||||
Testing varbinary(8):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to varbinary(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to varbinary(8) is supported****
|
||||
|
||||
Testing varbinary(64):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to varbinary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to varbinary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to varbinary(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to varbinary(64) is supported****
|
||||
|
||||
Testing varbinary(512):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to varbinary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to varbinary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(512) to varbinary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to varbinary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to varbinary(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(512) to varbinary(512) is supported****
|
||||
|
||||
Testing varbinary(4000):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to varbinary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to varbinary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(512) to varbinary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(4000) to varbinary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to varbinary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to varbinary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(512) to varbinary(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(4000) to varbinary(4000) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
|
||||
Testing varbinary(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(1) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(8) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(64) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(512) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY(4000) to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARBINARY('max') to varbinary(max) is supported****
|
336
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_char_size.phpt
Normal file
336
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_char_size.phpt
Normal file
|
@ -0,0 +1,336 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data of char types with different sizes
|
||||
--DESCRIPTION--
|
||||
Test implicit conversions between different char types of different sizes
|
||||
With Always Encrypted, implicit conversion works if:
|
||||
1. From input of SQLSRV_SQLTYPE_CHAR(n) to a larger char(m) column where n <= m
|
||||
2. From input of SQLSRV_SQLTYPE_CHAR(n) to a larger varchar(m) column where n <= m (m can be max)
|
||||
3. From input of SQLSRV_SQLTYPE_VARCHAR(n) to a larger char(m) column where n <= m
|
||||
4. From input of SQLSRV_SQLTYPE_VARCHAR(n) to a larger varchar(m) column where n <= m (m can be max)
|
||||
Without AlwaysEncrypted, implicit conversion between different binary types and sizes works
|
||||
--SKIPIF--
|
||||
<?php require('skipif_versions_old.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
$dataTypes = array("char", "varchar", "varchar(max)");
|
||||
$lengths = array(1, 8, 64, 512, 4096, 8000);
|
||||
$sqlTypes = array("SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_VARCHAR", "SQLSRV_SQLTYPE_VARCHAR('max')");
|
||||
$sqltypeLengths = $lengths;
|
||||
$inputValue = "d";
|
||||
|
||||
$conn = AE\connect();
|
||||
foreach($dataTypes as $dataType) {
|
||||
$maxcol = strpos($dataType, "(max)");
|
||||
foreach($lengths as $m) {
|
||||
if ($maxcol !== false) {
|
||||
$typeFull = $dataType;
|
||||
} else {
|
||||
$typeFull = "$dataType($m)";
|
||||
}
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing char(m) or varchar(m) columns
|
||||
// only one column is created because a row has a limitation of 8060 bytes
|
||||
// for lengths 4096 and 8000, cannot create 2 columns as it will exceed the maximum row sizes
|
||||
// for AE, only testing deterministic here, randomized is tested in the nchar test
|
||||
$tbname = "test_" . str_replace(array('(', ')'), '', $dataType) . $m;
|
||||
$colMetaArr = array(new AE\ColumnMeta($typeFull, "c1"));
|
||||
AE\createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying SQLSRV_SQLTYPE_CHAR(n) or SQLSRV_SQLTYPE_VARCHAR(n)
|
||||
// with AE, should be successful as long as the SQLSRV_SQLTYPE length (n) is smaller than the column length (m)
|
||||
foreach($sqlTypes as $sqlType) {
|
||||
$maxsqltype = strpos($sqlType, "max");
|
||||
foreach($sqltypeLengths as $n) {
|
||||
if ($maxsqltype !== false) {
|
||||
$sqltypeFull = $sqlType;
|
||||
} else {
|
||||
$sqltypeFull = "$sqlType($n)";
|
||||
}
|
||||
|
||||
//insert a row
|
||||
$input = new AE\BindParamOption($inputValue, null, null, $sqltypeFull);
|
||||
$r;
|
||||
$stmt = AE\insertRow($conn, $tbname, array("c1" => $input), $r, AE\INSERT_PREPARE_PARAMS);
|
||||
|
||||
// check the case when SQLSRV_SQLTYPE length (n) is greater than the column length (m)
|
||||
// with AE: should not work
|
||||
// without AE: should work
|
||||
if (($n > $m || $maxsqltype) && !$maxcol) {
|
||||
if (AE\isDataEncrypted()) {
|
||||
if ($r !== false) {
|
||||
echo "AE: Conversion from $sqltypeFull to $typeFull should not be supported\n";
|
||||
} else {
|
||||
if (sqlsrv_errors()[0]['SQLSTATE'] != "22018") {
|
||||
echo "AE: Conversion from $sqltypeFull to $typeFull expects an operand type clash error, actual error is incorrect\n";
|
||||
var_dump(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull should be supported\n";
|
||||
}
|
||||
$sql = "SELECT c1 FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (trim($row['c1']) != $inputValue) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
// check the case when SQLSRV_SQLTYPE length (n) is less than or equal to the column length (m)
|
||||
// should work with AE or non AE
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c1 FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (trim($row['c1']) == $inputValue) {
|
||||
echo "****Conversion from $sqltypeFull to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $sqltypeFull to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
sqlsrv_free_stmt($stmt);
|
||||
sqlsrv_query($conn, "TRUNCATE TABLE $tbname");
|
||||
}
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
sqlsrv_close($conn);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing char(1):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to char(1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to char(1) is supported****
|
||||
|
||||
Testing char(8):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to char(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to char(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to char(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to char(8) is supported****
|
||||
|
||||
Testing char(64):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to char(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to char(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to char(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to char(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to char(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to char(64) is supported****
|
||||
|
||||
Testing char(512):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to char(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to char(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to char(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to char(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to char(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to char(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to char(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to char(512) is supported****
|
||||
|
||||
Testing char(4096):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to char(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to char(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to char(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to char(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to char(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to char(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to char(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to char(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to char(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to char(4096) is supported****
|
||||
|
||||
Testing char(8000):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8000) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to char(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8000) to char(8000) is supported****
|
||||
|
||||
Testing varchar(1):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(1) is supported****
|
||||
|
||||
Testing varchar(8):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(8) is supported****
|
||||
|
||||
Testing varchar(64):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(64) is supported****
|
||||
|
||||
Testing varchar(512):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to varchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to varchar(512) is supported****
|
||||
|
||||
Testing varchar(4096):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to varchar(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to varchar(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to varchar(4096) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to varchar(4096) is supported****
|
||||
|
||||
Testing varchar(8000):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8000) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to varchar(8000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8000) to varchar(8000) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
|
||||
Testing varchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_CHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(1) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(64) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(512) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(4096) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR(8000) to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_VARCHAR('max') to varchar(max) is supported****
|
|
@ -0,0 +1,181 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data of datetime2, datetimeoffset and time datatypes with different precisions
|
||||
--DESCRIPTION--
|
||||
Test implicit conversions between different precisions
|
||||
With Always Encrypted, implicit conversion works if:
|
||||
1. From input of SQLSRV_SQLTYPE_DATETIME2 to a dateteim2(7) column
|
||||
2. From input of SQLSRV_SQLTYPE_DATETIMEOFFSET to a datetimeoffset(7) column
|
||||
3. From input of SQLSRV_SQLTYPE_TIME to a time(7) column
|
||||
Note: with Always Encrypted, implicit converion should work as long as the SQLSRV_SQLTYPE has a smaller precision than the one defined in the column. However, the SQLSRV driver does not let the user specify the precision in these SQLSRV_SQLTYPE_* constants and they are all default to a precision of 7. Hence when user specifies SQLSRV_SQLTYPE_DATETIME2, SQLSRV_SQLTYPE_DATETIMEOFFSET or SQLSRV_SQLTYPE_TIME when binding parameter during insertion, only insertion into a column of precision 7 is allowed.
|
||||
Without AlwaysEncrypted, implicit conversion between different precisions works
|
||||
--SKIPIF--
|
||||
<?php require('skipif_versions_old.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
function compareDate($dtobj, $dtstr, $dataType, $precision) {
|
||||
$dtobj_date = $dtobj->format("Y-m-d H:i:s.u");
|
||||
$dtobj_timezone = $dtobj->getTimezone()->getName();
|
||||
$dtarr = null;
|
||||
|
||||
if ($dataType == "datetimeoffset") {
|
||||
$dtarr = explode(' ', $dtstr);
|
||||
}
|
||||
|
||||
// php only supports up to 6 decimal places in datetime
|
||||
// drop the last decimal place before comparing
|
||||
if ($precision == 7) {
|
||||
$dtstr = substr($dtstr, 0, -1);
|
||||
if (!is_null($dtarr)) {
|
||||
$dtarr[1] = substr($dtarr[1], 0, -1);
|
||||
}
|
||||
}
|
||||
if (strpos($dtobj_date, $dtstr) !== false) {
|
||||
return true;
|
||||
}
|
||||
if ($dataType == "datetimeoffset") {
|
||||
if (strpos($dtobj_date, $dtarr[0]) !== false && strpos($dtobj_date, $dtarr[1]) !== false && strpos($dtobj_timezone, $dtarr[2]) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$dataTypes = array("datetime2", "datetimeoffset", "time");
|
||||
$precisions = array(0, 1, 2, 4, 7);
|
||||
$inputValuesInit = array("datetime2" => array("0001-01-01 00:00:00", "9999-12-31 23:59:59"),
|
||||
"datetimeoffset" => array("0001-01-01 00:00:00 -14:00", "9999-12-31 23:59:59 +14:00"),
|
||||
"time" => array("00:00:00", "23:59:59"));
|
||||
|
||||
$conn = AE\connect();
|
||||
foreach($dataTypes as $dataType) {
|
||||
foreach($precisions as $m) {
|
||||
// add $m number of decimal digits to the some input values
|
||||
$inputValues[0] = $inputValuesInit[$dataType][0];
|
||||
$inputValues[1] = $inputValuesInit[$dataType][1];
|
||||
if ($m != 0) {
|
||||
if ($dataType == "datetime2") {
|
||||
$inputValues[1] .= "." . str_repeat("4", $m);
|
||||
} else if ($dataType == "datetimeoffset") {
|
||||
$dtoffsetPieces = explode(" ", $inputValues[1]);
|
||||
$inputValues[1] = $dtoffsetPieces[0] . " " . $dtoffsetPieces[1] . "." . str_repeat("4", $m) . " " . $dtoffsetPieces[2];
|
||||
} else if ($dataType == "time") {
|
||||
$inputValues[0] .= "." . str_repeat("0", $m);
|
||||
$inputValues[1] .= "." . str_repeat("4", $m);
|
||||
}
|
||||
}
|
||||
$typeFull = "$dataType($m)";
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing datetime2(m), datetimeoffset(m) or time(m) columns
|
||||
$tbname = "test_" . $dataType . $m;
|
||||
$colMetaArr = array(new AE\ColumnMeta($typeFull, "c_det"), new AE\ColumnMeta($typeFull, "c_rand", null, false));
|
||||
AE\createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying the corresponding SQLSRV_SQLTYPE
|
||||
$sqlType = "SQLSRV_SQLTYPE_" . strtoupper($dataType);
|
||||
$inputs = array(new AE\BindParamOption($inputValues[0], null, null, $sqlType),
|
||||
new AE\BindParamOption($inputValues[1], null, null, $sqlType));
|
||||
$r;
|
||||
$stmt = AE\insertRow($conn, $tbname, array("c_det" => $inputs[0], "c_rand" => $inputs[1]), $r, AE\INSERT_PREPARE_PARAMS);
|
||||
|
||||
// check the case when the column precision (m) is less than 7
|
||||
// with AE: should not work
|
||||
// without AE: should work
|
||||
if ($m < 7) {
|
||||
if (AE\isDataEncrypted()) {
|
||||
if ($r !== false) {
|
||||
echo "AE: Conversion from $sqlType to $typeFull should not be supported\n";
|
||||
} else {
|
||||
if (sqlsrv_errors()[0]['SQLSTATE'] != "22018") {
|
||||
echo "AE: Conversion from $sqlType to $typeFull expects an operand type clash error, actual error is incorrect\n";
|
||||
var_dump(sqlsrv_errors());
|
||||
} else {
|
||||
echo "Test successfully done\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqlType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (!compareDate($row['c_det'], $inputValues[0], $dataType, $m) || !compareDate($row['c_rand'], $inputValues[1], $dataType, $m)) {
|
||||
echo "Conversion from $sqlType to $typeFull causes data corruption\n";
|
||||
} else {
|
||||
echo "Test successfully done\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// check the case when the column precision is 7
|
||||
// should work with AE or non AE
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqlType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (compareDate($row['c_det'], $inputValues[0], $dataType, $m) && compareDate($row['c_rand'], $inputValues[1], $dataType, $m)) {
|
||||
echo "****Conversion from $sqlType to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $sqlType to $typeFull causes data corruption\n";
|
||||
var_dump($row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
sqlsrv_free_stmt($stmt);
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
sqlsrv_close($conn);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing datetime2(0):
|
||||
Test successfully done
|
||||
|
||||
Testing datetime2(1):
|
||||
Test successfully done
|
||||
|
||||
Testing datetime2(2):
|
||||
Test successfully done
|
||||
|
||||
Testing datetime2(4):
|
||||
Test successfully done
|
||||
|
||||
Testing datetime2(7):
|
||||
****Conversion from SQLSRV_SQLTYPE_DATETIME2 to datetime2(7) is supported****
|
||||
|
||||
Testing datetimeoffset(0):
|
||||
Test successfully done
|
||||
|
||||
Testing datetimeoffset(1):
|
||||
Test successfully done
|
||||
|
||||
Testing datetimeoffset(2):
|
||||
Test successfully done
|
||||
|
||||
Testing datetimeoffset(4):
|
||||
Test successfully done
|
||||
|
||||
Testing datetimeoffset(7):
|
||||
****Conversion from SQLSRV_SQLTYPE_DATETIMEOFFSET to datetimeoffset(7) is supported****
|
||||
|
||||
Testing time(0):
|
||||
Test successfully done
|
||||
|
||||
Testing time(1):
|
||||
Test successfully done
|
||||
|
||||
Testing time(2):
|
||||
Test successfully done
|
||||
|
||||
Testing time(4):
|
||||
Test successfully done
|
||||
|
||||
Testing time(7):
|
||||
****Conversion from SQLSRV_SQLTYPE_TIME to time(7) is supported****
|
|
@ -0,0 +1,247 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data of decimal types with different precisions and scales
|
||||
--DESCRIPTION--
|
||||
Test implicit conversions between different precisions and scales
|
||||
With Always Encrypted, no implicit conversion works for decimal datatypes, the precision and scale specified in the SQLSRV_SQLTYPE must be identical to the precision and scale defined in the column
|
||||
Without AlwaysEncrypted, implicit conversion between precisions or scales works if:
|
||||
1. From input of SQLSRV_SQLTYPE_DECIMAL(n1, n2) to a decimal(m1, m2) column where n1 - n2 > m1 - m2 and
|
||||
2. where n2 != 0 && m1 != m2
|
||||
--SKIPIF--
|
||||
<?php require('skipif_versions_old.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
$dataTypes = array("decimal", "numeric");
|
||||
$precisions = array(1 => array(0, 1),
|
||||
4 => array(0, 1, 4),
|
||||
16 => array(0, 1, 4, 16),
|
||||
38 => array(0, 1, 4, 16, 38));
|
||||
$sqlTypes = array("SQLSRV_SQLTYPE_DECIMAL", "SQLSRV_SQLTYPE_NUMERIC");
|
||||
$sqltypePrecisions = $precisions;
|
||||
$inputValuesInit = array(92233720368547758089223372036854775808, -92233720368547758089223372036854775808);
|
||||
$maxInPrecision = 38;
|
||||
|
||||
$conn = AE\connect();
|
||||
|
||||
foreach($dataTypes as $dataType) {
|
||||
foreach($precisions as $m1 => $inScales) {
|
||||
foreach($inScales as $m2) {
|
||||
// change the number of integers in the input values to be $m1 - $m2
|
||||
$precDiff = $maxInPrecision - ($m1 - $m2);
|
||||
$inputValues = $inputValuesInit;
|
||||
foreach ($inputValues as &$inputValue) {
|
||||
$inputValue = $inputValue / pow(10, $precDiff);
|
||||
}
|
||||
$typeFull = "$dataType($m1, $m2)";
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing decimal(m1, m2) or numeric(m1, m2) columns
|
||||
$tbname = "test_" . $dataType . $m1 . $m2;
|
||||
$colMetaArr = array(new AE\ColumnMeta($typeFull, "c_det"), new AE\ColumnMeta($typeFull, "c_rand", null, false));
|
||||
AE\createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying SQLSRV_SQLTYPE_DECIMAL(n1, n2) or SQLSRV_SQLTYPE_NUMERIC(n1, n2)
|
||||
// with AE, should only be successful if the SQLSRV_SQLTYPE precision (n1) and scale (n2) are the same as the column precision (m1) and scale (m2)
|
||||
foreach($sqlTypes as $sqlType) {
|
||||
foreach($sqltypePrecisions as $n1 => $sqltypeScales) {
|
||||
foreach($sqltypeScales as $n2) {
|
||||
|
||||
// compute the epsilon for comparing doubles
|
||||
// float in PHP only has a precision of roughtly 14 digits: http://php.net/manual/en/language.types.float.php
|
||||
// the smaller precision and scale (n1 and n2 vs m1 and m2) take precedence
|
||||
$epsilon;
|
||||
$smallerprec = min($m1, $n1);
|
||||
$smallerscale = min($m2, $n2);
|
||||
if ($smallerprec < 14) {
|
||||
$epsilon = pow(10, $smallerscale * -1);
|
||||
} else {
|
||||
$numint = $smallerprec - $smallerscale;
|
||||
if ($numint < 14) {
|
||||
$epsilon = pow(10, (14 - $numint) * -1);
|
||||
} else {
|
||||
$epsilon = pow(10, $numint - 14);
|
||||
}
|
||||
}
|
||||
|
||||
$sqltypeFull = "$sqlType($n1, $n2)";
|
||||
|
||||
//insert a row
|
||||
$inputs = array(new AE\BindParamOption((string)$inputValues[0], null, null, $sqltypeFull),
|
||||
new AE\BindParamOption((string)$inputValues[1], null, null, $sqltypeFull));
|
||||
$r;
|
||||
$stmt = AE\insertRow($conn, $tbname, array("c_det" => $inputs[0], "c_rand" => $inputs[1]), $r, AE\INSERT_PREPARE_PARAMS);
|
||||
|
||||
// check the case when the SQLSRV_SQLTYPE precision (n1) is not the same as the column precision (m1)
|
||||
// or the SQLSRV_SQLTYPE scale (n2) is not the same as the column precision (m2)
|
||||
// with AE: should not work
|
||||
// without AE: should not work if n1 - n2 < m1 - m2 (Numeric value out of range error)
|
||||
// or n2 != 0 && $m1 == $m2 (Arithmetic overflow error)
|
||||
if ($n1 != $m1 || $n2 != $m2) {
|
||||
if (AE\isDataEncrypted()) {
|
||||
if ($r !== false) {
|
||||
echo "AE: Conversion from $sqltypeFull to $typeFull should not be supported\n";
|
||||
} else {
|
||||
if (sqlsrv_errors()[0]['SQLSTATE'] != "22018") {
|
||||
echo "AE: Conversion from $sqltypeFull to $typeFull expects an operand type clash error, actual error is incorrect\n";
|
||||
var_dump(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($n1 - $n2 < $m1 - $m2 || ($m1 == $m2 && $n2 == 0)) {
|
||||
if ($r !== false) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull should not be supported\n";
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (abs($row['c_det'] - $inputValues[0]) > $epsilon || abs($row['c_rand'] - $inputValues[1]) > $epsilon) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// check the case when the SQLSRV_SQLTYPE precision (n1) and scale (n2) are the same as the column precision (m1) and scale (m2)
|
||||
// should work with AE or non AE
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (abs($row['c_det'] - $inputValues[0]) < $epsilon && abs($row['c_rand'] - $inputValues[1]) < $epsilon) {
|
||||
echo "****Conversion from $sqltypeFull to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $sqltypeFull to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
sqlsrv_free_stmt($stmt);
|
||||
sqlsrv_query($conn, "TRUNCATE TABLE $tbname");
|
||||
}
|
||||
}
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlsrv_close($conn);
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing decimal(1, 0):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(1, 0) to decimal(1, 0) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(1, 0) to decimal(1, 0) is supported****
|
||||
|
||||
Testing decimal(1, 1):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(1, 1) to decimal(1, 1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(1, 1) to decimal(1, 1) is supported****
|
||||
|
||||
Testing decimal(4, 0):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(4, 0) to decimal(4, 0) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(4, 0) to decimal(4, 0) is supported****
|
||||
|
||||
Testing decimal(4, 1):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(4, 1) to decimal(4, 1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(4, 1) to decimal(4, 1) is supported****
|
||||
|
||||
Testing decimal(4, 4):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(4, 4) to decimal(4, 4) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(4, 4) to decimal(4, 4) is supported****
|
||||
|
||||
Testing decimal(16, 0):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(16, 0) to decimal(16, 0) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(16, 0) to decimal(16, 0) is supported****
|
||||
|
||||
Testing decimal(16, 1):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(16, 1) to decimal(16, 1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(16, 1) to decimal(16, 1) is supported****
|
||||
|
||||
Testing decimal(16, 4):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(16, 4) to decimal(16, 4) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(16, 4) to decimal(16, 4) is supported****
|
||||
|
||||
Testing decimal(16, 16):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(16, 16) to decimal(16, 16) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(16, 16) to decimal(16, 16) is supported****
|
||||
|
||||
Testing decimal(38, 0):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 0) to decimal(38, 0) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 0) to decimal(38, 0) is supported****
|
||||
|
||||
Testing decimal(38, 1):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 1) to decimal(38, 1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 1) to decimal(38, 1) is supported****
|
||||
|
||||
Testing decimal(38, 4):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 4) to decimal(38, 4) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 4) to decimal(38, 4) is supported****
|
||||
|
||||
Testing decimal(38, 16):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 16) to decimal(38, 16) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 16) to decimal(38, 16) is supported****
|
||||
|
||||
Testing decimal(38, 38):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 38) to decimal(38, 38) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 38) to decimal(38, 38) is supported****
|
||||
|
||||
Testing numeric(1, 0):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(1, 0) to numeric(1, 0) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(1, 0) to numeric(1, 0) is supported****
|
||||
|
||||
Testing numeric(1, 1):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(1, 1) to numeric(1, 1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(1, 1) to numeric(1, 1) is supported****
|
||||
|
||||
Testing numeric(4, 0):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(4, 0) to numeric(4, 0) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(4, 0) to numeric(4, 0) is supported****
|
||||
|
||||
Testing numeric(4, 1):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(4, 1) to numeric(4, 1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(4, 1) to numeric(4, 1) is supported****
|
||||
|
||||
Testing numeric(4, 4):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(4, 4) to numeric(4, 4) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(4, 4) to numeric(4, 4) is supported****
|
||||
|
||||
Testing numeric(16, 0):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(16, 0) to numeric(16, 0) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(16, 0) to numeric(16, 0) is supported****
|
||||
|
||||
Testing numeric(16, 1):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(16, 1) to numeric(16, 1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(16, 1) to numeric(16, 1) is supported****
|
||||
|
||||
Testing numeric(16, 4):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(16, 4) to numeric(16, 4) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(16, 4) to numeric(16, 4) is supported****
|
||||
|
||||
Testing numeric(16, 16):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(16, 16) to numeric(16, 16) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(16, 16) to numeric(16, 16) is supported****
|
||||
|
||||
Testing numeric(38, 0):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 0) to numeric(38, 0) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 0) to numeric(38, 0) is supported****
|
||||
|
||||
Testing numeric(38, 1):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 1) to numeric(38, 1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 1) to numeric(38, 1) is supported****
|
||||
|
||||
Testing numeric(38, 4):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 4) to numeric(38, 4) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 4) to numeric(38, 4) is supported****
|
||||
|
||||
Testing numeric(38, 16):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 16) to numeric(38, 16) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 16) to numeric(38, 16) is supported****
|
||||
|
||||
Testing numeric(38, 38):
|
||||
****Conversion from SQLSRV_SQLTYPE_DECIMAL(38, 38) to numeric(38, 38) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NUMERIC(38, 38) to numeric(38, 38) is supported****
|
103
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_float_bits.phpt
Normal file
103
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_float_bits.phpt
Normal file
|
@ -0,0 +1,103 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data of float types with different number of bits
|
||||
--DESCRIPTION--
|
||||
Test implicit conversions between different number of bits
|
||||
With Always Encrypted, implicit conversion works if:
|
||||
1. From input of SQLSRV_SQLTYPE_FLOAT to a float(m) column where m > 24
|
||||
Note: with Always Encrypted, implicit conversion should work as long as the SQLSRV_SQLTYPE has a smaller number of bits than the one defined in the column. However, the SQLSRV driver does not let the user specify the number of bits in the SQLSRV_SQLTYPE_FLOAT constant and it is default to 53. Hence when user specifies SQLSRV_SQLTYPE_FLOAT when binding parameter during insertion, only insertion into a column of > 24 is allowed.
|
||||
Without Always Encrypted, implicit conversion between different number of bits works.
|
||||
--SKIPIF--
|
||||
<?php require('skipif_versions_old.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
$dataType = "float";
|
||||
$bits = array(1, 12, 24, 36, 53);
|
||||
$sqlType = "SQLSRV_SQLTYPE_FLOAT";
|
||||
$inputValues = array(9223372036854775808.9223372036854775808, -9223372036854775808.9223372036854775808);
|
||||
$epsilon = 100000;
|
||||
|
||||
$conn = AE\connect();
|
||||
foreach($bits as $m) {
|
||||
$typeFull = "$dataType($m)";
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing float(m) columns
|
||||
$tbname = "test_" . $dataType . $m;
|
||||
$colMetaArr = array(new AE\ColumnMeta($typeFull, "c_det"), new AE\ColumnMeta($typeFull, "c_rand", null, false));
|
||||
AE\createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying SQLSRV_SQLTYPE_FLOAT
|
||||
$inputs = array(new AE\BindParamOption($inputValues[0], null, null, $sqlType),
|
||||
new AE\BindParamOption($inputValues[1], null, null, $sqlType));
|
||||
$r;
|
||||
$stmt = AE\insertRow($conn, $tbname, array("c_det" => $inputs[0], "c_rand" => $inputs[1]), $r, AE\INSERT_PREPARE_PARAMS);
|
||||
|
||||
// check the case when the column number of bits is less than 25
|
||||
// with AE: should not work
|
||||
// without AE: should work
|
||||
if ($m < 25) {
|
||||
if (AE\isDataEncrypted()) {
|
||||
if ($r !== false) {
|
||||
echo "AE: Conversion from $sqlType to $typeFull should not be supported\n";
|
||||
} else {
|
||||
if (sqlsrv_errors()[0]['SQLSTATE'] != "22018") {
|
||||
echo "AE: Conversion from $sqlType to $typeFull expects an operand type clash error, actual error is incorrect\n";
|
||||
var_dump(sqlsrv_errors());
|
||||
} else {
|
||||
echo "Test successfully done\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqlType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (abs($row['c_det'] - $inputValues[0]) > $epsilon || abs($row['c_rand'] - $inputValues[1]) > $epsilon) {
|
||||
echo "Conversion from $sqlType to $typeFull causes data corruption\n";
|
||||
} else {
|
||||
echo "Test successfully done\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// check the case when the column number of bits 25 or more
|
||||
// should work with AE or non AE
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqlType to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (abs($row['c_det'] - $inputValues[0]) < $epsilon && abs($row['c_rand'] - $inputValues[1]) < $epsilon) {
|
||||
echo "****Conversion from $sqlType to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $sqlType to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
sqlsrv_free_stmt($stmt);
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
sqlsrv_close($conn);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing float(1):
|
||||
Test successfully done
|
||||
|
||||
Testing float(12):
|
||||
Test successfully done
|
||||
|
||||
Testing float(24):
|
||||
Test successfully done
|
||||
|
||||
Testing float(36):
|
||||
****Conversion from SQLSRV_SQLTYPE_FLOAT to float(36) is supported****
|
||||
|
||||
Testing float(53):
|
||||
****Conversion from SQLSRV_SQLTYPE_FLOAT to float(53) is supported****
|
127
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_int_conv.phpt
Normal file
127
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_int_conv.phpt
Normal file
|
@ -0,0 +1,127 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data of int types
|
||||
--DESCRIPTION--
|
||||
Test implicit conversions between different integer types
|
||||
With Always Encrypted, implicit conversion works if:
|
||||
1. From input SQLSRV_SQLTYPE_BIT to a bit column
|
||||
2. From input SQLSRV_SQLTYPE_BIT to a tinyint column
|
||||
3. From input SQLSRV_SQLTYPE_BIT to a smallint column
|
||||
4. From input SQLSRV_SQLTYPE_BIT to an int column
|
||||
5. From input SQLSRV_SQLTYPE_BIT to a bigint column
|
||||
6. From input SQLSRV_SQLTYPE_TINYINT to a tinyint column
|
||||
7. From input SQLSRV_SQLTYPE_TINYINT to a smallint column
|
||||
8. From input SQLSRV_SQLTYPE_TINYINT to an int column
|
||||
9. From input SQLSRV_SQLTYPE_TINYINT to a bigint column
|
||||
10. From input SQLSRV_SQLTYPE_SMALLINT to a smallint column
|
||||
11. From input SQLSRV_SQLTYPE_SMALLINT to an int column
|
||||
12. From input SQLSRV_SQLTYPE_SMALLINT to a bigint column
|
||||
13. From input SQLSRV_SQLTYPE_INT to an int column
|
||||
14. From input SQLSRV_SQLTYPE_INT to a bigint column
|
||||
15. From input SQLSRV_SQLTYPE_BIGINT to a bigint column
|
||||
Without AlwaysEncrypted, implicit conversion between different integer types works
|
||||
--SKIPIF--
|
||||
<?php require('skipif_versions_old.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
$dataTypes = array("bit", "tinyint", "smallint", "int", "bigint");
|
||||
$sqlTypes = array("SQLSRV_SQLTYPE_BIT", "SQLSRV_SQLTYPE_TINYINT", "SQLSRV_SQLTYPE_SMALLINT", "SQLSRV_SQLTYPE_INT", "SQLSRV_SQLTYPE_BIGINT");
|
||||
// only 1 and 0 inputs are tested as they are the only values that fit into all integer types
|
||||
// this test is for testing different integer conversions, if the input value does not fit into a datatype,
|
||||
// the conversion would fail not because the conversion is not supported, but because of other errors such as truncation
|
||||
$inputValues = array(1, 0);
|
||||
|
||||
// this is a list of implicit datatype conversion that AE supports
|
||||
$aeConvList = array("bit" => array("SQLSRV_SQLTYPE_BIT"),
|
||||
"tinyint" => array("SQLSRV_SQLTYPE_BIT", "SQLSRV_SQLTYPE_TINYINT"),
|
||||
"smallint" => array("SQLSRV_SQLTYPE_BIT", "SQLSRV_SQLTYPE_TINYINT", "SQLSRV_SQLTYPE_SMALLINT"),
|
||||
"int" => array("SQLSRV_SQLTYPE_BIT", "SQLSRV_SQLTYPE_TINYINT", "SQLSRV_SQLTYPE_SMALLINT", "SQLSRV_SQLTYPE_INT"),
|
||||
"bigint" => array("SQLSRV_SQLTYPE_BIT", "SQLSRV_SQLTYPE_TINYINT", "SQLSRV_SQLTYPE_SMALLINT", "SQLSRV_SQLTYPE_INT", "SQLSRV_SQLTYPE_BIGINT"));
|
||||
|
||||
$conn = AE\connect();
|
||||
foreach ($dataTypes as $dataType) {
|
||||
echo "\nTesting $dataType:\n";
|
||||
|
||||
// create table containing bit, tinyint, smallint, int, or bigint columns
|
||||
$tbname = "test_" . $dataType;
|
||||
$colMetaArr = array( new AE\ColumnMeta($dataType, "c_det"), new AE\ColumnMeta($dataType, "c_rand", null, false));
|
||||
AE\createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying different SQLSRV_SQLTYPE integer constants
|
||||
// with AE, should only be successful if the SQLSRV_SQLTYPE is smaller in size than the column datatype
|
||||
foreach($sqlTypes as $sqlType) {
|
||||
$inputs = array(new AE\BindParamOption($inputValues[0], null, null, $sqlType), new AE\BindParamOption($inputValues[1], null, null, $sqlType));
|
||||
$r;
|
||||
$stmt = AE\insertRow($conn, $tbname, array($colMetaArr[0]->colName => $inputs[0], $colMetaArr[1]->colName => $inputs[1]), $r, AE\INSERT_PREPARE_PARAMS);
|
||||
|
||||
// check the case if the type conversion is not listed in $aeConvList
|
||||
if (!in_array($sqlType, $aeConvList["$dataType"])) {
|
||||
if (AE\isDataEncrypted()) {
|
||||
if ($r !== false) {
|
||||
echo "AE: Conversion from $sqlType to $dataType should not be supported\n";
|
||||
} else {
|
||||
if (sqlsrv_errors()[0]['SQLSTATE'] != "22018") {
|
||||
echo "AE: Conversion from $sqlType to $dataType expects an operand type clash error, actual error is incorrect\n";
|
||||
var_dump(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqlType to $dataType should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if ($row['c_det'] != $inputValues[0] || $row['c_rand'] != $inputValues[1]) {
|
||||
echo "Conversion from $sqlType to $dataType causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqlType to $dataType should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c_det, c_rand FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if ($row['c_det'] == $inputValues[0] && $row['c_rand'] == $inputValues[1]) {
|
||||
echo "****Conversion from $sqlType to $dataType is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $sqlType to $dataType causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
sqlsrv_free_stmt($stmt);
|
||||
sqlsrv_query($conn, "TRUNCATE TABLE $tbname");
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
sqlsrv_close($conn);
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing bit:
|
||||
****Conversion from SQLSRV_SQLTYPE_BIT to bit is supported****
|
||||
|
||||
Testing tinyint:
|
||||
****Conversion from SQLSRV_SQLTYPE_BIT to tinyint is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_TINYINT to tinyint is supported****
|
||||
|
||||
Testing smallint:
|
||||
****Conversion from SQLSRV_SQLTYPE_BIT to smallint is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_TINYINT to smallint is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_SMALLINT to smallint is supported****
|
||||
|
||||
Testing int:
|
||||
****Conversion from SQLSRV_SQLTYPE_BIT to int is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_TINYINT to int is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_SMALLINT to int is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_INT to int is supported****
|
||||
|
||||
Testing bigint:
|
||||
****Conversion from SQLSRV_SQLTYPE_BIT to bigint is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_TINYINT to bigint is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_SMALLINT to bigint is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_INT to bigint is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_BIGINT to bigint is supported****
|
275
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_nchar_size.phpt
Normal file
275
test/functional/sqlsrv/sqlsrv_ae_insert_sqltype_nchar_size.phpt
Normal file
|
@ -0,0 +1,275 @@
|
|||
--TEST--
|
||||
Test for inserting encrypted data of nchar types with different sizes
|
||||
--DESCRIPTION--
|
||||
Test implicit conversions between different nchar types of different sizes
|
||||
With Always Encrypted, implicit conversion works if:
|
||||
1. From input of SQLSRV_SQLTYPE_NCHAR(n) to a larger nchar(m) column where n <= m
|
||||
2. From input of SQLSRV_SQLTYPE_NCHAR(n) to a larger nvarchar(m) column where n <= m (m can be max)
|
||||
3. From input of SQLSRV_SQLTYPE_NVARCHAR(n) to a larger nchar(m) column where n <= m
|
||||
4. From input of SQLSRV_SQLTYPE_NVARCHAR(n) to a larger nvarchar(m) column where n <= m (m can be max)
|
||||
Without AlwaysEncrypted, implicit conversion between different binary types and sizes works
|
||||
--SKIPIF--
|
||||
<?php require('skipif_versions_old.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
$dataTypes = array("nchar", "nvarchar", "nvarchar(max)");
|
||||
$lengths = array(1, 8, 64, 512, 4000);
|
||||
$sqlTypes = array("SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_NVARCHAR('max')");
|
||||
$sqltypeLengths = $lengths;
|
||||
$inputValue = "d";
|
||||
|
||||
$conn = AE\connect();
|
||||
foreach($dataTypes as $dataType) {
|
||||
$maxcol = strpos($dataType, "(max)");
|
||||
foreach($lengths as $m) {
|
||||
if ($maxcol !== false) {
|
||||
$typeFull = $dataType;
|
||||
} else {
|
||||
$typeFull = "$dataType($m)";
|
||||
}
|
||||
echo "\nTesting $typeFull:\n";
|
||||
|
||||
// create table containing nchar(m) or nvarchar(m) columns
|
||||
// only one column is created because a row has a limitation of 8060 bytes
|
||||
// for lengths 4096 and 8000, cannot create 2 columns as it will exceed the maximum row sizes
|
||||
// for AE, only testing randomized here, deterministic is tested in the char test
|
||||
$tbname = "test_" . str_replace(array('(', ')'), '', $dataType) . $m;
|
||||
$colMetaArr = array(new AE\ColumnMeta($typeFull, "c1", null, false));
|
||||
AE\createTable($conn, $tbname, $colMetaArr);
|
||||
|
||||
// insert by specifying SQLSRV_SQLTYPE_NCHAR(n) or SQLSRV_SQLTYPE_NVARCHAR(n)
|
||||
// with AE, should be successful as long as the SQLSRV_SQLTYPE length (n) is smaller than the column length (m)
|
||||
foreach($sqlTypes as $sqlType) {
|
||||
$maxsqltype = strpos($sqlType, "max");
|
||||
foreach($sqltypeLengths as $n) {
|
||||
if ($maxsqltype !== false) {
|
||||
$sqltypeFull = $sqlType;
|
||||
} else {
|
||||
$sqltypeFull = "$sqlType($n)";
|
||||
}
|
||||
|
||||
//insert a row
|
||||
$input = new AE\BindParamOption($inputValue, null, null, $sqltypeFull);
|
||||
$r;
|
||||
$stmt = AE\insertRow($conn, $tbname, array("c1" => $input), $r, AE\INSERT_PREPARE_PARAMS);
|
||||
|
||||
// check the case when SQLSRV_SQLTYPE length (n) is greater than the column length (m)
|
||||
// if SQLSRV_SQLTYPE_NVARCHAR(max) ($maxsqltype), no conversion is supported except if the column is also max ($maxcol)
|
||||
// if column is max ($maxcol), all conversions are supported
|
||||
// with AE: should not work
|
||||
// without AE: should work
|
||||
if (($n > $m || $maxsqltype) && !$maxcol) {
|
||||
if (AE\isDataEncrypted()) {
|
||||
if ($r !== false) {
|
||||
echo "AE: Conversion from $sqltypeFull to $typeFull should not be supported\n";
|
||||
} else {
|
||||
if (sqlsrv_errors()[0]['SQLSTATE'] != "22018") {
|
||||
echo "AE: Conversion from $sqltypeFull to $typeFull expects an operand type clash error, actual error is incorrect\n";
|
||||
var_dump(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversions from $sqltypeFull to $typeFull should be supported\n";
|
||||
}
|
||||
$sql = "SELECT c1 FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (trim($row['c1']) != $inputValue) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
// check the case when SQLSRV_SQLTYPE length (n) is less than or equal to the column length (m)
|
||||
// should work with AE or non AE
|
||||
} else {
|
||||
if ($r === false) {
|
||||
echo "Conversion from $sqltypeFull to $typeFull should be supported\n";
|
||||
} else {
|
||||
$sql = "SELECT c1 FROM $tbname";
|
||||
$stmt = sqlsrv_query($conn, $sql);
|
||||
$row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
|
||||
if (trim($row['c1']) == $inputValue) {
|
||||
echo "****Conversion from $sqltypeFull to $typeFull is supported****\n";
|
||||
} else {
|
||||
echo "Conversion from $sqltypeFull to $typeFull causes data corruption\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
sqlsrv_free_stmt($stmt);
|
||||
sqlsrv_query($conn, "TRUNCATE TABLE $tbname");
|
||||
}
|
||||
}
|
||||
dropTable($conn, $tbname);
|
||||
}
|
||||
}
|
||||
sqlsrv_close($conn);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Testing nchar(1):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nchar(1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nchar(1) is supported****
|
||||
|
||||
Testing nchar(8):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nchar(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nchar(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nchar(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nchar(8) is supported****
|
||||
|
||||
Testing nchar(64):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nchar(64) is supported****
|
||||
|
||||
Testing nchar(512):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(512) to nchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(512) to nchar(512) is supported****
|
||||
|
||||
Testing nchar(4000):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(512) to nchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(4000) to nchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(512) to nchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(4000) to nchar(4000) is supported****
|
||||
|
||||
Testing nvarchar(1):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(1) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(1) is supported****
|
||||
|
||||
Testing nvarchar(8):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nvarchar(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(8) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nvarchar(8) is supported****
|
||||
|
||||
Testing nvarchar(64):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nvarchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nvarchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nvarchar(64) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nvarchar(64) is supported****
|
||||
|
||||
Testing nvarchar(512):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nvarchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nvarchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(512) to nvarchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nvarchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nvarchar(512) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(512) to nvarchar(512) is supported****
|
||||
|
||||
Testing nvarchar(4000):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nvarchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nvarchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(512) to nvarchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(4000) to nvarchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nvarchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nvarchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(512) to nvarchar(4000) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(4000) to nvarchar(4000) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
|
||||
Testing nvarchar(max):
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(1) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(8) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(64) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(512) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR(4000) to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
||||
****Conversion from SQLSRV_SQLTYPE_NVARCHAR('max') to nvarchar(max) is supported****
|
|
@ -1,158 +1,134 @@
|
|||
--TEST--
|
||||
Test new connection keyword Driver with valid and invalid values
|
||||
--SKIPIF--
|
||||
<?php require('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
sqlsrv_configure('WarningsReturnAsErrors', 0);
|
||||
require_once('MsSetup.inc');
|
||||
|
||||
$connectionOptions = array("Database"=>$database, "UID"=>$userName, "PWD"=>$userPassword);
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
$msodbcsqlVer = sqlsrv_client_info($conn)['DriverVer'];
|
||||
$msodbcsqlMaj = explode(".", $msodbcsqlVer)[0];
|
||||
sqlsrv_close($conn);
|
||||
|
||||
// start test
|
||||
testValidValues($msodbcsqlMaj, $server, $connectionOptions);
|
||||
testInvalidValues($msodbcsqlMaj, $server, $connectionOptions);
|
||||
testEncryptedWithODBC($msodbcsqlMaj, $server, $connectionOptions);
|
||||
testWrongODBC($msodbcsqlMaj, $server, $connectionOptions);
|
||||
echo "Done";
|
||||
// end test
|
||||
|
||||
///////////////////////////
|
||||
function connectVerifyOutput($server, $connectionOptions, $expected = '')
|
||||
{
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
if (strpos(sqlsrv_errors($conn)[0]['message'], $expected) === false) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testValidValues($msodbcsqlMaj, $server, $connectionOptions)
|
||||
{
|
||||
$value = "";
|
||||
// The major version number of ODBC 11 can be 11 or 12
|
||||
// Test with {}
|
||||
switch ($msodbcsqlMaj) {
|
||||
case 17:
|
||||
$value = "{ODBC Driver 17 for SQL Server}";
|
||||
break;
|
||||
case 14:
|
||||
case 13:
|
||||
$value = "{ODBC Driver 13 for SQL Server}";
|
||||
break;
|
||||
case 12:
|
||||
case 11:
|
||||
$value = "{ODBC Driver 11 for SQL Server}";
|
||||
break;
|
||||
default:
|
||||
$value = "invalid value $msodbcsqlMaj";
|
||||
}
|
||||
$connectionOptions['Driver']=$value;
|
||||
connectVerifyOutput($server, $connectionOptions);
|
||||
|
||||
// Test without {}
|
||||
switch ($msodbcsqlMaj) {
|
||||
case 17:
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
break;
|
||||
case 14:
|
||||
case 13:
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
break;
|
||||
case 12:
|
||||
case 11:
|
||||
$value = "ODBC Driver 11 for SQL Server";
|
||||
break;
|
||||
default:
|
||||
$value = "invalid value $msodbcsqlMaj";
|
||||
}
|
||||
|
||||
$connectionOptions['Driver']=$value;
|
||||
connectVerifyOutput($server, $connectionOptions);
|
||||
}
|
||||
|
||||
function testInvalidValues($msodbcsqlMaj, $server, $connectionOptions)
|
||||
{
|
||||
$values = array("{SQL Server Native Client 11.0}",
|
||||
"SQL Server Native Client 11.0",
|
||||
"ODBC Driver 00 for SQL Server");
|
||||
|
||||
foreach ($values as $value) {
|
||||
$connectionOptions['Driver']=$value;
|
||||
$expected = "Invalid value $value was specified for Driver option.";
|
||||
connectVerifyOutput($server, $connectionOptions, $expected);
|
||||
}
|
||||
|
||||
$values = array(123, false);
|
||||
|
||||
foreach ($values as $value) {
|
||||
$connectionOptions['Driver']=$value;
|
||||
$expected = "Invalid value type for option Driver was specified. String type was expected.";
|
||||
connectVerifyOutput($server, $connectionOptions, $expected);
|
||||
}
|
||||
}
|
||||
|
||||
function testEncryptedWithODBC($msodbcsqlMaj, $server, $connectionOptions)
|
||||
{
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
$connectionOptions['Driver']=$value;
|
||||
$connectionOptions['ColumnEncryption']='Enabled';
|
||||
|
||||
$expected = "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.";
|
||||
|
||||
connectVerifyOutput($server, $connectionOptions, $expected);
|
||||
|
||||
// TODO: the following block will change once ODBC 17 is officially released
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
$connectionOptions['Driver']=$value;
|
||||
$connectionOptions['ColumnEncryption']='Enabled';
|
||||
|
||||
$success = "Successfully connected with column encryption.";
|
||||
$expected = "The specified ODBC Driver is not found.";
|
||||
$message = $success;
|
||||
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
$message = sqlsrv_errors($conn)[0]['message'];
|
||||
}
|
||||
|
||||
if ($msodbcsqlMaj == 17) {
|
||||
// this indicates that OCBC 17 is the only available driver
|
||||
if (strcmp($message, $success)) {
|
||||
print_r($message);
|
||||
}
|
||||
} else {
|
||||
// OCBC 17 might or might not exist
|
||||
if (strcmp($message, $success)) {
|
||||
if (strpos($message, $expected) === false) {
|
||||
print_r($message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testWrongODBC($msodbcsqlMaj, $server, $connectionOptions)
|
||||
{
|
||||
// TODO: this will change once ODBC 17 is officially released
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
if ($msodbcsqlMaj == 17 || $msodbcsqlMaj < 13) {
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
}
|
||||
|
||||
$connectionOptions['Driver']=$value;
|
||||
$expected = "The specified ODBC Driver is not found.";
|
||||
|
||||
connectVerifyOutput($server, $connectionOptions, $expected);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
||||
--TEST--
|
||||
Test new connection keyword Driver with valid and invalid values
|
||||
--SKIPIF--
|
||||
<?php require('skipif.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
sqlsrv_configure('WarningsReturnAsErrors', 0);
|
||||
require_once('MsSetup.inc');
|
||||
|
||||
$connectionOptions = array("Database"=>$database, "UID"=>$userName, "PWD"=>$userPassword);
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
$msodbcsqlVer = sqlsrv_client_info($conn)['DriverVer'];
|
||||
$msodbcsqlMaj = explode(".", $msodbcsqlVer)[0];
|
||||
sqlsrv_close($conn);
|
||||
|
||||
// start test
|
||||
testValidValues($msodbcsqlMaj, $server, $connectionOptions);
|
||||
testInvalidValues($msodbcsqlMaj, $server, $connectionOptions);
|
||||
testEncryptedWithODBC($msodbcsqlMaj, $server, $connectionOptions);
|
||||
testWrongODBC($msodbcsqlMaj, $server, $connectionOptions);
|
||||
echo "Done";
|
||||
// end test
|
||||
|
||||
///////////////////////////
|
||||
function connectVerifyOutput($server, $connectionOptions, $expected = '')
|
||||
{
|
||||
$conn = sqlsrv_connect($server, $connectionOptions);
|
||||
if ($conn === false) {
|
||||
if (strpos(sqlsrv_errors($conn)[0]['message'], $expected) === false) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function testValidValues($msodbcsqlMaj, $server, $connectionOptions)
|
||||
{
|
||||
$value = "";
|
||||
// The major version number of ODBC 11 can be 11 or 12
|
||||
// Test with {}
|
||||
switch ($msodbcsqlMaj) {
|
||||
case 17:
|
||||
$value = "{ODBC Driver 17 for SQL Server}";
|
||||
break;
|
||||
case 14:
|
||||
case 13:
|
||||
$value = "{ODBC Driver 13 for SQL Server}";
|
||||
break;
|
||||
case 12:
|
||||
case 11:
|
||||
$value = "{ODBC Driver 11 for SQL Server}";
|
||||
break;
|
||||
default:
|
||||
$value = "invalid value $msodbcsqlMaj";
|
||||
}
|
||||
$connectionOptions['Driver']=$value;
|
||||
connectVerifyOutput($server, $connectionOptions);
|
||||
|
||||
// Test without {}
|
||||
switch ($msodbcsqlMaj) {
|
||||
case 17:
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
break;
|
||||
case 14:
|
||||
case 13:
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
break;
|
||||
case 12:
|
||||
case 11:
|
||||
$value = "ODBC Driver 11 for SQL Server";
|
||||
break;
|
||||
default:
|
||||
$value = "invalid value $msodbcsqlMaj";
|
||||
}
|
||||
|
||||
$connectionOptions['Driver']=$value;
|
||||
connectVerifyOutput($server, $connectionOptions);
|
||||
}
|
||||
|
||||
function testInvalidValues($msodbcsqlMaj, $server, $connectionOptions)
|
||||
{
|
||||
$values = array("{SQL Server Native Client 11.0}",
|
||||
"SQL Server Native Client 11.0",
|
||||
"ODBC Driver 00 for SQL Server");
|
||||
|
||||
foreach ($values as $value) {
|
||||
$connectionOptions['Driver']=$value;
|
||||
$expected = "Invalid value $value was specified for Driver option.";
|
||||
connectVerifyOutput($server, $connectionOptions, $expected);
|
||||
}
|
||||
|
||||
$values = array(123, false);
|
||||
|
||||
foreach ($values as $value) {
|
||||
$connectionOptions['Driver']=$value;
|
||||
$expected = "Invalid value type for option Driver was specified. String type was expected.";
|
||||
connectVerifyOutput($server, $connectionOptions, $expected);
|
||||
}
|
||||
}
|
||||
|
||||
function testEncryptedWithODBC($msodbcsqlMaj, $server, $connectionOptions)
|
||||
{
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
$connectionOptions['Driver']=$value;
|
||||
$connectionOptions['ColumnEncryption']='Enabled';
|
||||
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
|
||||
$expected = "The Always Encrypted feature requires Microsoft ODBC Driver 17 for SQL Server.";
|
||||
} else {
|
||||
$expected = "Invalid option ColumnEncryption was passed to sqlsrv_connect.";
|
||||
}
|
||||
|
||||
connectVerifyOutput($server, $connectionOptions, $expected);
|
||||
}
|
||||
|
||||
function testWrongODBC($msodbcsqlMaj, $server, $connectionOptions)
|
||||
{
|
||||
// TODO: this will change once ODBC 17 is officially released
|
||||
$value = "ODBC Driver 17 for SQL Server";
|
||||
if ($msodbcsqlMaj == 17 || $msodbcsqlMaj < 13) {
|
||||
$value = "ODBC Driver 13 for SQL Server";
|
||||
}
|
||||
|
||||
$connectionOptions['Driver']=$value;
|
||||
$expected = "The specified ODBC Driver is not found.";
|
||||
|
||||
connectVerifyOutput($server, $connectionOptions, $expected);
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Done
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
--TEST--
|
||||
Test new connection keyword ColumnEncryption
|
||||
--SKIPIF--
|
||||
<?php require('skipif.inc'); ?>
|
||||
<?php require('skipif_unix.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
sqlsrv_configure( 'WarningsReturnAsErrors', 0 );
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
--TEST--
|
||||
Fetch data from a prepopulated test table given a custom keystore provider
|
||||
--SKIPIF--
|
||||
<?php require('skipif_not_ksp.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
function verifyData($row, $num)
|
||||
{
|
||||
$c1 = $num * 10 + $num + 1;
|
||||
if (AE\isColEncrypted()) {
|
||||
$c2 = "Sample data $num for column 2";
|
||||
|
||||
$c3 = '';
|
||||
for ($i = 0; $i < 3; $i++) {
|
||||
// add to letter 'a'
|
||||
$c3 .= chr(97 + $num + $i);
|
||||
}
|
||||
$c4 = "2017-08-" . ($num + 10);
|
||||
|
||||
// need to trim the third value because it is a char(5)
|
||||
if ($row[0] !== $c1 || $row[1] !== $c2 || trim($row[2]) !== $c3 || $row[3] !== $c4) {
|
||||
echo "Expected the following\n";
|
||||
echo "c1=$c1\nc2=$c2\nc3=$c3\nc4=$c4\n";
|
||||
echo "But got these instead\n";
|
||||
echo "c1=" . $row[0] . "\nc2=" . $row[1] . "\nc3=" . $row[2] . "\nc4=" . $row[3] . "\n" ;
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ($row[0] !== $c1) {
|
||||
echo "Expected $c1 but got $row[0]\n";
|
||||
}
|
||||
// should expect binary values for the other columns
|
||||
for ($i = 1; $i <= 3; $i++) {
|
||||
if (ctype_print($row[1])) {
|
||||
print "Error: expected a binary array for column $i!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
sqlsrv_configure('WarningsReturnAsErrors', 1);
|
||||
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_ALL);
|
||||
|
||||
require_once('MsCommon.inc');
|
||||
$conn = AE\connect(array('ReturnDatesAsStrings'=>true));
|
||||
if ($conn !== false) {
|
||||
echo "Connected successfully with ColumnEncryption enabled.\n";
|
||||
}
|
||||
|
||||
$ksp_test_table = AE\KSP_TEST_TABLE;
|
||||
$tsql = "SELECT * FROM $ksp_test_table";
|
||||
$stmt = sqlsrv_prepare($conn, $tsql);
|
||||
if (!sqlsrv_execute($stmt)) {
|
||||
fatalError("Failed to fetch data.\n");
|
||||
}
|
||||
|
||||
// fetch data
|
||||
$id = 0;
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_NUMERIC)) {
|
||||
if (!verifyData($row, $id++)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sqlsrv_free_stmt($stmt);
|
||||
sqlsrv_close($conn);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
Connected successfully with ColumnEncryption enabled.
|
||||
Done
|
|
@ -1,52 +0,0 @@
|
|||
--TEST--
|
||||
Fetch encrypted data from a prepopulated test table given a custom keystore provider
|
||||
--SKIPIF--
|
||||
<?php require('skipif_not_ksp.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
sqlsrv_configure('WarningsReturnAsErrors', 1);
|
||||
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_ALL);
|
||||
|
||||
require_once('MsCommon.inc');
|
||||
$conn = AE\connect(array('ReturnDatesAsStrings'=>true));
|
||||
if ($conn === false) {
|
||||
fatalError("Failed to connect.\n");
|
||||
} else {
|
||||
echo "Connected successfully with ColumnEncryption disabled.\n";
|
||||
}
|
||||
|
||||
$ksp_test_table = AE\KSP_TEST_TABLE;
|
||||
$tsql = "SELECT * FROM $ksp_test_table";
|
||||
$stmt = sqlsrv_prepare($conn, $tsql);
|
||||
if (!sqlsrv_execute($stmt)) {
|
||||
fatalError("Failed to fetch data.\n");
|
||||
}
|
||||
|
||||
// fetch data
|
||||
while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_NUMERIC)) {
|
||||
// all columns should return binary data except the first column
|
||||
echo "c1=" . $row[0];
|
||||
echo "\tc2=" . bin2hex($row[1]);
|
||||
echo "\tc3=" . bin2hex($row[2]);
|
||||
echo "\tc4=" . bin2hex($row[3]);
|
||||
echo "\n" ;
|
||||
}
|
||||
|
||||
sqlsrv_free_stmt($stmt);
|
||||
sqlsrv_close($conn);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECTREGEX--
|
||||
Connected successfully with ColumnEncryption disabled.
|
||||
c1=1 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=12 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=23 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=34 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=45 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=56 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=67 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=78 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=89 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
c1=100 c2=[a-f0-9]+ c3=[a-f0-9]+ c4=[a-f0-9]+
|
||||
Done
|
|
@ -1,127 +0,0 @@
|
|||
--TEST--
|
||||
Connect using a custom keystore provider with some required inputs missing
|
||||
--SKIPIF--
|
||||
<?php require('skipif_not_ksp.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
function connect($server, $connectionInfo)
|
||||
{
|
||||
$conn = sqlsrv_connect($server, $connectionInfo);
|
||||
if ($conn === false) {
|
||||
echo "Failed to connect.\n";
|
||||
$errors = sqlsrv_errors();
|
||||
foreach ($errors[0] as $key => $error) {
|
||||
if(is_string($key)) {
|
||||
echo "[$key] => $error\n";
|
||||
}
|
||||
}
|
||||
echo "\n";
|
||||
} else {
|
||||
echo "Connected successfully with ColumnEncryption enabled.\n";
|
||||
}
|
||||
|
||||
return $conn;
|
||||
}
|
||||
|
||||
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_ALL);
|
||||
|
||||
require_once('MsHelper.inc');
|
||||
$ksp_path = AE\getKSPpath();
|
||||
$ksp_name = AE\KSP_NAME;
|
||||
$encrypt_key = AE\ENCRYPT_KEY;
|
||||
|
||||
echo "Connecting... with column encryption\n";
|
||||
$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd,
|
||||
"ColumnEncryption"=>"enabled");
|
||||
|
||||
connect($server, $connectionInfo);
|
||||
|
||||
echo "Connecting... with an invalid input to CEKeystoreProvider\n";
|
||||
$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd,
|
||||
"ColumnEncryption"=>"enabled",
|
||||
"CEKeystoreProvider"=>1);
|
||||
|
||||
connect($server, $connectionInfo);
|
||||
|
||||
echo "Connecting... with an empty path\n";
|
||||
$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd,
|
||||
"ColumnEncryption"=>"enabled",
|
||||
"CEKeystoreProvider"=>"",
|
||||
"CEKeystoreName"=>$ksp_name,
|
||||
"CEKeystoreEncryptKey"=>$encrypt_key);
|
||||
|
||||
connect($server, $connectionInfo);
|
||||
|
||||
echo "Connecting... without a name\n";
|
||||
$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd,
|
||||
"ColumnEncryption"=>"enabled",
|
||||
"CEKeystoreProvider"=>$ksp_path,
|
||||
"CEKeystoreEncryptKey"=>$encrypt_key);
|
||||
|
||||
connect($server, $connectionInfo);
|
||||
|
||||
echo "Connecting... with an empty name\n";
|
||||
$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd,
|
||||
"ColumnEncryption"=>"enabled",
|
||||
"CEKeystoreProvider"=>$ksp_path,
|
||||
"CEKeystoreName"=>"",
|
||||
"CEKeystoreEncryptKey"=>$encrypt_key);
|
||||
|
||||
connect($server, $connectionInfo);
|
||||
|
||||
echo "Connecting... without a key\n";
|
||||
$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd,
|
||||
"ColumnEncryption"=>"enabled",
|
||||
"CEKeystoreProvider"=>$ksp_path,
|
||||
"CEKeystoreName"=>$ksp_name);
|
||||
|
||||
connect($server, $connectionInfo);
|
||||
|
||||
echo "Connecting... with all required inputs\n";
|
||||
$connectionInfo = array("Database"=>$databaseName, "UID"=>$uid, "PWD"=>$pwd,
|
||||
"ColumnEncryption"=>"enabled",
|
||||
"CEKeystoreProvider"=>$ksp_path,
|
||||
"CEKeystoreName"=>$ksp_name,
|
||||
"CEKeystoreEncryptKey"=>$encrypt_key);
|
||||
|
||||
connect($server, $connectionInfo);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
Connecting... with column encryption
|
||||
Connected successfully with ColumnEncryption enabled.
|
||||
Connecting... with an invalid input to CEKeystoreProvider
|
||||
Failed to connect.
|
||||
[SQLSTATE] => IMSSP
|
||||
[code] => -33
|
||||
[message] => Invalid value type for option CEKeystoreProvider was specified. String type was expected.
|
||||
|
||||
Connecting... with an empty path
|
||||
Failed to connect.
|
||||
[SQLSTATE] => IMSSP
|
||||
[code] => -104
|
||||
[message] => Invalid value for loading a custom keystore provider.
|
||||
|
||||
Connecting... without a name
|
||||
Failed to connect.
|
||||
[SQLSTATE] => IMSSP
|
||||
[code] => -101
|
||||
[message] => The name of the custom keystore provider is missing.
|
||||
|
||||
Connecting... with an empty name
|
||||
Failed to connect.
|
||||
[SQLSTATE] => IMSSP
|
||||
[code] => -104
|
||||
[message] => Invalid value for loading a custom keystore provider.
|
||||
|
||||
Connecting... without a key
|
||||
Failed to connect.
|
||||
[SQLSTATE] => IMSSP
|
||||
[code] => -103
|
||||
[message] => The encryption key for the custom keystore provider is missing.
|
||||
|
||||
Connecting... with all required inputs
|
||||
Connected successfully with ColumnEncryption enabled.
|
||||
Done
|
|
@ -1,213 +0,0 @@
|
|||
--TEST--
|
||||
Test simple insert, fetch and update with ColumnEncryption enabled and a custome keystore provider
|
||||
--SKIPIF--
|
||||
<?php require('skipif_not_ksp.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
function createPatientsTable()
|
||||
{
|
||||
global $conn;
|
||||
$tableName = 'Patients';
|
||||
|
||||
$columns = array(new AE\ColumnMeta('int', 'PatientId', 'IDENTITY(1,1) NOT NULL'),
|
||||
new AE\ColumnMeta('char(11)', 'SSN'),
|
||||
new AE\ColumnMeta('nvarchar(50)', 'FirstName'),
|
||||
new AE\ColumnMeta('nvarchar(50)', 'LastName'),
|
||||
new AE\ColumnMeta('date', 'BirthDate'));
|
||||
$stmt = AE\createTable($conn, $tableName, $columns);
|
||||
if (!$stmt) {
|
||||
fatalError("Failed to create test table!\n");
|
||||
}
|
||||
|
||||
return $tableName;
|
||||
}
|
||||
|
||||
function insertData($ssn, $fname, $lname, $date)
|
||||
{
|
||||
global $conn, $tableName;
|
||||
$params = array(
|
||||
array($ssn, null, null, SQLSRV_SQLTYPE_CHAR(11)), array($fname, null, null, SQLSRV_SQLTYPE_NVARCHAR(50)), array($lname, null, null, SQLSRV_SQLTYPE_NVARCHAR(50)), array($date, null, null, SQLSRV_SQLTYPE_DATE)
|
||||
);
|
||||
|
||||
$tsql = "INSERT INTO $tableName (SSN, FirstName, LastName, BirthDate) VALUES (?, ?, ?, ?)";
|
||||
if (! $stmt = sqlsrv_prepare($conn, $tsql, $params)) {
|
||||
fatalError("Failed to prepare statement.\n");
|
||||
}
|
||||
|
||||
if (! sqlsrv_execute($stmt)) {
|
||||
fatalError("Failed to insert a new record.\n");
|
||||
}
|
||||
}
|
||||
|
||||
function selectData()
|
||||
{
|
||||
global $conn, $tableName;
|
||||
$stmt = sqlsrv_query($conn, "SELECT * FROM $tableName");
|
||||
while ($obj = sqlsrv_fetch_object($stmt)) {
|
||||
echo $obj->PatientId . "\n";
|
||||
echo $obj->SSN . "\n";
|
||||
echo $obj->FirstName . "\n";
|
||||
echo $obj->LastName . "\n";
|
||||
echo $obj->BirthDate . "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
function selectDataBuffered()
|
||||
{
|
||||
global $conn, $tableName;
|
||||
|
||||
$stmt = sqlsrv_query($conn, "SELECT * FROM $tableName", array(), array("Scrollable"=>"buffered"));
|
||||
|
||||
$row_count = sqlsrv_num_rows($stmt);
|
||||
echo "\nRow count for result set is $row_count\n";
|
||||
|
||||
echo "First record=>\t";
|
||||
$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_FIRST);
|
||||
$SSN = sqlsrv_get_field($stmt, 1);
|
||||
echo "SSN = $SSN\n";
|
||||
|
||||
echo "Next record=>\t";
|
||||
$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_NEXT);
|
||||
$BirthDate = sqlsrv_get_field($stmt, 4);
|
||||
echo "BirthDate = $BirthDate\n";
|
||||
|
||||
echo "Last record=>\t";
|
||||
$row = sqlsrv_fetch($stmt, SQLSRV_SCROLL_LAST);
|
||||
$LastName = sqlsrv_get_field($stmt, 3);
|
||||
echo "LastName = $LastName\n";
|
||||
}
|
||||
|
||||
sqlsrv_configure('WarningsReturnAsErrors', 1);
|
||||
sqlsrv_configure('LogSeverity', SQLSRV_LOG_SEVERITY_ALL);
|
||||
|
||||
require_once('MsHelper.inc');
|
||||
$conn = AE\connect(array('ReturnDatesAsStrings'=>true));
|
||||
if ($conn === false) {
|
||||
fatalError( "Failed to connect.\n");
|
||||
} else {
|
||||
echo "Connected successfully with ColumnEncryption enabled.\n";
|
||||
}
|
||||
|
||||
$tableName = createPatientsTable();
|
||||
|
||||
insertData('748-68-0245', 'Jeannette', 'McDonald', '2002-11-28');
|
||||
insertData('795-73-9838', 'John', 'Doe', '2001-05-29');
|
||||
insertData('456-12-5486', 'Jonathan', 'Wong', '1999-12-20');
|
||||
insertData('156-45-5486', 'Marianne', 'Smith', '1997-03-04');
|
||||
|
||||
selectData();
|
||||
|
||||
///////////////////////////////////////////
|
||||
echo "Update Patient Jonathan Wong...\n";
|
||||
$params = array(array('1999-12-31', null, null, SQLSRV_SQLTYPE_DATE),
|
||||
array('Chang', null, null, SQLSRV_SQLTYPE_NVARCHAR(50)),
|
||||
array('456-12-5486', null, null, SQLSRV_SQLTYPE_CHAR(11)));
|
||||
|
||||
$tsql = "UPDATE $tableName SET BirthDate = ?, LastName = ? WHERE SSN = ?";
|
||||
$stmt = sqlsrv_query($conn, $tsql, $params);
|
||||
|
||||
if (!$stmt) {
|
||||
fatalError("Failed to update record\n");
|
||||
}
|
||||
|
||||
echo "Update his birthdate too...\n";
|
||||
$params = array(array('456-12-5486', null, null, SQLSRV_SQLTYPE_CHAR(11)));
|
||||
$tsql = "SELECT SSN, FirstName, LastName, BirthDate FROM $tableName WHERE SSN = ?";
|
||||
$stmt = sqlsrv_query($conn, $tsql, $params);
|
||||
if (!$stmt) {
|
||||
fatalError("Failed to select with a WHERE clause\n");
|
||||
} else {
|
||||
$obj = sqlsrv_fetch_object($stmt);
|
||||
echo "BirthDate updated for $obj->FirstName:\n";
|
||||
echo $obj->SSN . "\n";
|
||||
echo $obj->FirstName . "\n";
|
||||
echo $obj->LastName . "\n";
|
||||
echo $obj->BirthDate . "\n\n";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
$procName = '#phpAEProc1';
|
||||
$spArgs = "@p1 INT, @p2 DATE OUTPUT";
|
||||
$spCode = "SET @p2 = (SELECT [BirthDate] FROM $tableName WHERE [PatientId] = @p1)";
|
||||
$stmt = sqlsrv_query($conn, "CREATE PROC [$procName] ($spArgs) AS BEGIN $spCode END");
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
$callResult = '1900-01-01';
|
||||
//when binding parameter using sqlsrv_query in a column encryption enabled connection, need to provide the sql_type in all parameters
|
||||
$params = array(array(1, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_INT),
|
||||
array(&$callResult, SQLSRV_PARAM_OUT, null, SQLSRV_SQLTYPE_DATE));
|
||||
$callArgs = "?, ?";
|
||||
$stmt = sqlsrv_query($conn, "{ CALL [$procName] ($callArgs)}", $params);
|
||||
if (!$stmt) {
|
||||
print_r(sqlsrv_errors());
|
||||
} else {
|
||||
echo "BirthDate for the first record is: $callResult\n";
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
$procName = '#phpAEProc2';
|
||||
$spArgs = "@p1 INT, @p2 CHAR(11) OUTPUT";
|
||||
$spCode = "SET @p2 = (SELECT [SSN] FROM $tableName WHERE [PatientId] = @p1)";
|
||||
$stmt = sqlsrv_query($conn, "CREATE PROC [$procName] ($spArgs) AS BEGIN $spCode END");
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
$callResult = '000-00-0000';
|
||||
// when binding parameter using sqlsrv_query in a column encryption enabled connection,
|
||||
// need to provide the sql_type in all parameters
|
||||
$params = array(array(1, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_INT),
|
||||
array(&$callResult, SQLSRV_PARAM_OUT, null, SQLSRV_SQLTYPE_CHAR(11)));
|
||||
$callArgs = "?, ?";
|
||||
$stmt = sqlsrv_query($conn, "{ CALL [$procName] ($callArgs)}", $params);
|
||||
if (!$stmt) {
|
||||
print_r(sqlsrv_errors());
|
||||
} else {
|
||||
echo "SSN for the first record is: $callResult\n";
|
||||
}
|
||||
|
||||
selectDataBuffered();
|
||||
|
||||
echo "\nDone\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
Connected successfully with ColumnEncryption enabled.
|
||||
1
|
||||
748-68-0245
|
||||
Jeannette
|
||||
McDonald
|
||||
2002-11-28
|
||||
|
||||
2
|
||||
795-73-9838
|
||||
John
|
||||
Doe
|
||||
2001-05-29
|
||||
|
||||
3
|
||||
456-12-5486
|
||||
Jonathan
|
||||
Wong
|
||||
1999-12-20
|
||||
|
||||
4
|
||||
156-45-5486
|
||||
Marianne
|
||||
Smith
|
||||
1997-03-04
|
||||
|
||||
Update Patient Jonathan Wong...
|
||||
Update his birthdate too...
|
||||
BirthDate updated for Jonathan:
|
||||
456-12-5486
|
||||
Jonathan
|
||||
Chang
|
||||
1999-12-31
|
||||
|
||||
BirthDate for the first record is: 2002-11-28
|
||||
SSN for the first record is: 748-68-0245
|
||||
|
||||
Row count for result set is 4
|
||||
First record=> SSN = 748-68-0245
|
||||
Next record=> BirthDate = 2001-05-29
|
||||
Last record=> LastName = Smith
|
||||
|
||||
Done
|
Loading…
Reference in a new issue