add insertion tests for Always Encrypted; add common functions in MsCommon.inc for refactoring in the future

This commit is contained in:
v-kaywon 2017-09-13 17:46:44 -07:00
parent 964ec5f087
commit bef0e3eab7
31 changed files with 3649 additions and 2 deletions

View file

@ -0,0 +1,72 @@
<?php
// exact numerics
$bigint_params = array( 2147483648, -922337203685479936, 922337203685479936, -2147583649, 461168601735364608, -461168601735364608 );
$int_params = array( 32768, -2147483647, 2147483647, -32769, 1073725440, -1073725440 );
$smallint_params = array( 256, -32767, 32767, -1, 16256, -16256 );
$tinyint_params = array( 128, 0, 255, 96, 64, 162 );
$decimal_params = array( 21474.83648, -9223372036854.80000, 9223372036854.80000, -21475.83649, -4611686017353.64608, -4611686017353.64608 );
$numeric_params = array( 0.32768, -21474.83647, 21474.83647, -0.32769, 10737.25440, -10737.25440 );
$money_params = array( 214748.3648, -92233720368548.0000, 92233720368548.0000, -214758.3649, 46116860173536.608, -46116860173536.608 );
$smallmoney_params = array( 0, -214748.3647, 214748.3647, 161061.2736, 107374.1824, -107374.1824 );
$bit_params = array( 0, 1, 0, 1, 0, 1 );
// approximate numerics
$float_params = array( 21474.83648, -9223372036.8548, 9223372036.8548, -21475, 4611686017, -4611686017 );
$real_params = array( 0, -2147.483, 2147.483, 1610, 1073, -1073 );
// date and time
$date_params = array( '1900-01-01', '0001-01-01', '9999-12-31', '5000-07-15', '2500-04-08', '7500-10-23' );
$datetime2_params = array( '1900-01-01 00:00:00', '0001-01-01 00:00:00', '9999-12-31 23:59:59.9999999', '5000-07-15 12:30:30.5555', '2500-04-08 06:15:15.33', '7500-10-23 18:45:45.888888' );
$datetime_params = array( '1900-01-01 00:00:00', '1753-01-01 00:00:00', '9999-12-31 23:59:59.997', '5000-07-15 12:30:30.5', '2500-04-08 06:15:15.33', '7500-10-23 18:45:45.888' );
$datetimeoffset_params = array( '1900-01-01 00:00:00 +01:00', '0001-01-01 00:00:00 -14:00', '9999-12-31 23:59:59.9999999 +14:00', '5000-07-15 12:30:30.55 -03:00', '2500-04-08 06:15:15.3333 -07:00', '7500-10-23 18:45:45.888888 +07:00' );
$smalldatetime_params = array( '1900-01-01 00:00:00', '1900-01-01 00:00:00', '2079-06-05 23:59:00', '1990-07-15 12:30:00', '1945-04-08 06:15:00', '2000-10-23 18:45:00' );
$time_params = array( '00:00:00', '00:00:00.0000000', '23:59:59.9999999', '12:30:30.5555', '06:15:15.33', '18:45:45.888888' );
// character strings
$char_params = array( 'Fixed', '-leng', 'th, n', 'on-Un', 'icode', 'strin' );
$varchar_params = array( 'This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.',
'Use varchar(max) when the sizes of the column data entries vary considerably, and the size might exceed 8,000 bytes.',
'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.',
'This can create an implicit limit to the number of non-null varchar(max) or nvarchar(max) columns that can be created in a table.',
'No special error is provided when the table is created (beyond the usual warning that the maximum row size exceeds the allowed maximum of 8060 bytes) or at the time of data insertion.',
'This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.' );
// unicode character strings
$nchar_params = array( 'Fixed', '-leng', 'th Un', 'icode', 'strin', 'g dat' );
$nvarchar_params = array( 'max indicates that the maximum storage size is 2^31-1 bytes (2 GB).',
'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).',
'Otherwise, the implicit conversion will result in a Unicode large-value (max).',
'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.',
'This can create an implicit limit to the number of non-null varchar(max) or nvarchar(max) columns that can be created in a table.',
'No special error is provided when the table is created (beyond the usual warning that the maximum row size exceeds the allowed maximum of 8060 bytes) or at the time of data insertion.' );
// binary strings
$binary_params = array( 'Fixed', '-leng', 'th, n', 'on-Un', 'icode', 'strin' );
$varbinary_params = array( 'Variable-length, non-', 'Unicode string data. n', 'defines the string length', 'and can be a value from 1', 'through 8,000.', 'The storage size is the' );
$varbinarymax_params = array( 'max indicates that the maximum storage size is 2^31-1 bytes (2 GB)',
'Use varchar(max) when the sizes of the column data entries vary considerably, and the size might exceed 8,000 bytes.',
'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.',
'This can create an implicit limit to the number of non-null varchar(max) or nvarchar(max) columns that can be created in a table.',
'No special error is provided when the table is created (beyond the usual warning that the maximum row size exceeds the allowed maximum of 8060 bytes) or at the time of data insertion.',
'This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.' );
// Array containing all PDO::PARAM_ types to pass into a PDOstatement::bindParam
$pdoParamTypes = array(
'PDO::PARAM_BOOL',
'PDO::PARAM_NULL',
'PDO::PARAM_INT',
'PDO::PARAM_STR',
'PDO::PARAM_LOB'
);
// Checks if the current error is the incompatible types error
// if so, state which sql type is incompatible with which data type
function is_incompatible_types_error( $stmt, $dataType, $pdoParamType ) {
if ( $stmt->errorInfo()[0] == "22018" )
echo "PDO param type $pdoParamType is incompatible with encrypted $dataType\n";
else
var_dump( $stmt->errorInfo() );
}
?>

View file

@ -20,11 +20,12 @@ function IsAEQualified($conn)
$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 < 13 || explode('.', $server_ver)[0] < 13)
return false;
return true;
}
// TO BE DELETED
function connect($options=array())
{
try
@ -52,6 +53,374 @@ function connect($options=array())
}
}
/**
* Connect to the database specified in MsSetup.inc; Column Encryption keywords automatically added when $keystore is not none
* @param string $keywords : string to append to the dsn string in PDO::_construct
* @param array $options : attributes to pass to PDO::_construct
* @param bool $disableCE : flag for disabling column encryption even when keystore is NOT none
* for testing fetching encrypted data when connection column encryption is off
* @return PDO connection object
*/
function ae_connect( $keywords='', $options=array(), $disableCE = false )
{
try
{
// simply use $databaseName from MsSetup.inc to facilitate testing in Azure,
// which does not support switching databases
require 'MsSetup.inc';
$dsn = "sqlsrv:Server=$server;database=$databaseName;ConnectionPooling=false;";
if ( $keystore != "none" && !$disableCE )
{
$dsn .= "ColumnEncryption=Enabled;";
}
if ( $keystore == "ksp" && !$disableCE )
{
require( 'AE_Ksp.inc' );
$ksp_path = getKSPPath();
$dsn .= "CEKeystoreProvider=$ksp_path;CEKeystoreName=$ksp_name;CEKeystoreEncryptKey=$encrypt_key;";
}
if ( $keywords )
{
$dsn .= $keywords;
}
$conn = new PDO( $dsn, $uid, $pwd, $options );
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
return $conn;
}
catch( PDOException $e )
{
var_dump( $e );
exit;
}
catch(Exception $e)
{
var_dump( $e );
exit;
}
}
/**
* @return string CEK name depending on the connection keywords
*/
function getCekName()
{
require 'MsSetup.inc';
$cekName = '';
switch ( $keystore ) {
case "none":
$cekName = '';
break;
case "win":
$cekName = 'AEColumnKey';
break;
case "ksp":
$cekName = 'CustomCEK';
break;
case "akv":
$cekName = 'AKVColumnKey';
break;
}
return $cekName;
}
/**
* class for encapsulating column metadata needed for creating a table
*/
class columnMeta {
public $colName;
public $dataType; //a string that includes the size of the type if necessary (e.g., decimal(10,5))
public $encType; //randomized or deterministic; default is deterministic
public $options; //a string that is empty by default (e.g. NOT NULL Identity (1,1) )
function __construct( $dataType, $colName = null, $options = null, $encType = "deterministic" )
{
if ( !$colName )
{
$this->colName = get_default_colname( $dataType );
}
else
{
$this->colName = $colName;
}
$this->dataType = $dataType;
$this->encType = $encType;
$this->options = $options;
}
/**
* @return string column definition for creating a table
*/
function getColDef()
{
require 'MsSetup.inc';
$append = " ";
if ( $keystore != "none" && stripos( $this->options, "identity" ) === false )
{
$cekName = getCekName();
$encDet = "ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = $cekName) ";
$encRand = "ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = $cekName) ";
if ( stripos( $this->dataType, "char" ) !== false )
$append .= "COLLATE Latin1_General_BIN2 ";
if ( $this->encType == "deterministic" )
$append .= $encDet;
else
$append .= $encRand;
}
$append .= $this->options;
$colDef = "[" . $this->colName . "] " . $this->dataType . $append;
return $colDef;
}
}
/**
* @return string default column name when a name is not provided in the columnMeta class
*/
function get_default_colname( $dataType )
{
$colName = "c_" . str_replace( ",", "_", str_replace( "(", "_", $dataType ));
$colName = rtrim( $colName, ")" );
return $colName;
}
/**
* Create a table
* @param object $conn : PDO connection object
* @param string $tbname : name of the table to be created
* @param array $columnMeta : array of columnMeta objects, which contain metadata for one column
*/
function create_table( $conn, $tbname, $columnMeta )
{
try
{
$dropSql = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'" . $tbname . "') AND type in (N'U')) DROP TABLE $tbname";
$conn->exec( $dropSql );
$colDef = "";
foreach ( $columnMeta as $meta )
{
$colDef = $colDef . $meta->getColDef() . ", ";
}
$colDef = rtrim( $colDef, ", " );
$createSql = "CREATE TABLE $tbname ( $colDef )";
$conn->exec( $createSql );
}
catch ( Exception $e )
{
var_dump( $e );
exit;
}
}
/**
* class for encapsulating optional parameters for PDOStatement::bindParam
*/
class bindParamOption {
public $index; //1-based index of the parameter
public $pdoType; //PDO_PARAM_ type specified for PDOStatement::bindParam
public $length; //length specified for PDOStatement::bindParam
public $options; //options specified for PDOStatement::bindParam
function __construct( $index, $pdoType = null, $length = null, $options = null )
{
$this->index = $index;
$this->pdoType = $pdoType;
$this->length = $length;
$this->options = $options;
}
/**
* @param object $stmt : PDO Statement object
* @param mix $var : variable to bind to the SQL statement parameter
*/
function bindWithOp( $stmt, $var )
{
$stmt->bindParam( $this->index, $var, constant( $this->pdoType ), $this->length, $this->options );
}
}
/**
* Create a row into a table
* @param object $conn : PDO connection object
* @param string $tbname : name of the table to be created
* @param array $inputs : an associative array column name and its value
* @param bool $r : if the row was successfully inserted
* $param string $api : PDO_SQLSRV API used for executing the insert query
* accepted values: "exec", "query", "prepare", "prepareBindParam"
* @param array $paramOption : an array of bindParamOptions. Should only be provided if $api is "perpareWithParamOp", if provided, has to be in the same order as $inputs
* @return object PDOStatement object of the insert statement
*/
function insert_row( $conn, $tbname, $inputs, &$r = null, $api = "query", $paramOption = array() )
{
try
{
require 'MsSetup.inc';
$stmt = null;
if ( $keystore == "none" && $api != "prepareBindParam" )
{
$insertSql = get_insertSql_complete( $tbname, $inputs );
switch ( $api ) {
case "exec":
$conn->exec( $insertSql );
break;
case "query":
$stmt = $conn->query( $insertSql );
break;
case "prepare":
$stmt = $conn->prepare( $insertSql );
$r = $stmt->execute();
break;
}
}
else
{
// if AE is on, must bind param
$insertSql = get_insertSql_placeholders( $tbname, $inputs );
$stmt = $conn->prepare( $insertSql );
if ( empty( $paramOption ))
{
$i = 1;
foreach( $inputs as $key => $value )
{
$stmt->bindParam( $i, $inputs[$key] );
$i++;
}
}
else
{
$i = 1;
foreach( $inputs as $key => $value )
{
$noparam = true;
foreach( $paramOption as $op )
{
if ( $op->index == $i )
{
$op->bindWithOp( $stmt, $inputs[$key] );
$noparam = false;
$i++;
break;
}
}
if ( $noparam )
{
$stmt->bindParam( $i, $inputs[$key] );
$i++;
}
}
}
$r = $stmt->execute();
}
return $stmt;
}
catch ( Exception $e )
{
var_dump( $e );
exit;
}
}
/**
* @param string $tbname : name of the table for an insert sql
* @param array $input : associative array containing a key value pair of column name and data to put into an insert sql string
* @return string a complete insert sql string
*/
function get_insertSql_complete( $tbname, $inputs )
{
$colStr = "INSERT INTO $tbname (";
$valStr = "VALUES (";
foreach( $inputs as $key => $value )
{
$colStr .= $key . ", ";
if ( is_string( $value ))
$valStr .= "'" . $value . "', ";
else
$valStr .= $value . ", ";
}
$colStr = rtrim( $colStr, ", " ) . ") ";
$valStr = rtrim( $valStr, ", " ) . ") ";
$insertSql = $colStr . $valStr;
return $insertSql;
}
/**
* @param string $tbname : name of the table for an insert sql
* @param array $input : associative array containing a key value pair of column name and data to put into an insert sql string
* @return string an insert sql string with "?" placeholders for all values
*/
function get_insertSql_placeholders( $tbname, $inputs )
{
$colStr = "INSERT INTO $tbname (";
$valStr = "VALUES (";
foreach( $inputs as $key => $value )
{
$colStr .= $key . ", ";
}
$colStr = rtrim( $colStr, ", " ) . ") ";
$valStr .= get_seq_placeholders( count( $inputs )) . ") ";
$insertSql = $colStr . $valStr;
return $insertSql;
}
/**
* @param string $spname : name of the stored procedure
* @param int $num : number of parameters needed for the stored procedure
* @return string a call stored procedure sql string with "?" placeholders for all parameters
*/
function get_callProcSql_placeholders( $spname, $num )
{
$callStr = "{CALL $spname (";
$callStr .= get_seq_placeholders( $num ) . ")} ";
return $callStr;
}
/**
* @param int $num : number of placeholders needed
* @return string a string containing $num number of repeated "?" placeholders delimited by ", "
*/
function get_seq_placeholders( $num )
{
$placeholderStr = str_repeat( "?, ", $num );
$placeholderStr = rtrim( $placeholderStr, ", " );
return $placeholderStr;
}
/**
* Fetch all rows and all columns given a table name, and print them
* @param object $conn : PDO connection object
* @param string $tbname : name of the table to fetch from
*/
function fetch_all( $conn, $tbname ) {
try
{
$sql = "SELECT * FROM $tbname";
$stmt = $conn->query( $sql );
while ( $row = $stmt->fetch( PDO::FETCH_ASSOC ))
{
foreach ( $row as $key => $value )
{
print ( "$key: $value\n" );
}
}
}
catch ( Exception $e )
{
var_dump( $e );
exit;
}
}
// Create and insert
function create_and_insert_table1( $conn )
{
@ -1547,4 +1916,6 @@ function PhpVersionComponents( &$major, &$minor, &$sub )
$minor = strtok( "." );
$sub = strtok( "." );
}
?>

View file

@ -0,0 +1,78 @@
--TEST--
Test for inserting and retrieving encrypted datetime types data
Binding parameters in PDOstatement::execute
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "date", "datetime", "datetime2", "smalldatetime", "time", "datetimeoffset" );
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType:\n";
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r );
if ( $r === false ) {
is_incompatible_types_error( $stmt, $dataType, "default type" );
}
else {
echo "****Encrypted default type is compatible with encrypted $dataType****\n";
fetch_all( $conn, $tbname );
}
DropTable( $conn, $tbname );
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
?>
--EXPECT--
Testing date:
****Encrypted default type is compatible with encrypted date****
c_det: 0001-01-01
c_rand: 9999-12-31
Testing datetime:
****Encrypted default type 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:
****Encrypted default type is compatible with encrypted datetime2****
c_det: 0001-01-01 00:00:00.0000000
c_rand: 9999-12-31 23:59:59.9999999
Testing smalldatetime:
****Encrypted default type is compatible with encrypted smalldatetime****
c_det: 1900-01-01 00:00:00
c_rand: 2079-06-05 23:59:00
Testing time:
****Encrypted default type is compatible with encrypted time****
c_det: 00:00:00.0000000
c_rand: 23:59:59.9999999
Testing datetimeoffset:
****Encrypted default type 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

View file

@ -0,0 +1,86 @@
--TEST--
Test for inserting and retrieving encrypted numeric types data
Binding parameters in PDOstatement::execute
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "smallmoney", "money" );
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType:\n";
$success = true;
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r );
if ( $keystore == "none" )
{
if ( $r === false )
{
echo "Default type should be compatible with $dataType.\n";
$success = false;
}
else
{
$sql = "SELECT * FROM $tbname";
$stmt = $conn->query( $sql );
$row = $stmt->fetch( PDO::FETCH_ASSOC );
if ( $row["c_det"] != $inputValues[0] || $row["c_rand"] != $inputValues[1] )
{
echo "Incorrect output retrieved for datatype $dataType.\n";
$success = false;
}
}
}
else
{
if ( $r === false )
{
if ( $stmt->errorInfo()[0] != "22018" )
{
echo "Incorrect error returned.\n";
$success = false;
}
}
else
{
echo "$dataType is not compatible with any type.\n";
$success = false;
}
}
if ( $success )
echo "Test successfully.\n";
DropTable( $conn, $tbname );
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
?>
--EXPECT--
Testing smallmoney:
Test successfully.
Testing money:
Test successfully.

View file

@ -0,0 +1,93 @@
--TEST--
Test for inserting and retrieving encrypted numeric types data
Binding parameters in PDOstatement::execute
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "bit", "tinyint", "smallint", "int", "bigint", "decimal(18,5)", "numeric(10,5)", "float", "real" );
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType:\n";
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r );
if ( $r === false ) {
is_incompatible_types_error( $stmt, $dataType, "default type" );
}
else {
echo "****Encrypted default type is compatible with encrypted $dataType****\n";
fetch_all( $conn, $tbname );
}
DropTable( $conn, $tbname );
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
?>
--EXPECT--
Testing bit:
****Encrypted default type is compatible with encrypted bit****
c_det: 1
c_rand: 0
Testing tinyint:
****Encrypted default type is compatible with encrypted tinyint****
c_det: 0
c_rand: 255
Testing smallint:
****Encrypted default type is compatible with encrypted smallint****
c_det: -32767
c_rand: 32767
Testing int:
****Encrypted default type is compatible with encrypted int****
c_det: -2147483647
c_rand: 2147483647
Testing bigint:
****Encrypted default type is compatible with encrypted bigint****
c_det: -922337203685479936
c_rand: 922337203685479936
Testing decimal(18,5):
****Encrypted default type is compatible with encrypted decimal(18,5)****
c_det: -9223372036854.80000
c_rand: 9223372036854.80000
Testing numeric(10,5):
****Encrypted default type is compatible with encrypted numeric(10,5)****
c_det: -21474.83647
c_rand: 21474.83647
Testing float:
****Encrypted default type is compatible with encrypted float****
c_det: -9223372036.8547993
c_rand: 9223372036.8547993
Testing real:
****Encrypted default type is compatible with encrypted real****
c_det: -2147.4829
c_rand: 2147.4829

View file

@ -0,0 +1,157 @@
--TEST--
Test for inserting and retrieving encrypted datetime types data
Use PDOstatement::bindParam with all PDO::PARAM_ types
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "date", "datetime", "datetime2", "smalldatetime", "time", "datetimeoffset" );
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType:\n";
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// prepare statement for inserting into table
$insertSql = get_insert_sql( $tbname, 3 );
foreach ( $pdoParamTypes as $pdoParamType ) {
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r, "prepareBindParam", array( new bindParamOption( 1, $pdoParamType ), new bindParamOption( 2, $pdoParamType )));
if ( $r === false )
{
is_incompatible_types_error( $stmt, $dataType, $pdoParamType );
}
else {
echo "****PDO param type $pdoParamType is compatible with encrypted $dataType****\n";
fetch_all( $conn, $tbname );
}
$conn->query( "TRUNCATE TABLE $tbname" );
}
DropTable( $conn, $tbname );
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
?>
--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
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
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

View file

@ -0,0 +1,93 @@
--TEST--
Test for inserting and retrieving encrypted numeric types data
Use PDOstatement::bindParam with all PDO::PARAM_ types
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "smallmoney", "money" );
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType:\n";
$success = true;
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// test each PDO::PARAM_ type
foreach ( $pdoParamTypes as $pdoParamType ) {
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r, "prepareBindParam", array( new bindParamOption( 1, $pdoParamType ), new bindParamOption( 2, $pdoParamType )));
if ( $keystore == "none" )
{
if ( $r === false )
{
echo "$pdoParamType should be compatible with $dataType.\n";
$success = false;
}
else
{
$sql = "SELECT * FROM $tbname";
$stmt = $conn->query( $sql );
$row = $stmt->fetch( PDO::FETCH_ASSOC );
if ( ( $row["c_det"] != $inputValues[0] || $row["c_rand"] != $inputValues[1] ) && $pdoParamType != "PDO::PARAM_NULL" )
{
echo "Incorrect output retrieved for datatype $dataType.\n";
var_dump( $inputValues );
var_dump( $row );
$success = false;
}
}
}
else
{
if ( $r === false )
{
if ( $stmt->errorInfo()[0] != "22018" )
{
echo "Incorrect error returned.\n";
$success = false;
}
}
else
{
echo "$dataType is not compatible with any type.\n";
$success = false;
}
}
$conn->query( "TRUNCATE TABLE $tbname" );
}
if ( $success )
echo "Test successfully.\n";
DropTable( $conn, $tbname );
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
?>
--EXPECT--
Testing smallmoney:
Test successfully.
Testing money:
Test successfully.

View file

@ -0,0 +1,189 @@
--TEST--
Test for inserting and retrieving encrypted numeric types data
Use PDOstatement::bindParam with all PDO::PARAM_ types
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "bit", "tinyint", "smallint", "int", "decimal(18,5)", "numeric(10,5)", "float", "real" );
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType:\n";
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// test each PDO::PARAM_ type
foreach ( $pdoParamTypes as $pdoParamType ) {
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r, "prepareBindParam", array( new bindParamOption( 1, $pdoParamType ), new bindParamOption( 2, $pdoParamType )));
if ( $r === false )
{
is_incompatible_types_error( $stmt, $dataType, $pdoParamType );
}
else {
echo "****PDO param type $pdoParamType is compatible with encrypted $dataType****\n";
fetch_all( $conn, $tbname );
}
$conn->query( "TRUNCATE TABLE $tbname" );
}
DropTable( $conn, $tbname );
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
?>
--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
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
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
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
Testing decimal(18,5):
****PDO param type PDO::PARAM_BOOL is compatible with encrypted decimal(18,5)****
c_det: -9223372036854.80078
c_rand: 9223372036854.80078
****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.80078
c_rand: 9223372036854.80078
****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.80078
c_rand: 9223372036854.80078
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 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

View file

@ -0,0 +1,123 @@
--TEST--
Test for inserting and retrieving encrypted string types data
Use PDOstatement::bindParam with all PDO::PARAM_ types
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "char(5)", "varchar(max)", "nchar(5)", "nvarchar(max)" );
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType:\n";
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// prepare statement for inserting into table
$insertSql = get_insert_sql( $tbname, 3 );
foreach ( $pdoParamTypes as $pdoParamType ) {
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r, "prepareBindParam", array( new bindParamOption( 1, $pdoParamType ), new bindParamOption( 2, $pdoParamType )));
if ( $r === false )
{
is_incompatible_types_error( $stmt, $dataType, $pdoParamType );
}
else {
echo "****PDO param type $pdoParamType is compatible with encrypted $dataType****\n";
fetch_all( $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).

View file

@ -0,0 +1,85 @@
--TEST--
Test for inserting encrypted data and retrieving both encrypted and decrypted data
Retrieving SQL query contains encrypted filter
--SKIPIF--
--FILE--
<?php
include 'MsSetup.inc';
include 'MsCommon.inc';
include 'AEData.inc';
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
// Create the table
$tbname = 'Patients';
$colMetaArr = array( new columnMeta( "int", "PatientId", "IDENTITY(1,1)" ),
new columnMeta( "char(11)", "SSN"),
new columnMeta( "nvarchar(50)", "FirstName", "NULL" ),
new columnMeta( "nvarchar(50)", "LastName", "NULL"),
new columnMeta( "date", "BirthDate", null, "randomized" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$SSN = "795-73-9838";
$inputs = array( "SSN" => $SSN, "FirstName" => "Catherine", "LastName" => "Abel", "BirthDate" => "1996-10-19" );
$stmt = insert_row( $conn, $tbname, $inputs );
echo "Retrieving plaintext data:\n";
$selectSql = "SELECT SSN, FirstName, LastName, BirthDate FROM $tbname WHERE SSN = ?";
$stmt = $conn->prepare( $selectSql );
$stmt->bindParam( 1, $SSN );
$stmt->execute();
$decrypted_row = $stmt->fetch( PDO::FETCH_ASSOC );
foreach ( $decrypted_row as $key => $value )
{
print "$key: $value\n";
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
// for AE only
echo "\nRetrieving ciphertext data:\n";
if ( $keystore != "none" )
{
try
{
$conn = ae_connect( null, null, true );
$selectSql = "SELECT SSN, FirstName, LastName, BirthDate FROM $tbname";
$stmt = $conn->query( $selectSql );
$encrypted_row = $stmt->fetch( PDO::FETCH_ASSOC );
foreach ( $encrypted_row as $key => $value )
{
if ( !ctype_print( $value ))
print "Binary array returned for $key\n";
}
//DropTable( $conn, $tbname );
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
}
?>
--EXPECT--
Retrieving plaintext data:
SSN: 795-73-9838
FirstName: Catherine
LastName: Abel
BirthDate: 1996-10-19
Retrieving ciphertext data:
Binary array returned for SSN
Binary array returned for FirstName
Binary array returned for LastName
Binary array returned for BirthDate

View file

@ -0,0 +1,100 @@
--TEST--
Test for inserting encrypted fixed size types data and retrieve both encrypted and decrypted data
--SKIPIF--
--FILE--
<?php
include 'MsSetup.inc';
include 'MsCommon.inc';
include 'AEData.inc';
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
// Create the table
$tbname = 'FixedSizeAnalysis';
$colMetaArr = array( new columnMeta( "tinyint", "TinyIntData" ),
new columnMeta( "smallint", "SmallIntData" ),
new columnMeta( "int", "IntData" ),
new columnMeta( "bigint", "BigIntData" ),
new columnMeta( "decimal(38,0)", "DecimalData" ),
new columnMeta( "bit", "BitData" ),
new columnMeta( "datetime", "DateTimeData" ),
new columnMeta( "datetime2", "DateTime2Data" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputs = array( "TinyIntData" => 255,
"SmallIntData" => 32767,
"IntData" => 2147483647,
"BigIntData" => 9223372036854774784,
"DecimalData" => 79228162514264,
"BitData" => true,
"DateTimeData" => '9999-12-31 23:59:59.997',
"DateTime2Data" => '9999-12-31 23:59:59.9999999');
$paramOptions = array( new bindParamOption( 4, "PDO::PARAM_INT" ) );
$r;
$stmt = insert_row( $conn, $tbname, $inputs, $r, "prepareBindParam", $paramOptions );
print "Decrypted values:\n";
fetch_all( $conn, $tbname );
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
// for AE only
if ( $keystore != "none" )
{
try
{
$conn = ae_connect( null, null, true );
print "\nEncrypted values:\n";
$selectSql = "SELECT * FROM $tbname";
$stmt = $conn->query( $selectSql );
$encrypted_row = $stmt->fetch( PDO::FETCH_ASSOC );
foreach ( $encrypted_row as $key => $value )
{
if ( !ctype_print( $value ))
{
print "Binary array returned for $key\n";
}
}
DropTable( $conn, $tbname );
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
}
?>
--EXPECT--
Decrypted values:
TinyIntData: 255
SmallIntData: 32767
IntData: 2147483647
BigIntData: 9223372036854774784
DecimalData: 79228162514264
BitData: 1
DateTimeData: 9999-12-31 23:59:59.997
DateTime2Data: 9999-12-31 23:59:59.9999999
Encrypted values:
Binary array returned for TinyIntData
Binary array returned for SmallIntData
Binary array returned for IntData
Binary array returned for BigIntData
Binary array returned for DecimalData
Binary array returned for BitData
Binary array returned for DateTimeData
Binary array returned for DateTime2Data

View file

@ -0,0 +1,80 @@
--TEST--
Test for inserting encrypted nvarchar data of variable lengths and retrieving encrypted and decrypted data
--SKIPIF--
--FILE--
<?php
include 'MsSetup.inc';
include 'MsCommon.inc';
include 'AEData.inc';
$testPass = true;
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
// Create the table
$tbname = 'NVarcharAnalysis';
$colMetaArr = array( new columnMeta( "int", "CharCount", "IDENTITY(0,1)" ), new columnMeta( "nvarchar(1000)" ));
create_table( $conn, $tbname, $colMetaArr );
// insert 1000 rows
for ( $i = 0; $i < 1000; $i++ )
{
$data = str_repeat( "*", $i );
$stmt = insert_row( $conn, $tbname, array( get_default_colname( "nvarchar(1000)" ) => $data ) );
}
$selectSql = "SELECT * FROM $tbname";
$stmt = $conn->query( $selectSql );
while ( $decrypted_row = $stmt->fetch( PDO::FETCH_ASSOC ))
{
if ( $decrypted_row[ 'CharCount' ] != strlen( $decrypted_row[ get_default_colname( "nvarchar(1000)" ) ] ))
{
$rowInd = $decrypted_row[ 'CharCount' ] + 1;
echo "Failed to decrypted at row $rowInd\n";
$testPass = false;
}
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
// for AE only
if ( $keystore != "none" )
{
try
{
$conn = connect( null, null, true );
$stmt = $conn->query( $selectSql );
while ( $decrypted_row = $stmt->fetch( PDO::FETCH_ASSOC ))
{
if ( $decrypted_row[ 'CharCount' ] == strlen( $decrypted_row[ get_default_colname( "nvarchar(1000)" ) ] ))
{
$rowInd = $decrypted_row[ 'CharCount' ] + 1;
echo "Failed to encrypted at row $rowInd\n";
$testPass = false;
}
}
if ( $testPass ) {
echo "Test successfully.\n";
}
DropTable( $conn, $tbname );
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
}
?>
--EXPECT--
Test successfully.

View file

@ -0,0 +1,80 @@
--TEST--
Test for inserting encrypted varchar data of variable lengths and retrieving encrypted and decrypted data
--SKIPIF--
--FILE--
<?php
include 'MsSetup.inc';
include 'MsCommon.inc';
include 'AEData.inc';
$testPass = true;
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
// Create the table
$tbname = 'VarcharAnalysis';
$colMetaArr = array( new columnMeta( "int", "CharCount", "IDENTITY(0,1)" ), new columnMeta( "varchar(1000)" ));
create_table( $conn, $tbname, $colMetaArr );
// insert 1000 rows
for( $i = 0; $i < 1000; $i++ )
{
$data = str_repeat( "*", $i );
$stmt = insert_row( $conn, $tbname, array( get_default_colname( "varchar(1000)" ) => $data ) );
}
$selectSql = "SELECT * FROM $tbname";
$stmt = $conn->query( $selectSql );
while ( $decrypted_row = $stmt->fetch( PDO::FETCH_ASSOC ))
{
if ( $decrypted_row[ 'CharCount' ] != strlen( $decrypted_row[ get_default_colname( "varchar(1000)" ) ] ))
{
$rowInd = $decrypted_row[ 'CharCount' ] + 1;
echo "Failed to decrypted at row $rowInd\n";
$testPass = false;
}
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
// for AE only
if ( $keystore != "none" )
{
try
{
$conn = connect( null, null, true );
$stmt = $conn->query( $selectSql );
while ( $decrypted_row = $stmt->fetch( PDO::FETCH_ASSOC ))
{
if ( $decrypted_row[ 'CharCount' ] == strlen( $decrypted_row[ get_default_colname( "varchar(1000)" ) ] ))
{
$rowInd = $decrypted_row[ 'CharCount' ] + 1;
echo "Failed to encrypted at row $rowInd\n";
$testPass = false;
}
}
if ( $testPass ) {
echo "Test successfully.\n";
}
DropTable( $conn, $tbname );
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
}
?>
--EXPECT--
Test successfully.

View file

@ -0,0 +1,69 @@
--TEST--
Test for inserting and retrieving encrypted string types data
Binding parameters in PDOstatement::execute
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "char(5)", "varchar(max)", "nchar(5)", "nvarchar(max)" );
try
{
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType:\n";
// create table
$tbname = GetTempTableName( "", false );
$tbname = "teststring";
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r );
if ( $r === false ) {
is_incompatible_types_error( $stmt, $dataType, "default type" );
}
else {
echo "****Encrypted default type is compatible with encrypted $dataType****\n";
fetch_all( $conn, $tbname );
}
//DropTable( $conn, $tbname );
}
unset( $stmt );
unset( $conn );
}
catch( PDOException $e )
{
echo $e->getMessage();
}
?>
--EXPECT--
Testing char(5):
****Encrypted default type is compatible with encrypted char(5)****
c_det: -leng
c_rand: th, n
Testing varchar(max):
****Encrypted default type 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):
****Encrypted default type is compatible with encrypted nchar(5)****
c_det: -leng
c_rand: th Un
Testing nvarchar(max):
****Encrypted default type 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).

View file

@ -0,0 +1,167 @@
--TEST--
Test for binding output params for encrypted data for all types
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'MsSetup.inc';
include 'AEData.inc';
$conn = ae_connect();
$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );
// Create the table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( "int", "c1_int" ),
new columnMeta( "smallint", "c2_smallint" ),
new columnMeta( "tinyint", "c3_tinyint" ),
new columnMeta( "bit", "c4_bit" ),
new columnMeta( "bigint", "c5_bigint" ),
new columnMeta( "decimal(18,5)", "c6_decimal" ),
new columnMeta( "numeric(10,5)", "c7_numeric" ),
new columnMeta( "float", "c8_float" ),
new columnMeta( "real", "c9_real" ),
new columnMeta( "date", "c10_date" ),
new columnMeta( "datetime", "c11_datetime" ),
new columnMeta( "datetime2", "c12_datetime2" ),
new columnMeta( "datetimeoffset", "c13_datetimeoffset" ),
new columnMeta( "time", "c14_time" ),
new columnMeta( "char(5)", "c15_char" ),
new columnMeta( "varchar(max)", "c16_varchar" ),
new columnMeta( "nchar(5)", "c17_nchar" ),
new columnMeta( "nvarchar(max)", "c18_nvarchar" ));
create_table( $conn, $tbname, $colMetaArr );
// Create a Store Procedure
$spname = 'selectAllColumns';
$spSql = "CREATE PROCEDURE $spname (
@c1_int int OUTPUT, @c2_smallint smallint OUTPUT,
@c3_tinyint tinyint OUTPUT, @c4_bit bit OUTPUT,
@c5_bigint bigint OUTPUT, @c6_decimal decimal(18,5) OUTPUT,
@c7_numeric numeric(10,5) OUTPUT, @c8_float float OUTPUT,
@c9_real real OUTPUT, @c10_date date OUTPUT,
@c11_datetime datetime OUTPUT, @c12_datetime2 datetime2 OUTPUT,
@c13_datetimeoffset datetimeoffset OUTPUT, @c14_time time OUTPUT,
@c15_char char(5) OUTPUT, @c16_varchar varchar(max) OUTPUT,
@c17_nchar nchar(5) OUTPUT, @c18_nvarchar nvarchar(max) OUTPUT) AS
SELECT @c1_int = c1_int, @c2_smallint = c2_smallint,
@c3_tinyint = c3_tinyint, @c4_bit = c4_bit,
@c5_bigint = c5_bigint, @c6_decimal = c6_decimal,
@c7_numeric = c7_numeric, @c8_float = c8_float,
@c9_real = c9_real, @c10_date = c10_date,
@c11_datetime = c11_datetime, @c12_datetime2 = c12_datetime2,
@c13_datetimeoffset = c13_datetimeoffset, @c14_time = c14_time,
@c15_char = c15_char, @c16_varchar = c16_varchar,
@c17_nchar = c17_nchar, @c18_nvarchar = c18_nvarchar
FROM $tbname";
$conn->query( $spSql );
// Insert data
$inputs = array( "c1_int" => 2147483647,
"c2_smallint" => 32767,
"c3_tinyint" => 255,
"c4_bit" => 1,
"c5_bigint" => 922337203685479936,
"c6_decimal" => 9223372036854.80000,
"c7_numeric" => 21474.83647,
"c8_float" => 9223372036.8548,
"c9_real" => 2147.483,
"c10_date" => '9999-12-31',
"c11_datetime" => '9999-12-31 23:59:59.997',
"c12_datetime2" => '9999-12-31 23:59:59.9999999',
"c13_datetimeoffset" => '9999-12-31 23:59:59.9999999 +14:00',
"c14_time" => '23:59:59.9999999',
"c15_char" => 'th, n',
"c16_varchar" => 'This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.',
"c17_nchar" => 'th Un',
"c18_nvarchar" => '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).' );
$paramOptions = array( new bindParamOption( 5, "PDO::PARAM_INT" ) );
$r;
$stmt = insert_row( $conn, $tbname, $inputs, $r, "prepareBindParam", $paramOptions );
// Call store procedure
$outSql = get_callProcSql_placeholders( $spname, count( $inputs ));
$intOut = 0;
$smallintOut = 0;
$tinyintOut = 0;
$bitOut = 0;
$bigintOut = 0.0;
$decimalOut = 0.0;
$numericOut = 0.0;
$floatOut = 0.0;
$realOut = 0.0;
$dateOut = '0001-01-01';
$datetimeOut = '1753-01-01 00:00:00';
$datetime2Out = '0001-01-01 00:00:00';
$datetimeoffsetOut = '1900-01-01 00:00:00 +01:00';
$timeOut = '00:00:00';
$charOut = '';
$varcharOut = '';
$ncharOut = '';
$nvarcharOut = '';
$stmt = $conn->prepare( $outSql );
$stmt->bindParam(1, $intOut, PDO::PARAM_INT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->bindParam(2, $smallintOut, PDO::PARAM_INT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->bindParam(3, $tinyintOut, PDO::PARAM_INT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->bindParam(4, $bitOut, PDO::PARAM_INT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->bindParam(5, $bigintOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(6, $decimalOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(7, $numericOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(8, $floatOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(9, $realOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(10, $dateOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(11, $datetimeOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(12, $datetime2Out, PDO::PARAM_STR, 2048);
$stmt->bindParam(13, $datetimeoffsetOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(14, $timeOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(15, $charOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(16, $varcharOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(17, $ncharOut, PDO::PARAM_STR, 2048);
$stmt->bindParam(18, $nvarcharOut, PDO::PARAM_STR, 2048);
$stmt->execute();
print ( "intOut: " . $intOut . "\n" );
print ( "smallintOut: " . $smallintOut . "\n" );
print ( "tinyintOut: " . $tinyintOut . "\n" );
print ( "bitOut: " . $bitOut . "\n" );
print ( "bigintOut: " . $bigintOut . "\n" );
print ( "decimalOut: " . $decimalOut . "\n" );
print ( "numericOut: " . $numericOut . "\n" );
print ( "floatOut: " . $floatOut . "\n" );
print ( "realOut: " . $realOut . "\n" );
print ( "dateOut: " . $dateOut . "\n" );
print ( "datetimeOut: " . $datetimeOut . "\n" );
print ( "datetime2Out: " . $datetime2Out . "\n" );
print ( "datetimeoffsetOut: " . $datetimeoffsetOut . "\n" );
print ( "timeOut: " . $timeOut . "\n" );
print ( "charOut: " . $charOut . "\n" );
print ( "varcharOut: " . $varcharOut . "\n" );
print ( "ncharOut: " . $ncharOut . "\n" );
print ( "nvarcharOut: " . $nvarcharOut . "\n" );
$conn->query( "DROP PROCEDURE $spname" );
$conn->query( "DROP TABLE $tbname" );
unset( $stmt );
unset( $conn );
?>
--EXPECT--
intOut: 2147483647
smallintOut: 32767
tinyintOut: 255
bitOut: 1
bigintOut: 922337203685479936
decimalOut: 9223372036854.80000
numericOut: 21474.83647
floatOut: 9223372036.8547993
realOut: 2147.4829
dateOut: 9999-12-31
datetimeOut: 9999-12-31 23:59:59.997
datetime2Out: 9999-12-31 23:59:59.9999999
datetimeoffsetOut: 9999-12-31 23:59:59.9999999 +14:00
timeOut: 23:59:59.9999999
charOut: th, n
varcharOut: This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.
ncharOut: th Un
nvarcharOut: 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).

View file

@ -0,0 +1,113 @@
<?php
// exact numerics
$bigint_params = array( 2147483648, -922337203685479936, 922337203685479936, -2147583649, 461168601735364608, -461168601735364608 );
$int_params = array( 32768, -2147483647, 2147483647, -32769, 1073725440, -1073725440 );
$smallint_params = array( 256, -32767, 32767, -1, 16256, -16256 );
$tinyint_params = array( 128, 0, 255, 96, 64, 162 );
$decimal_params = array( 21474.83648, -9223372036854.80000, 9223372036854.80000, -21475.83649, -4611686017353.64608, -4611686017353.64608 );
$numeric_params = array( 0.32768, -21474.83647, 21474.83647, -0.32769, 10737.25440, -10737.25440 );
$money_params = array( 214748.3648, -92233720368548.0000, 92233720368548.0000, -214758.3649, 46116860173536.608, -46116860173536.608 );
$smallmoney_params = array( 0, -214748.3647, 214748.3647, 161061.2736, 107374.1824, -107374.1824 );
$bit_params = array( 0, 1, 0, 1, 0, 1 );
// approximate numerics
$float_params = array( 21474.83648, -9223372036.8548, 9223372036.8548, -21475, 4611686017, -4611686017 );
$real_params = array( 0, -2147.483, 2147.483, 1610, 1073, -1073 );
// date and time
$date_params = array( '1900-01-01', '0001-01-01', '9999-12-31', '5000-07-15', '2500-04-08', '7500-10-23' );
$datetime2_params = array( '1900-01-01 00:00:00', '0001-01-01 00:00:00', '9999-12-31 23:59:59.9999999', '5000-07-15 12:30:30.5555', '2500-04-08 06:15:15.33', '7500-10-23 18:45:45.888888' );
$datetime_params = array( '1900-01-01 00:00:00', '1753-01-01 00:00:00', '9999-12-31 23:59:59.997', '5000-07-15 12:30:30.5', '2500-04-08 06:15:15.33', '7500-10-23 18:45:45.888' );
$datetimeoffset_params = array( '1900-01-01 00:00:00 +01:00', '0001-01-01 00:00:00 -14:00', '9999-12-31 23:59:59.9999999 +14:00', '5000-07-15 12:30:30.55 -03:00', '2500-04-08 06:15:15.3333 -07:00', '7500-10-23 18:45:45.888888 +07:00' );
$smalldatetime_params = array( '1900-01-01 00:00:00', '1900-01-01 00:00:00', '2079-06-05 23:59:00', '1990-07-15 12:30:00', '1945-04-08 06:15:00', '2000-10-23 18:45:00' );
$time_params = array( '00:00:00', '00:00:00.0000000', '23:59:59.9999999', '12:30:30.5555', '06:15:15.33', '18:45:45.888888' );
// character strings
$char_params = array( 'Fixed', '-leng', 'th, n', 'on-Un', 'icode', 'strin' );
$varchar_params = array( 'This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.',
'Use varchar(max) when the sizes of the column data entries vary considerably, and the size might exceed 8,000 bytes.',
'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.',
'This can create an implicit limit to the number of non-null varchar(max) or nvarchar(max) columns that can be created in a table.',
'No special error is provided when the table is created (beyond the usual warning that the maximum row size exceeds the allowed maximum of 8060 bytes) or at the time of data insertion.',
'This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.' );
// unicode character strings
$nchar_params = array( 'Fixed', '-leng', 'th Un', 'icode', 'strin', 'g dat' );
$nvarchar_params = array( 'max indicates that the maximum storage size is 2^31-1 bytes (2 GB).',
'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).',
'Otherwise, the implicit conversion will result in a Unicode large-value (max).',
'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.',
'This can create an implicit limit to the number of non-null varchar(max) or nvarchar(max) columns that can be created in a table.',
'No special error is provided when the table is created (beyond the usual warning that the maximum row size exceeds the allowed maximum of 8060 bytes) or at the time of data insertion.' );
// binary strings
$binary_params = array( 'Fixed', '-leng', 'th, n', 'on-Un', 'icode', 'strin' );
$varbinary_params = array( 'Variable-length, non-', 'Unicode string data. n', 'defines the string length', 'and can be a value from 1', 'through 8,000.', 'The storage size is the' );
$varbinarymax_params = array( 'max indicates that the maximum storage size is 2^31-1 bytes (2 GB)',
'Use varchar(max) when the sizes of the column data entries vary considerably, and the size might exceed 8,000 bytes.',
'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.',
'This can create an implicit limit to the number of non-null varchar(max) or nvarchar(max) columns that can be created in a table.',
'No special error is provided when the table is created (beyond the usual warning that the maximum row size exceeds the allowed maximum of 8060 bytes) or at the time of data insertion.',
'This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.' );
// Array containing all SQLSRV_SQLTYPE_ types to pass into a bind param prepare statement
$sqlTypes = array(
'SQLSRV_SQLTYPE_BIGINT',
'SQLSRV_SQLTYPE_BINARY',
'SQLSRV_SQLTYPE_BIT',
'SQLSRV_SQLTYPE_CHAR',
'SQLSRV_SQLTYPE_DATE',
'SQLSRV_SQLTYPE_DATETIME',
'SQLSRV_SQLTYPE_DATETIME2',
'SQLSRV_SQLTYPE_DATETIMEOFFSET',
'SQLSRV_SQLTYPE_DECIMAL',
'SQLSRV_SQLTYPE_FLOAT',
'SQLSRV_SQLTYPE_IMAGE',
'SQLSRV_SQLTYPE_INT',
'SQLSRV_SQLTYPE_MONEY',
'SQLSRV_SQLTYPE_NCHAR',
'SQLSRV_SQLTYPE_NUMERIC',
'SQLSRV_SQLTYPE_NVARCHAR',
'SQLSRV_SQLTYPE_NTEXT',
'SQLSRV_SQLTYPE_REAL',
'SQLSRV_SQLTYPE_SMALLDATETIME',
'SQLSRV_SQLTYPE_SMALLINT',
'SQLSRV_SQLTYPE_SMALLMONEY',
'SQLSRV_SQLTYPE_TEXT',
'SQLSRV_SQLTYPE_TIME',
'SQLSRV_SQLTYPE_TIMESTAMP',
'SQLSRV_SQLTYPE_TINYINT',
'SQLSRV_SQLTYPE_UNIQUEIDENTIFIER',
'SQLSRV_SQLTYPE_VARBINARY',
'SQLSRV_SQLTYPE_VARCHAR',
'SQLSRV_SQLTYPE_XML'
);
// Checks if the current error is the incompatible types error
// if so, state which sql type is incompatible with which data type
function is_incompatible_types_error( $dataType, $sqlType )
{
$errors = sqlsrv_errors();
foreach ( $errors as $error )
{
// 22018 is the SQLSTATE for the operand crash error for incompatible types
if ( $error['SQLSTATE'] == 22018 )
{
echo "Encrypted $sqlType is incompatible with encrypted $dataType\n";
}
}
}
function get_default_size_prec( $sqlType )
{
if ( $sqlType == 'SQLSRV_SQLTYPE_DECIMAL' )
$sqlType .= "(18, 5)";
elseif ( $sqlType == 'SQLSRV_SQLTYPE_NUMERIC' )
$sqlType .= "(10, 5)";
elseif ( $sqlType == 'SQLSRV_SQLTYPE_CHAR' || $sqlType == 'SQLSRV_SQLTYPE_NCHAR' )
$sqlType .= "(5)";
return $sqlType;
}
?>

View file

@ -86,7 +86,7 @@ function IsAEQualified($conn)
$server_ver = sqlsrv_server_info($conn)['SQLServerVersion'];
$msodbcsql_maj = explode(".", $msodbcsql_ver)[0];
$msodbcsql_min = explode(".", $msodbcsql_ver)[1];
if ($msodbcsql_maj < 17 || explode('.', $server_ver)[0] < 13)
if ($msodbcsql_maj < 13 || explode('.', $server_ver)[0] < 13)
return false;
return true;
}
@ -170,6 +170,381 @@ function Connect($options = array())
return ($conn);
}
/**
* Connect to the database specified in MsSetup.inc; Column Encryption options automatically added when $keystore is not none
* @param array $options : connection attributes to pass to sqlsrv_connect
* @param bool $disableCE : flag for disabling column encryption even when keystore is NOT none
* for testing fetching encrypted data when connection column encryption is off
* @return connection resource
*/
function ae_connect( $options = array(), $disableCE = false )
{
require 'MsSetup.inc';
if ( sizeof( $options ) > 0 )
{
$connectionOptions = array_merge( $connectionOptions, $options );
}
if ( $keystore != "none" && !$disableCE )
{
$connectionOptions = array_merge( $connectionOptions, array( "ColumnEncryption" => "Enabled" ));
}
if ( $keystore == "ksp" && !$disableCE )
{
require( 'AE_Ksp.inc' );
$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 )
FatalError( "Failed to connect to $server." );
return $conn;
}
/**
* @return string CEK name depending on the connection keywords
*/
function getCekName()
{
require 'MsSetup.inc';
$cekName = '';
switch ( $keystore ) {
case "none":
$cekName = '';
break;
case "win":
$cekName = 'AEColumnKey';
break;
case "ksp":
$cekName = 'CustomCEK';
break;
case "akv":
$cekName = 'AKVColumnKey';
break;
}
return $cekName;
}
/**
* class for encapsulating column metadata needed for creating a table
*/
class columnMeta {
public $colName;
public $dataType; //a string that includes the size of the type if necessary (e.g., decimal(10,5))
public $encType; //randomized or deterministic; default is deterministic
public $options; //a string that is empty by default (e.g. NOT NULL Identity (1,1) )
function __construct( $dataType, $colName = null, $options = null, $encType = "deterministic" )
{
if ( !$colName )
{
$this->colName = get_default_colname( $dataType );
}
else
{
$this->colName = $colName;
}
$this->dataType = $dataType;
$this->encType = $encType;
$this->options = $options;
}
/**
* @return string column definition for creating a table
*/
function getColDef()
{
require 'MsSetup.inc';
$append = " ";
if ( $keystore != "none" && stripos( $this->options, "identity" ) === false )
{
$cekName = getCekName();
$encDet = "ENCRYPTED WITH (ENCRYPTION_TYPE = DETERMINISTIC, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = $cekName) ";
$encRand = "ENCRYPTED WITH (ENCRYPTION_TYPE = RANDOMIZED, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256', COLUMN_ENCRYPTION_KEY = $cekName) ";
if ( stripos( $this->dataType, "char" ) !== false )
$append .= "COLLATE Latin1_General_BIN2 ";
if ( $this->encType == "deterministic" )
$append .= $encDet;
else
$append .= $encRand;
}
$append .= $this->options;
$colDef = "[" . $this->colName . "] " . $this->dataType . $append;
return $colDef;
}
}
/**
* @return string default column name when a name is not provided in the columnMeta class
*/
function get_default_colname( $dataType )
{
$colName = "c_" . str_replace( ",", "_", str_replace( "(", "_", $dataType ));
$colName = rtrim( $colName, ")" );
return $colName;
}
/**
* Create a table
* @param object $conn : PDO connection object
* @param string $tbname : name of the table to be created
* @param array $columnMeta : array of columnMeta objects, which contain metadata for one column
*/
function create_table( $conn, $tbname, $columnMeta )
{
$dropSql = "IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'" . $tbname . "') AND type in (N'U')) DROP TABLE $tbname";
sqlsrv_query( $conn, $dropSql );
$colDef = "";
foreach ( $columnMeta as $meta )
{
$colDef = $colDef . $meta->getColDef() . ", ";
}
$colDef = rtrim( $colDef, ", " );
$createSql = "CREATE TABLE $tbname ( $colDef )";
sqlsrv_query( $conn, $createSql );
}
/**
* class for encapsulating optional parameters for binding parameters in sqlsrv_prepare
*/
class bindParamOption {
public $index; //1-based index of the parameter
public $direction; //SQLSRV_PARAM_ constant indicating the parameter direction
public $phpType; //SQLSRV_PHPTYPE_ constant specifying the php type of the return values
public $sqlType; //SQLSRV_SQLTYPE_ constant specifying the SQL type of the input
function __construct( $index, $direction = null, $phpType = null, $sqlType = null )
{
$this->index = $index;
$this->direction = $direction;
$this->phpType = $phpType;
$this->sqlType = $sqlType;
}
/**
* @param resource $conn : connection resource
* @param mix $var : variable to bind to the SQL statement parameter
* @return array needed to bind parameter in sqlsrv_prepare
*/
function bindParamArr( $var )
{
// get the constant values of direction, phpType, and sqlType
$direction = null;
$phpType = null;
$sqlType = null;
if ( $this->direction )
$direction = constant( $this->direction );
if ( $this->phpType )
$phpType = constant( $this->phpType );
if ( $this->sqlType )
{
// parse out the datatype name, size, precision, and/or scale from a SQLSRV_SQLTYPE_ constant
$size = null;
$prec = null;
$scal = null;
$type_size = explode( "(", $this->sqlType );
$type = $type_size[0];
if ( count( $type_size ) > 1 )
{
$size = $type_size[1];
$prec_scal = explode( ",", $size );
if ( count( $prec_scal ) > 1 )
{
$prec = $prec_scal[0];
$scal = rtrim( $prec_scal[1], ")" );
$size = null;
}
}
// get the sqlType constant
if ( $prec && $scal )
$sqlType = call_user_func( $type, $prec, $scal );
elseif ( $size )
$sqlType = call_user_func( $type, $size );
else
$sqlType = constant( $type );
}
return array( $var, $direction, $phpType, $sqlType );
}
}
/**
* Create a row into a table
* @param object $conn : PDO connection object
* @param string $tbname : name of the table to be created
* @param array $inputs : an associative array column name and its value
* @param bool $r : if the row was successfully inserted
* $param string $api : SQLSRV API used for executing the insert query
* accepted values: "query", "queryParamsOp", "prepare", "prepareParamsOp"
* @param array $paramOption : an array of bindParamOptions. Should only be provided if $api is "perpareWithParamOp", if provided, has to be in the same order as $inputs
* @return object PDOStatement object of the insert statement
*/
function insert_row( $conn, $tbname, $inputs, &$r = null, $api = "query", $paramOption = array() )
{
require 'MsSetup.inc';
$stmt = null;
if ( $keystore == "none" && $api != "queryParamsOp" && $api != "prepareParamsOp" )
{
$insertSql = get_insertSql_complete( $tbname, $inputs );
switch ( $api ) {
case "query":
$stmt = sqlsrv_query( $conn, $insertSql );
break;
case "prepare":
$stmt = sqlsrv_prepare( $conn, $insertSql );
$r = sqlsrv_execute( $stmt );
break;
}
}
else
{
// if AE is on, must bind param
$insertSql = get_insertSql_placeholders( $tbname, $inputs );
$params = array();
if ( empty( $paramOption ))
{
foreach ( $inputs as $key => $value )
{
array_push($params, $inputs[$key] );
}
}
else
{
$i = 1;
foreach( $inputs as $key => $value )
{
$nooption = true;
foreach( $paramOption as $op )
{
if ( $op->index == $i )
{
array_push( $params, $op->bindParamArr( $inputs[$key] ));
$nooption = false;
$i++;
break;
}
}
if ( $nooption )
{
array_push( $params, $inputs[$key] );
$i++;
}
}
}
if ( $keystore != "none" || $api == "prepareParamsOp" )
{
$stmt = sqlsrv_prepare( $conn, $insertSql, $params );
$r = sqlsrv_execute( $stmt );
}
else
$stmt = sqlsrv_query( $conn, $insertSql, $params );
}
return $stmt;
}
/**
* @param string $tbname : name of the table for an insert sql
* @param array $input : associative array containing a key value pair of column name and data to put into an insert sql string
* @return string a complete insert sql string
*/
function get_insertSql_complete( $tbname, $inputs )
{
$colStr = "INSERT INTO $tbname (";
$valStr = "VALUES (";
foreach( $inputs as $key => $value )
{
$colStr .= $key . ", ";
if ( is_string( $value ))
$valStr .= "'" . $value . "', ";
else
$valStr .= $value . ", ";
}
$colStr = rtrim( $colStr, ", " ) . ") ";
$valStr = rtrim( $valStr, ", " ) . ") ";
$insertSql = $colStr . $valStr;
return $insertSql;
}
/**
* @param string $tbname : name of the table for an insert sql
* @param array $input : associative array containing a key value pair of column name and data to put into an insert sql string
* @return string an insert sql string with "?" placeholders for all values
*/
function get_insertSql_placeholders( $tbname, $inputs )
{
$colStr = "INSERT INTO $tbname (";
$valStr = "VALUES (";
foreach( $inputs as $key => $value )
{
$colStr .= $key . ", ";
}
$colStr = rtrim( $colStr, ", " ) . ") ";
$valStr .= get_seq_placeholders( count( $inputs )) . ") ";
$insertSql = $colStr . $valStr;
return $insertSql;
}
/**
* @param string $spname : name of the stored procedure
* @param int $num : number of parameters needed for the stored procedure
* @return string a call stored procedure sql string with "?" placeholders for all parameters
*/
function get_callProcSql_placeholders( $spname, $num )
{
$callStr = "{CALL $spname (";
$callStr .= get_seq_placeholders( $num ) . ")} ";
return $callStr;
}
/**
* @param int $num : number of placeholders needed
* @return string a string containing $num number of repeated "?" placeholders delimited by ", "
*/
function get_seq_placeholders( $num )
{
$placeholderStr = str_repeat( "?, ", $num );
$placeholderStr = rtrim( $placeholderStr, ", " );
return $placeholderStr;
}
/**
* Fetch all rows and all columns given a table name, and print them
* @param resource $conn : connection resource
* @param string $tbname : name of the table to fetch from
*/
function fetch_all( $conn, $tbname ) {
$sql = "SELECT * FROM $tbname";
$stmt = sqlsrv_query( $conn, $sql );
while ( $row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC ))
{
foreach ( $row as $key => $value )
{
if ( is_object( $value ) )
{
print "$key:\n";
foreach ( $value as $k =>$value )
{
print ( " $k: $value\n" );
}
}
else
print ( "$key: $value\n" );
}
}
}
function GetTempTableName($table = '', $temporary = true)
{
// A temporary table name with the '#' prefix will be automatically

View file

@ -0,0 +1,106 @@
--TEST--
Test for inserting and retrieving encrypted datetime types data
Bind params using sqlsrv_prepare without any sql_type specified
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "date", "datetime", "datetime2", "smalldatetime", "time", "datetimeoffset" );
$conn = ae_connect();
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType: \n";
// create table
$tbname = GetTempTableName( "", false );
$tbname = "test_numeric";
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r );
if ( $r === false ) {
is_incompatible_types_error( $dataType, "default type" );
}
else {
echo "****Encrypted default type is compatible with encrypted $dataType****\n";
fetch_all( $conn, $tbname );
}
//DropTable( $conn, $tbname );
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
Testing date:
****Encrypted default type is compatible with encrypted date****
c_det:
date: 0001-01-01 00:00:00.000000
timezone_type: 3
timezone: UTC
c_rand:
date: 9999-12-31 00:00:00.000000
timezone_type: 3
timezone: UTC
Testing datetime:
****Encrypted default type is compatible with encrypted datetime****
c_det:
date: 1753-01-01 00:00:00.000000
timezone_type: 3
timezone: UTC
c_rand:
date: 9999-12-31 23:59:59.997000
timezone_type: 3
timezone: UTC
Testing datetime2:
****Encrypted default type is compatible with encrypted datetime2****
c_det:
date: 0001-01-01 00:00:00.000000
timezone_type: 3
timezone: UTC
c_rand:
date: 9999-12-31 23:59:59.1000000
timezone_type: 3
timezone: UTC
Testing smalldatetime:
****Encrypted default type is compatible with encrypted smalldatetime****
c_det:
date: 1900-01-01 00:00:00.000000
timezone_type: 3
timezone: UTC
c_rand:
date: 2079-06-05 23:59:00.000000
timezone_type: 3
timezone: UTC
Testing time:
****Encrypted default type is compatible with encrypted time****
c_det:
date: 2017-09-12 00:00:00.000000
timezone_type: 3
timezone: UTC
c_rand:
date: 2017-09-12 23:59:59.1000000
timezone_type: 3
timezone: UTC
Testing datetimeoffset:
****Encrypted default type is compatible with encrypted datetimeoffset****
c_det:
date: 0001-01-01 00:00:00.000000
timezone_type: 1
timezone: -14:00
c_rand:
date: 9999-12-31 23:59:59.1000000
timezone_type: 1
timezone: +14:00

View file

@ -0,0 +1,77 @@
--TEST--
Test for inserting and retrieving encrypted numeric types data
Bind params using sqlsrv_prepare without any sql_type specified
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "smallmoney", "money" );
$conn = ae_connect();
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType: \n";
$success = true;
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r );
if ( $keystore == "none" )
{
if ( $r === false )
{
echo "Default type should be compatible with $dataType.\n";
$success = false;
}
else
{
$sql = "SELECT * 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 "Incorrect output retrieved for datatype $dataType and sqlType $sqlType.\n";
$success = false;
}
}
}
else
{
if ( $r === false )
{
if ( sqlsrv_errors()[0]['SQLSTATE'] != 22018 )
{
echo "Incorrect error returned.\n";
$success = false;
}
}
else
{
echo "$dataType is not compatible with any type.\n";
$success = false;
}
}
if ( $success )
echo "Test successfully.\n";
DropTable( $conn, $tbname );
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
Testing smallmoney:
Test successfully.
Testing money:
Test successfully.

View file

@ -0,0 +1,84 @@
--TEST--
Test for inserting and retrieving encrypted numeric types data
Bind params using sqlsrv_prepare without any sql_type specified
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "bit", "tinyint", "smallint", "int", "bigint", "decimal(18,5)", "numeric(10,5)", "float", "real" );
$conn = ae_connect();
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType: \n";
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r );
if ( $r === false ) {
is_incompatible_types_error( $dataType, "default type" );
}
else {
echo "****Encrypted default type is compatible with encrypted $dataType****\n";
fetch_all( $conn, $tbname );
}
DropTable( $conn, $tbname );
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
Testing bit:
****Encrypted default type is compatible with encrypted bit****
c_det: 1
c_rand: 0
Testing tinyint:
****Encrypted default type is compatible with encrypted tinyint****
c_det: 0
c_rand: 255
Testing smallint:
****Encrypted default type is compatible with encrypted smallint****
c_det: -32767
c_rand: 32767
Testing int:
****Encrypted default type is compatible with encrypted int****
c_det: -2147483647
c_rand: 2147483647
Testing bigint:
****Encrypted default type is compatible with encrypted bigint****
c_det: -922337203685479936
c_rand: 922337203685479936
Testing decimal(18,5):
****Encrypted default type is compatible with encrypted decimal(18,5)****
c_det: -9223372036854.80000
c_rand: 9223372036854.80000
Testing numeric(10,5):
****Encrypted default type is compatible with encrypted numeric(10,5)****
c_det: -21474.83647
c_rand: 21474.83647
Testing float:
****Encrypted default type is compatible with encrypted float****
c_det: -9223372036.8548
c_rand: 9223372036.8548
Testing real:
****Encrypted default type is compatible with encrypted real****
c_det: -2147.4829101562
c_rand: 2147.4829101562

View file

@ -0,0 +1,82 @@
--TEST--
Test for inserting encrypted data and retrieving both encrypted and decrypted data
Retrieving SQL query contains encrypted filter
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'MsSetup.inc';
include 'AEData.inc';
$conn = ae_connect();
// Create the table
$tbname = 'Patients';
$colMetaArr = array( new columnMeta( "int", "PatientId", "IDENTITY(1,1)" ),
new columnMeta( "char(11)", "SSN"),
new columnMeta( "nvarchar(50)", "FirstName", "NULL" ),
new columnMeta( "nvarchar(50)", "LastName", "NULL"),
new columnMeta( "date", "BirthDate", null, "randomized" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$SSN = "795-73-9838";
$inputs = array( "SSN" => $SSN, "FirstName" => "Catherine", "LastName" => "Abel", "BirthDate" => "1996-10-19" );
$stmt = insert_row( $conn, $tbname, $inputs );
echo "Retrieving plaintext data:\n";
$selectSql = "SELECT SSN, FirstName, LastName, BirthDate FROM $tbname WHERE SSN = ?";
$stmt = sqlsrv_prepare( $conn, $selectSql, array( $SSN ));
sqlsrv_execute( $stmt );
$decrypted_row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC );
foreach ( $decrypted_row as $key => $value )
{
if ( !is_object( $value ))
print "$key: $value\n";
else
{
print "$key:\n";
foreach ( $value as $dateKey => $dateValue )
{
print " $dateKey: $dateValue\n";
}
}
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
//for AE only
echo "\nRetrieving ciphertext data:\n";
if ( $keystore != "none" )
{
$conn = ae_connect( null, true );
$selectSql = "SELECT SSN, FirstName, LastName, BirthDate FROM $tbname";
$stmt = sqlsrv_query( $conn, $selectSql );
$encrypted_row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC );
foreach( $encrypted_row as $key => $value )
{
if ( !ctype_print( $value ))
print "Binary array returned for $key\n";
}
DropTable( $conn, $tbname );
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
}
?>
--EXPECT--
Retrieving plaintext data:
SSN: 795-73-9838
FirstName: Catherine
LastName: Abel
BirthDate:
date: 1996-10-19 00:00:00.000000
timezone_type: 3
timezone: UTC
Retrieving ciphertext data:
Binary array returned for SSN
Binary array returned for FirstName
Binary array returned for LastName
Binary array returned for BirthDate

View file

@ -0,0 +1,90 @@
--TEST--
Test for inserting encrypted fixed size types data and retrieve both encrypted and decrypted data
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'MsSetup.inc';
include 'AEData.inc';
$conn = ae_connect();
$testPass = true;
// Create the table
$tbname = 'FixedSizeAnalysis';
$colMetaArr = array( new columnMeta( "tinyint", "TinyIntData" ),
new columnMeta( "smallint", "SmallIntData" ),
new columnMeta( "int", "IntData" ),
new columnMeta( "bigint", "BigIntData" ),
new columnMeta( "decimal(38,0)", "DecimalData" ),
new columnMeta( "bit", "BitData" ),
new columnMeta( "datetime", "DateTimeData" ),
new columnMeta( "datetime2", "DateTime2Data" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputs = array( "TinyIntData" => 255,
"SmallIntData" => 32767,
"IntData" => 2147483647,
"BigIntData" => 9223372036854774784,
"DecimalData" => 79228162514264,
"BitData" => true,
"DateTimeData" => '9999-12-31 23:59:59.997',
"DateTime2Data" => '9999-12-31 23:59:59.9999999');
$stmt = insert_row( $conn, $tbname, $inputs );
print "Decrypted values:\n";
fetch_all( $conn, $tbname );
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
// for AE only
if ( $keystore != "none" )
{
$conn = connect( null, true );
print "\nEncrypted values:\n";
$selectSql = "SELECT * FROM $tbname";
$stmt = sqlsrv_query( $conn, $selectSql );
$encrypted_row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC );
foreach( $encrypted_row as $key => $value )
{
if ( !ctype_print( $value ))
{
print "Binary array returned for $key\n";
}
}
DropTable( $conn, $tbname );
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
}
?>
--EXPECT--
Decrypted values:
TinyIntData: 255
SmallIntData: 32767
IntData: 2147483647
BigIntData: 9223372036854774784
DecimalData: 79228162514264
BitData: 1
DateTimeData:
date: 9999-12-31 23:59:59.997000
timezone_type: 3
timezone: UTC
DateTime2Data:
date: 9999-12-31 23:59:59.1000000
timezone_type: 3
timezone: UTC
Encrypted values:
Binary array returned for TinyIntData
Binary array returned for SmallIntData
Binary array returned for IntData
Binary array returned for BigIntData
Binary array returned for DecimalData
Binary array returned for BitData
Binary array returned for DateTimeData
Binary array returned for DateTime2Data

View file

@ -0,0 +1,65 @@
--TEST--
Test for inserting encrypted nvarchar data of variable lengths and retrieving encrypted and decrypted data
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'MsSetup.inc';
include 'AEData.inc';
$conn = ae_connect();
$testPass = true;
// Create the table
$tbname = 'NVarcharAnalysis';
$colMetaArr = array( new columnMeta( "int", "CharCount", "IDENTITY(0,1)" ), new columnMeta( "nvarchar(1000)" ));
create_table( $conn, $tbname, $colMetaArr );
// insert 1000 rows
for ( $i = 0; $i < 1000; $i++ )
{
$data = str_repeat( "*", $i );
$stmt = insert_row( $conn, $tbname, array( get_default_colname( "nvarchar(1000)" ) => $data ));
}
$selectSql = "SELECT * FROM $tbname";
$stmt = sqlsrv_query( $conn, $selectSql );
while ( $decrypted_row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC ))
{
if ( $decrypted_row[ 'CharCount' ] != strlen( $decrypted_row[ get_default_colname( "nvarchar(1000)" ) ] ))
{
$rowInd = $decrypted_row[ 'CharCount' ] + 1;
echo "Failed to decrypted at row $rowInd\n";
$testPass = false;
}
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
// for AE only
if ( $keystore != "none" )
{
$conn = ae_connect( null, true );
$stmt = sqlsrv_query( $conn, $selectSql );
while ( $encrypted_row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC ))
{
if ( $encrypted_row[ 'CharCount' ] == strlen( $encrypted_row[ get_default_colname( "nvarchar(1000)" ) ] ))
{
$rowInd = $encrypted_row[ 'CharCount' ] + 1;
echo "Failed to encrypted at row $rowInd\n";
$testPass = false;
}
}
if ( $testPass ) {
echo "Test successfully.\n";
}
DropTable( $conn, $tbname );
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
}
?>
--EXPECT--
Test successfully.

View file

@ -0,0 +1,65 @@
--TEST--
Test for inserting encrypted varchar data of variable lengths and retrieving encrypted and decrypted data
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'MsSetup.inc';
include 'AEData.inc';
$conn = ae_connect();
$testPass = true;
// Create the table
$tbname = 'VarcharAnalysis';
$colMetaArr = array( new columnMeta( "int", "CharCount", "IDENTITY(0,1)" ), new columnMeta( "varchar(1000)" ));
create_table( $conn, $tbname, $colMetaArr );
// insert 1000 rows
for ( $i = 0; $i < 1000; $i++ )
{
$data = str_repeat( "*", $i );
$stmt = insert_row( $conn, $tbname, array( get_default_colname( "varchar(1000)" ) => $data ));
}
$selectSql = "SELECT * FROM $tbname";
$stmt = sqlsrv_query( $conn, $selectSql );
while ( $decrypted_row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC ))
{
if ( $decrypted_row[ 'CharCount' ] != strlen( $decrypted_row[ get_default_colname( "varchar(1000)" ) ] ))
{
$rowInd = $decrypted_row[ 'CharCount' ] + 1;
echo "Failed to decrypted at row $rowInd\n";
$testPass = false;
}
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
// for AE only
if ( $keystore != "none" )
{
$conn = ae_connect( null, true );
$stmt = sqlsrv_query( $conn, $selectSql );
while ( $encrypted_row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC ))
{
if ( $encrypted_row[ 'CharCount' ] == strlen( $encrypted_row[ get_default_colname( "varchar(1000)" ) ] ))
{
$rowInd = $encrypted_row[ 'CharCount' ] + 1;
echo "Failed to encrypted at row $rowInd\n";
$testPass = false;
}
}
if ( $testPass ) {
echo "Test successfully.\n";
}
DropTable( $conn, $tbname );
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
}
?>
--EXPECT--
Test successfully.

View file

@ -0,0 +1,110 @@
--TEST--
Test for inserting and retrieving encrypted datetime types data
Bind params using sqlsrv_prepare with all sql_type
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "date", "datetime", "datetime2", "smalldatetime", "time", "datetimeoffset" );
$compatList = array( "date" => array( "SQLSRV_SQLTYPE_DATE", "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_DATETIME2", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_VARCHAR"),
"datetime" => array( "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_DATETIME2", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_VARCHAR"),
"datetime2" => array( "SQLSRV_SQLTYPE_DATETIME2", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_VARCHAR"),
"smalldatetime" => array( "SQLSRV_SQLTYPE_DATETIME", "SQLSRV_SQLTYPE_DATETIME2", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_SMALLDATETIME", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_VARCHAR" ),
"time" => array( "SQLSRV_SQLTYPE_DATETIME2", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_VARCHAR" ),
"datetimeoffset" => array( "SQLSRV_SQLTYPE_DATETIME2", "SQLSRV_SQLTYPE_DATETIMEOFFSET", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_TIME", "SQLSRV_SQLTYPE_VARCHAR" ));
$conn = ae_connect();
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType: \n";
$success = true;
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// test each SQLSRV_SQLTYPE_ constants
foreach ( $sqlTypes as $sqlType )
{
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$sqlType = get_default_size_prec( $sqlType );
$paramOp = array( new bindParamOption( 1, null, null, $sqlType ), new bindParamOption( 2, null, null, $sqlType ));
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r, "prepareParamsOp", $paramOp );
if ( $keystore == "none" )
{
if ( $r === false )
{
$isCompat = false;
foreach ( $compatList[$dataType] as $compatType )
{
if ( $compatType == $sqlType )
$isCompat = true;
}
if ( $isCompat )
{
echo "$sqlType should be compatible with $dataType\n";
$success = false;
}
}
}
else
{
if ( $r === false )
{
if ( "SQLSRV_SQLTYPE_" . strtoupper( $dataType ) == $sqlType )
{
echo "$sqlType should be compatible with $dataType\n";
$success = false;
}
}
else
{
$sql = "SELECT * FROM $tbname";
$stmt = sqlsrv_query( $conn, $sql );
$row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC );
if ( $row["c_det"] != new DateTime( $inputValues[0] ) || $row["c_rand"] != new DateTime( $inputValues[1] ))
{
echo "Incorrect output retrieved for datatype $dataType and sqlType $sqlType.\n";
var_dump( $inputValues );
var_dump( $row );
$success = false;
}
}
}
sqlsrv_query( $conn, "TRUNCATE TABLE $tbname" );
}
if ( $success )
echo "Test successfully.\n";
DropTable( $conn, $tbname );
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
Testing date:
Test successfully.
Testing datetime:
Test successfully.
Testing datetime2:
Test successfully.
Testing smalldatetime:
Test successfully.
Testing time:
Test successfully.
Testing datetimeoffset:
Test successfully.

View file

@ -0,0 +1,77 @@
--TEST--
Test for inserting and retrieving encrypted numeric types data
Bind params using sqlsrv_prepare with all sql_type
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "smallmoney", "money" );
$compatList = array( "smallmoney" => array( 'SQLSRV_SQLTYPE_CHAR', 'SQLSRV_SQLTYPE_DECIMAL', 'SQLSRV_SQLTYPE_FLOAT', 'SQLSRV_SQLTYPE_MONEY', 'SQLSRV_SQLTYPE_NCHAR', 'SQLSRV_SQLTYPE_NUMERIC', 'SQLSRV_SQLTYPE_NVARCHAR', 'SQLSRV_SQLTYPE_REAL', 'SQLSRV_SQLTYPE_SMALLMONEY', 'SQLSRV_SQLTYPE_VARCHAR' ),
"money" => array( 'SQLSRV_SQLTYPE_BIGINT', 'SQLSRV_SQLTYPE_CHAR', 'SQLSRV_SQLTYPE_DECIMAL', 'SQLSRV_SQLTYPE_FLOAT', 'SQLSRV_SQLTYPE_MONEY', 'SQLSRV_SQLTYPE_NCHAR', 'SQLSRV_SQLTYPE_NUMERIC', 'SQLSRV_SQLTYPE_NVARCHAR', 'SQLSRV_SQLTYPE_REAL', 'SQLSRV_SQLTYPE_VARCHAR' ));
$conn = ae_connect();
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType: \n";
$success = true;
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// test each SQLSRV_SQLTYPE_ constants
foreach ( $sqlTypes as $sqlType )
{
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$sqlType = get_default_size_prec( $sqlType );
$paramOp = array( new bindParamOption( 1, null, null, $sqlType ), new bindParamOption( 2, null, null, $sqlType ));
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r, "prepareParamsOp", $paramOp );
if ( $keystore == "none" )
{
if ( $r === false )
{
$isCompat = false;
foreach ( $compatList[$dataType] as $compatType )
{
if ( stripos( $compatType, $sqlType ) !== false )
$isCompat = true;
}
if ( $isCompat )
{
echo "$sqlType should be compatible with $dataType\n";
$success = false;
}
}
}
else
{
if ( $r !== false )
{
echo "$dataType should not be compatible with any type.\n";
$success = false;
}
}
sqlsrv_query( $conn, "TRUNCATE TABLE $tbname" );
}
if ( $success )
echo "Test successfully.\n";
DropTable( $conn, $tbname );
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
Testing smallmoney:
Test successfully.
Testing money:
Test successfully.

View file

@ -0,0 +1,132 @@
--TEST--
Test for inserting and retrieving encrypted numeric types data
Bind params using sqlsrv_prepare with all sql_type
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "bit", "tinyint", "smallint", "int", "bigint", "decimal(18,5)", "numeric(10,5)", "float", "real" );
$compatList = array( "bit" => array( "SQLSRV_SQLTYPE_BIGINT", "SQLSRV_SQLTYPE_BIT", "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_DECIMAL", "SQLSRV_SQLTYPE_FLOAT", "SQLSRV_SQLTYPE_INT", "SQLSRV_SQLTYPE_MONEY", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NUMERIC", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_REAL", "SQLSRV_SQLTYPE_SMALLINT", "SQLSRV_SQLTYPE_SMALLMONEY", "SQLSRV_SQLTYPE_TINYINT", "SQLSRV_SQLTYPE_VARCHAR"),
"tinyint" => array( "SQLSRV_SQLTYPE_BIGINT", "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_DECIMAL", "SQLSRV_SQLTYPE_FLOAT", "SQLSRV_SQLTYPE_INT", "SQLSRV_SQLTYPE_MONEY", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NUMERIC", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_REAL", "SQLSRV_SQLTYPE_SMALLINT", "SQLSRV_SQLTYPE_SMALLMONEY", "SQLSRV_SQLTYPE_TINYINT", "SQLSRV_SQLTYPE_VARCHAR"),
"smallint" => array( "SQLSRV_SQLTYPE_BIGINT", "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_DECIMAL", "SQLSRV_SQLTYPE_FLOAT", "SQLSRV_SQLTYPE_INT", "SQLSRV_SQLTYPE_MONEY", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NUMERIC", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_REAL", "SQLSRV_SQLTYPE_SMALLINT", "SQLSRV_SQLTYPE_SMALLMONEY", "SQLSRV_SQLTYPE_VARCHAR"),
"int" => array( "SQLSRV_SQLTYPE_BIGINT", "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_DECIMAL", "SQLSRV_SQLTYPE_FLOAT", "SQLSRV_SQLTYPE_INT", "SQLSRV_SQLTYPE_MONEY", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_VARCHAR"),
"bigint" => array( "SQLSRV_SQLTYPE_BIGINT", "SQLSRV_SQLTYPE_FLOAT", "SQLSRV_SQLTYPE_REAL"),
"decimal(18,5)" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_DECIMAL", "SQLSRV_SQLTYPE_FLOAT", "SQLSRV_SQLTYPE_MONEY", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_REAL", "SQLSRV_SQLTYPE_VARCHAR"),
"numeric(10,5)" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_DECIMAL", "SQLSRV_SQLTYPE_FLOAT", "SQLSRV_SQLTYPE_MONEY", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NUMERIC", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_REAL", "SQLSRV_SQLTYPE_SMALLMONEY", "SQLSRV_SQLTYPE_VARCHAR"),
"float" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_DECIMAL", "SQLSRV_SQLTYPE_FLOAT", "SQLSRV_SQLTYPE_MONEY", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_REAL", "SQLSRV_SQLTYPE_VARCHAR"),
"real" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_DECIMAL", "SQLSRV_SQLTYPE_FLOAT", "SQLSRV_SQLTYPE_MONEY", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NUMERIC", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_REAL", "SQLSRV_SQLTYPE_SMALLMONEY", "SQLSRV_SQLTYPE_VARCHAR" ));
$epsilon = 0.0001;
$conn = ae_connect();
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType: \n";
$success = true;
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// test each SQLSRV_SQLTYPE_ constants
foreach ( $sqlTypes as $sqlType )
{
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$sqlType = get_default_size_prec( $sqlType );
$paramOp = array( new bindParamOption( 1, null, null, $sqlType ), new bindParamOption( 2, null, null, $sqlType ));
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r, "prepareParamsOp", $paramOp );
if ( $keystore == "none" )
{
if ( $r === false )
{
$isCompat = false;
foreach ( $compatList[$dataType] as $compatType )
{
if ( stripos( $compatType, $sqlType ) !== false )
$isCompat = true;
}
if ( $isCompat )
{
echo "$sqlType should be compatible with $dataType\n";
$success = false;
}
}
}
else
{
if ( $r === false )
{
if ( stripos( "SQLSRV_SQLTYPE_" . $dataType, $sqlType ) !== false )
{
echo "$sqlType should be compatible with $dataType\n";
$success = false;
}
}
else
{
$sql = "SELECT * FROM $tbname";
$stmt = sqlsrv_query( $conn, $sql );
$row = sqlsrv_fetch_array( $stmt, SQLSRV_FETCH_ASSOC );
if ( $dataType == "float" || $dataType == "real" )
{
if ( abs( $row["c_det"] - $inputValues[0] ) > $epsilon || abs( $row["c_rand"] - $inputValues[1] ) > $epsilon )
{
echo "Incorrect output retrieved for datatype $dataType and sqlType $sqlType.\n";
$success = false;
}
}
else
{
if ( $row["c_det"] != $inputValues[0] || $row["c_rand"] != $inputValues[1] )
{
echo "Incorrect output retrieved for datatype $dataType and sqlType $sqlType.\n";
$success = false;
}
}
}
}
sqlsrv_query( $conn, "TRUNCATE TABLE $tbname" );
}
if ( $success )
echo "Test successfully.\n";
DropTable( $conn, $tbname );
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
Testing bit:
Test successfully.
Testing tinyint:
Test successfully.
Testing smallint:
Test successfully.
Testing int:
Test successfully.
Testing bigint:
Test successfully.
Testing decimal(18,5):
Test successfully.
Testing numeric(10,5):
Test successfully.
Testing float:
Test successfully.
Testing real:
Test successfully.

View file

@ -0,0 +1,97 @@
--TEST--
Test for inserting and retrieving encrypted string types data
Bind params using sqlsrv_prepare with all sql_type
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "char(5)", "varchar(max)", "nchar(5)", "nvarchar(max)" );
$compatList = array( "char(5)" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_NTEXT", "SQLSRV_SQLTYPE_TEXT", "SQLSRV_SQLTYPE_VARCHAR"),
"varchar(max)" => array( "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_NTEXT", "SQLSRV_SQLTYPE_TEXT", "SQLSRV_SQLTYPE_VARCHAR"),
"nchar(5)" => array( "SQLSRV_SQLTYPE_CHAR", "SQLSRV_SQLTYPE_NCHAR", "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_NTEXT", "SQLSRV_SQLTYPE_TEXT", "SQLSRV_SQLTYPE_VARCHAR"),
"nvarchar(max)" => array( "SQLSRV_SQLTYPE_NVARCHAR", "SQLSRV_SQLTYPE_NTEXT", "SQLSRV_SQLTYPE_TEXT", "SQLSRV_SQLTYPE_VARCHAR" ));
$conn = ae_connect();
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType: \n";
$success = true;
// create table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// test each SQLSRV_SQLTYPE_ constants
foreach ( $sqlTypes as $sqlType )
{
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$sqlType = get_default_size_prec( $sqlType );
$paramOp = array( new bindParamOption( 1, null, null, $sqlType ), new bindParamOption( 2, null, null, $sqlType ));
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r, "prepareParamsOp", $paramOp );
if ( $r === false )
{
if ( $keystore == "none" )
{
$isCompat = false;
foreach ( $compatList[$dataType] as $compatType )
{
if ( stripos( $compatType, $sqlType ) !== false )
$isCompat = true;
}
if ( $isCompat )
{
echo "$sqlType should be compatible with $dataType\n";
$success = false;
}
}
else
{
if ( stripos( "SQLSRV_SQLTYPE_" . $dataType, $sqlType ) !== false )
{
echo "$sqlType should be compatible with $dataType\n";
$success = false;
}
}
}
else
{
$sql = "SELECT * 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 "Incorrect output retrieved for datatype $dataType and sqlType $sqlType.\n";
$success = false;
}
}
sqlsrv_query( $conn, "TRUNCATE TABLE $tbname" );
}
if ( $success )
echo "Test successfully.\n";
DropTable( $conn, $tbname );
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
Testing char(5):
Test successfully.
Testing varchar(max):
Test successfully.
Testing nchar(5):
Test successfully.
Testing nvarchar(max):
Test successfully.

View file

@ -0,0 +1,60 @@
--TEST--
Test for inserting and retrieving encrypted string types data
Bind params using sqlsrv_prepare without any sql_type specified
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'AEData.inc';
include 'MsSetup.inc';
$dataTypes = array( "char(5)", "varchar(max)", "nchar(5)", "nvarchar(max)" );
$conn = ae_connect();
foreach ( $dataTypes as $dataType ) {
echo "\nTesting $dataType: \n";
// create table
$tbname = GetTempTableName( "", false );
$tbname = "test_numeric";
$colMetaArr = array( new columnMeta( $dataType, "c_det" ), new columnMeta( $dataType, "c_rand" ));
create_table( $conn, $tbname, $colMetaArr );
// insert a row
$inputValues = array_slice( ${explode( "(", $dataType )[0] . "_params"}, 1, 2 );
$r;
$stmt = insert_row( $conn, $tbname, array( $colMetaArr[0]->colName => $inputValues[0], $colMetaArr[1]->colName => $inputValues[1] ), $r );
if ( $r === false ) {
is_incompatible_types_error( $dataType, "default type" );
}
else {
echo "****Encrypted default type is compatible with encrypted $dataType****\n";
fetch_all( $conn, $tbname );
}
//DropTable( $conn, $tbname );
}
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
Testing char(5):
****Encrypted default type is compatible with encrypted char(5)****
c_det: -leng
c_rand: th, n
Testing varchar(max):
****Encrypted default type 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):
****Encrypted default type is compatible with encrypted nchar(5)****
c_det: -leng
c_rand: th Un
Testing nvarchar(max):
****Encrypted default type 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).

View file

@ -0,0 +1,106 @@
--TEST--
Test for binding output parameter of encrypted values for a sample emplolyee table
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'MsSetup.inc';
include 'AEData.inc';
$conn = ae_connect();
$tbname = 'employee';
$colMetaArr = array( new columnMeta( "int", "PersonID", "NOT NULL Identity (1,1)" ),
new columnMeta( "varchar(255)", "FirstName", "NOT NULL" ),
new columnMeta( "varchar(255)", "LastName" ),
new columnMeta( "varchar(255)", "Address" ),
new columnMeta( "varchar(255)", "City" ));
create_table( $conn, $tbname, $colMetaArr );
// Create a Store Procedure
$spname = 'InOutRet_Params';
$createSpSql = "CREATE PROCEDURE $spname (
@pPersonID int, @MatchingRecs int OUTPUT) AS
SELECT PersonID, FirstName, LastName, Address, City
FROM $tbname WHERE PersonID=@pPersonID;
SELECT @MatchingRecs=count(*) FROM $tbname WHERE
PersonID=@pPersonID;
RETURN 100";
sqlsrv_query( $conn, $createSpSql );
// Create a select Store Procedure
$sspname = 'getInfo';
$selectSpSql = "CREATE PROCEDURE $sspname (
@FirstName varchar(255) OUTPUT, @LastName varchar(255) OUTPUT,
@Address varchar(255) OUTPUT, @City varchar(255) OUTPUT, @PersonID int) AS
SELECT @FirstName = FirstName, @LastName = LastName, @Address = Address, @City = City
FROM $tbname WHERE PersonID=@PersonID";
sqlsrv_query( $conn, $selectSpSql );
// Insert data
$firstNameParams = array( 'Luke', 'Tahir', 'Gwen', 'Mike', 'Sarah' );
$lastNameParams = array( 'Duke', 'Chaudry', 'Wheeler', 'Leibskind', 'Ackerman' );
$addressParams = array( '2130 Boars Nest', '83 First Street', '842 Vine Ave.', '33 Elm St.', '440 U.S. 11' );
$cityParams = array( 'Hazard Co', 'Brooklyn', 'New York', 'Binghamton', 'Roselle' );
for ( $i = 0; $i < 5; $i++ )
{
$inputs = array( "FirstName" => $firstNameParams[$i],
"LastName" => $lastNameParams[$i],
"Address" => $addressParams[$i],
"City" => $cityParams[$i] );
$stmt = insert_row( $conn, $tbname, $inputs );
}
// call Store Procedure
$callSpSql = "{? = CALL $spname (?, ?)}";
$retParam = 0;
$pPersonID = 1;
$cbOutParam = 0;
$stmt = sqlsrv_prepare( $conn, $callSpSql, array( array( &$retParam, SQLSRV_PARAM_OUT ), array( $pPersonID, SQLSRV_PARAM_IN ), array( &$cbOutParam, SQLSRV_PARAM_OUT )));
sqlsrv_execute( $stmt );
sqlsrv_next_result( $stmt );
if ( sqlsrv_errors() )
{
var_dump( sqlsrv_errors() );
}
print ( "retParam: " . $retParam . "\n" );
print ( "pPersonID: " . $pPersonID . "\n" );
print ( "cbOutParam: " . $cbOutParam . "\n" );
// Retrieve all data through output params
$outSql = get_callProcSql_placeholders( $sspname, 5 );
$firstNameOut = '';
$lastNameOut = '';
$addressOut = '';
$cityOut = '';
$pPersonID = 2;
$stmt = sqlsrv_prepare( $conn, $outSql, array( array( &$firstNameOut, SQLSRV_PARAM_OUT ), array( &$lastNameOut, SQLSRV_PARAM_OUT ), array( &$addressOut, SQLSRV_PARAM_OUT ), array( &$cityOut, SQLSRV_PARAM_OUT ), array( $pPersonID, SQLSRV_PARAM_IN )));
sqlsrv_execute( $stmt );
if ( sqlsrv_errors() )
{
var_dump( sqlsrv_errors() );
}
print ( "firstNameOut: " . $firstNameOut . "\n" );
print ( "lastNameOut: " . $lastNameOut . "\n" );
print ( "addressOut: " . $addressOut . "\n" );
print ( "cityOut: " . $cityOut . "\n" );
print ( "pPersonID: " . $pPersonID . "\n" );
sqlsrv_query( $conn, "DROP PROCEDURE $spname" );
sqlsrv_query( $conn, "DROP PROCEDURE $sspname" );
sqlsrv_query( $conn, "DROP TABLE $tbname" );
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
retParam: 100
pPersonID: 1
cbOutParam: 1
firstNameOut: Tahir
lastNameOut: Chaudry
addressOut: 83 First Street
cityOut: Brooklyn
pPersonID: 2

View file

@ -0,0 +1,165 @@
--TEST--
Test for binding output parameter of encrypted values for all types
--SKIPIF--
--FILE--
<?php
include 'MsCommon.inc';
include 'MsSetup.inc';
include 'AEData.inc';
$conn = ae_connect();
// Create the table
$tbname = GetTempTableName( "", false );
$colMetaArr = array( new columnMeta( "int", "c1_int" ),
new columnMeta( "smallint", "c2_smallint" ),
new columnMeta( "tinyint", "c3_tinyint" ),
new columnMeta( "bit", "c4_bit" ),
new columnMeta( "bigint", "c5_bigint" ),
new columnMeta( "decimal(18,5)", "c6_decimal" ),
new columnMeta( "numeric(10,5)", "c7_numeric" ),
new columnMeta( "float", "c8_float" ),
new columnMeta( "real", "c9_real" ),
new columnMeta( "date", "c10_date" ),
new columnMeta( "datetime", "c11_datetime" ),
new columnMeta( "datetime2", "c12_datetime2" ),
new columnMeta( "datetimeoffset", "c13_datetimeoffset" ),
new columnMeta( "time", "c14_time" ),
new columnMeta( "char(5)", "c15_char" ),
new columnMeta( "varchar(max)", "c16_varchar" ),
new columnMeta( "nchar(5)", "c17_nchar" ),
new columnMeta( "nvarchar(max)", "c18_nvarchar" ));
create_table( $conn, $tbname, $colMetaArr );
// Create a Store Procedure
$spname = 'selectAllColumns';
$spSql = "CREATE PROCEDURE $spname (
@c1_int int OUTPUT, @c2_smallint smallint OUTPUT,
@c3_tinyint tinyint OUTPUT, @c4_bit bit OUTPUT,
@c5_bigint bigint OUTPUT, @c6_decimal decimal(18,5) OUTPUT,
@c7_numeric numeric(10,5) OUTPUT, @c8_float float OUTPUT,
@c9_real real OUTPUT, @c10_date date OUTPUT,
@c11_datetime datetime OUTPUT, @c12_datetime2 datetime2 OUTPUT,
@c13_datetimeoffset datetimeoffset OUTPUT, @c14_time time OUTPUT,
@c15_char char(5) OUTPUT, @c16_varchar varchar(max) OUTPUT,
@c17_nchar nchar(5) OUTPUT, @c18_nvarchar nvarchar(max) OUTPUT) AS
SELECT @c1_int = c1_int, @c2_smallint = c2_smallint,
@c3_tinyint = c3_tinyint, @c4_bit = c4_bit,
@c5_bigint = c5_bigint, @c6_decimal = c6_decimal,
@c7_numeric = c7_numeric, @c8_float = c8_float,
@c9_real = c9_real, @c10_date = c10_date,
@c11_datetime = c11_datetime, @c12_datetime2 = c12_datetime2,
@c13_datetimeoffset = c13_datetimeoffset, @c14_time = c14_time,
@c15_char = c15_char, @c16_varchar = c16_varchar,
@c17_nchar = c17_nchar, @c18_nvarchar = c18_nvarchar
FROM $tbname";
sqlsrv_query( $conn, $spSql );
// Insert data
$inputs = array( "c1_int" => 2147483647,
"c2_smallint" => 32767,
"c3_tinyint" => 255,
"c4_bit" => 1,
"c5_bigint" => 922337203685479936,
"c6_decimal" => 9223372036854.80000,
"c7_numeric" => 21474.83647,
"c8_float" => 9223372036.8548,
"c9_real" => 2147.483,
"c10_date" => '9999-12-31',
"c11_datetime" => '9999-12-31 23:59:59.997',
"c12_datetime2" => '9999-12-31 23:59:59.9999999',
"c13_datetimeoffset" => '9999-12-31 23:59:59.9999999 +14:00',
"c14_time" => '23:59:59.9999999',
"c15_char" => 'th, n',
"c16_varchar" => 'This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.',
"c17_nchar" => 'th Un',
"c18_nvarchar" => '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).' );
$stmt = insert_row( $conn, $tbname, $inputs );
// Call store procedure
$outSql = get_callProcSql_placeholders( $spname, count( $inputs ));
$intOut = 0;
$smallintOut = 0;
$tinyintOut = 0;
$bitOut = 0;
$bigintOut = 0.0;
$decimalOut = 0.0;
$numericOut = 0.0;
$floatOut = 0.0;
$realOut = 0.0;
$dateOut = '';
$datetimeOut = '';
$datetime2Out = '';
$datetimeoffsetOut = '';
$timeOut = '';
$charOut = '';
$varcharOut = '';
$ncharOut = '';
$nvarcharOut = '';
$stmt = sqlsrv_prepare( $conn, $outSql, array( array( &$intOut, SQLSRV_PARAM_OUT ),
array( &$smallintOut, SQLSRV_PARAM_OUT ),
array( &$tinyintOut, SQLSRV_PARAM_OUT ),
array( &$bitOut, SQLSRV_PARAM_OUT ),
array( &$bigintOut, SQLSRV_PARAM_OUT ),
array( &$decimalOut, SQLSRV_PARAM_OUT ),
array( &$numericOut, SQLSRV_PARAM_OUT ),
array( &$floatOut, SQLSRV_PARAM_OUT ),
array( &$realOut, SQLSRV_PARAM_OUT ),
array( &$dateOut, SQLSRV_PARAM_OUT ),
array( &$datetimeOut, SQLSRV_PARAM_OUT ),
array( &$datetime2Out, SQLSRV_PARAM_OUT ),
array( &$datetimeoffsetOut, SQLSRV_PARAM_OUT ),
array( &$timeOut, SQLSRV_PARAM_OUT ),
array( &$charOut, SQLSRV_PARAM_OUT ),
array( &$varcharOut, SQLSRV_PARAM_OUT ),
array( &$ncharOut, SQLSRV_PARAM_OUT ),
array( &$nvarcharOut, SQLSRV_PARAM_OUT )));
sqlsrv_execute( $stmt );
print ( "intOut: " . $intOut . "\n" );
print ( "smallintOut: " . $smallintOut . "\n" );
print ( "tinyintOut: " . $tinyintOut . "\n" );
print ( "bitOut: " . $bitOut . "\n" );
print ( "bigintOut: " . $bigintOut . "\n" );
print ( "decimalOut: " . $decimalOut . "\n" );
print ( "numericOut: " . $numericOut . "\n" );
print ( "floatOut: " . $floatOut . "\n" );
print ( "realOut: " . $realOut . "\n" );
print ( "dateOut: " . $dateOut . "\n" );
print ( "datetimeOut: " . $datetimeOut . "\n" );
print ( "datetime2Out: " . $datetime2Out . "\n" );
print ( "datetimeoffsetOut: " . $datetimeoffsetOut . "\n" );
print ( "timeOut: " . $timeOut . "\n" );
print ( "charOut: " . $charOut . "\n" );
print ( "varcharOut: " . $varcharOut . "\n" );
print ( "ncharOut: " . $ncharOut . "\n" );
print ( "nvarcharOut: " . $nvarcharOut . "\n" );
sqlsrv_query( $conn, "DROP PROCEDURE $spname" );
sqlsrv_query( $conn, "DROP TABLE $tbname" );
sqlsrv_free_stmt( $stmt );
sqlsrv_close( $conn );
?>
--EXPECT--
intOut: 2147483647
smallintOut: 32767
tinyintOut: 255
bitOut: 1
bigintOut: 9.2233720368548E+17
decimalOut: 9223372036854.8
numericOut: 21474.83647
floatOut: 9223372036.8548
realOut: 2147.4829101562
dateOut: 9999-12-31
datetimeOut: 9999-12-31 23:59:59.997
datetime2Out: 9999-12-31 23:59:59.9999999
datetimeoffsetOut: 9999-12-31 23:59:59.9999999 +14:00
timeOut: 23:59:59.9999999
charOut: th, n
varcharOut: This large row size can cause errors (such as error 512) during some normal operations, such as a clustered index key update, or sorts of the full column set, which users cannot anticipate until performing an operation.
ncharOut: th Un
nvarcharOut: 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).