PDO tests for retrieving data as output params using various PDO param types
This commit is contained in:
parent
a24a8a7035
commit
7a6a8d5a72
210
test/functional/pdo_sqlsrv/pdo_ae_output_param_binary_size.phpt
Normal file
210
test/functional/pdo_sqlsrv/pdo_ae_output_param_binary_size.phpt
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
--TEST--
|
||||||
|
Test for retrieving encrypted data of binary types of various sizes as output parameters
|
||||||
|
--DESCRIPTION--
|
||||||
|
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||||
|
--ENV--
|
||||||
|
PHPT_EXEC=true
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require('skipif_mid-refactor.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
|
||||||
|
$dataTypes = array("binary", "varbinary", "varbinary(max)");
|
||||||
|
$lengths = array(1, 2, 4, 8, 64, 512, 4000);
|
||||||
|
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.", "07006" => "Restricted data type attribute violation");
|
||||||
|
|
||||||
|
$pdoParamTypes = array(
|
||||||
|
PDO::PARAM_BOOL, // 5
|
||||||
|
PDO::PARAM_NULL, // 0
|
||||||
|
PDO::PARAM_INT, // 1
|
||||||
|
PDO::PARAM_STR, // 2
|
||||||
|
PDO::PARAM_LOB // 3
|
||||||
|
);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
function printValues($msg, $det, $rand, $input0, $input1)
|
||||||
|
{
|
||||||
|
echo $msg;
|
||||||
|
echo "input 0: "; var_dump($input0);
|
||||||
|
echo "fetched: "; var_dump($det);
|
||||||
|
echo "input 1: "; var_dump($input1);
|
||||||
|
echo "fetched: "; var_dump($rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
function convert2Hex($ch, $length)
|
||||||
|
{
|
||||||
|
// Without AE, the binary values returned as integers will
|
||||||
|
// have lengths no more than 4 times the original hex string value
|
||||||
|
// (e.g. string(8) "65656565") - limited by the buffer sizes
|
||||||
|
if (!isAEConnected()) {
|
||||||
|
$count = ($length <= 2) ? $length : 4;
|
||||||
|
} else {
|
||||||
|
$count = $length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str_repeat(bin2hex($ch), $count);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutputBinary($inout)
|
||||||
|
{
|
||||||
|
global $pdoParamTypes, $dataTypes, $lengths, $errors;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn = connect();
|
||||||
|
$tbname = "test_binary_types";
|
||||||
|
$spname = "test_binary_proc";
|
||||||
|
$ch0 = 'd';
|
||||||
|
$ch1 = 'e';
|
||||||
|
|
||||||
|
foreach ($dataTypes as $dataType) {
|
||||||
|
$maxtype = strpos($dataType, "(max)");
|
||||||
|
foreach ($lengths as $length) {
|
||||||
|
if ($maxtype !== false) {
|
||||||
|
$type = $dataType;
|
||||||
|
} else {
|
||||||
|
$type = "$dataType($length)";
|
||||||
|
}
|
||||||
|
trace("\nTesting $type:\n");
|
||||||
|
|
||||||
|
//create and populate table
|
||||||
|
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||||
|
createTable($conn, $tbname, $colMetaArr);
|
||||||
|
$input0 = str_repeat($ch0, $length);
|
||||||
|
$input1 = str_repeat($ch1, $length);
|
||||||
|
$ord0 = convert2Hex($ch0, $length);
|
||||||
|
$ord1 = convert2Hex($ch1, $length);
|
||||||
|
insertRow($conn, $tbname, array("c_det" => new BindParamOp(1, $input0, "PDO::PARAM_LOB", 0, "PDO::SQLSRV_ENCODING_BINARY"),
|
||||||
|
"c_rand" => new BindParamOp(2, $input1, "PDO::PARAM_LOB", 0, "PDO::SQLSRV_ENCODING_BINARY")), "prepareBindParam");
|
||||||
|
|
||||||
|
// fetch with PDO::bindParam using a stored procedure
|
||||||
|
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||||
|
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||||
|
createProc($conn, $spname, $procArgs, $procCode);
|
||||||
|
|
||||||
|
// call stored procedure
|
||||||
|
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||||
|
foreach ($pdoParamTypes as $pdoParamType) {
|
||||||
|
$stmt = $conn->prepare($outSql);
|
||||||
|
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||||
|
|
||||||
|
if ($inout && $pdoParamType != PDO::PARAM_STR) {
|
||||||
|
// Currently do not support getting binary as strings + INOUT param
|
||||||
|
// See VSO 2829 for details
|
||||||
|
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||||
|
} else {
|
||||||
|
$paramType = $pdoParamType;
|
||||||
|
}
|
||||||
|
|
||||||
|
$det = "";
|
||||||
|
$rand = "";
|
||||||
|
if ($pdoParamType == PDO::PARAM_STR || $pdoParamType == PDO::PARAM_LOB) {
|
||||||
|
$stmt->bindParam(1, $det, $paramType, $length, PDO::SQLSRV_ENCODING_BINARY);
|
||||||
|
$stmt->bindParam(2, $rand, $paramType, $length, PDO::SQLSRV_ENCODING_BINARY);
|
||||||
|
} elseif ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||||
|
$det = $rand = 0;
|
||||||
|
$stmt->bindParam(1, $det, $paramType, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
|
||||||
|
$stmt->bindParam(2, $rand, $paramType, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
|
||||||
|
} else {
|
||||||
|
$stmt->bindParam(1, $det, $paramType, $length);
|
||||||
|
$stmt->bindParam(2, $rand, $paramType, $length);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$errMsg = "****$dataType as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_STR) {
|
||||||
|
if ($det !== $input0 || $rand !== $input1) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} elseif ($pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
// for boolean values, they should all be bool(true)
|
||||||
|
// because all floats are non-zeroes
|
||||||
|
// This only occurs without AE
|
||||||
|
// With AE enabled, this would have caused an exception
|
||||||
|
if (!$det || !$rand) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// $pdoParamType is PDO::PARAM_INT
|
||||||
|
// This only occurs without AE -- likely a rare use case
|
||||||
|
// With AE enabled, this would have caused an exception
|
||||||
|
if (strval($det) != $ord0 || strval($rand) != $ord1) {
|
||||||
|
printValues($errMsg, $det, $rand, $ord0, $ord1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||||
|
// Expected error IMSSP: "An invalid PHP type was specified
|
||||||
|
// as an output parameter. DateTime objects, NULL values, and
|
||||||
|
// streams cannot be specified as output parameters."
|
||||||
|
$found = strpos($message, $errors['IMSSP']);
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} elseif ($pdoParamType == PDO::PARAM_BOOL || PDO::PARAM_INT) {
|
||||||
|
if (isAEConnected()) {
|
||||||
|
if ($pdoParamType == PDO::PARAM_INT) {
|
||||||
|
// Expected to fail with this message
|
||||||
|
$error = "String data, right truncated for output parameter";
|
||||||
|
$found = strpos($message, $error);
|
||||||
|
} else {
|
||||||
|
// PDO::PARAM_BOOL -
|
||||||
|
// Expected error 07006 with AE enabled:
|
||||||
|
// "Restricted data type attribute violation"
|
||||||
|
// The data value returned for a parameter bound as
|
||||||
|
// SQL_PARAM_INPUT_OUTPUT or SQL_PARAM_OUTPUT could not
|
||||||
|
// be converted to the data type identified by the
|
||||||
|
// ValueType argument in SQLBindParameter.
|
||||||
|
$found = strpos($message, $errors['07006']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// When not AE enabled, expected to fail with something like this message
|
||||||
|
// "Implicit conversion from data type nvarchar(max) to binary is not allowed. Use the CONVERT function to run this query."
|
||||||
|
// Sometimes it's about nvarchar too
|
||||||
|
$error = "to $dataType is not allowed. Use the CONVERT function to run this query.";
|
||||||
|
$found = strpos($message, $error);
|
||||||
|
}
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// catch all
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($stmt);
|
||||||
|
unset($conn);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutputBinary(false);
|
||||||
|
testOutputBinary(true);
|
||||||
|
|
||||||
|
echo "Done\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
// drop the temporary table and stored procedure in case
|
||||||
|
// the test failed without dropping them
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
$tbname = "test_binary_types";
|
||||||
|
$spname = "test_binary_proc";
|
||||||
|
$conn = connect();
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
unset($conn);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Done
|
171
test/functional/pdo_sqlsrv/pdo_ae_output_param_char_size.phpt
Normal file
171
test/functional/pdo_sqlsrv/pdo_ae_output_param_char_size.phpt
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
--TEST--
|
||||||
|
Test for retrieving encrypted data of char types of various sizes as output parameters
|
||||||
|
--DESCRIPTION--
|
||||||
|
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||||
|
--ENV--
|
||||||
|
PHPT_EXEC=true
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require('skipif_mid-refactor.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
|
||||||
|
$dataTypes = array("char", "varchar", "varchar(max)");
|
||||||
|
$lengths = array(1, 8, 64, 512, 4000);
|
||||||
|
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.",
|
||||||
|
"22003" => "Numeric value out of range");
|
||||||
|
|
||||||
|
$pdoParamTypes = array(
|
||||||
|
PDO::PARAM_BOOL, // 5
|
||||||
|
PDO::PARAM_NULL, // 0
|
||||||
|
PDO::PARAM_INT, // 1
|
||||||
|
PDO::PARAM_STR, // 2
|
||||||
|
PDO::PARAM_LOB // 3
|
||||||
|
);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
function printValues($msg, $det, $rand, $input0, $input1)
|
||||||
|
{
|
||||||
|
echo $msg;
|
||||||
|
echo "input 0: "; var_dump($input0);
|
||||||
|
echo "fetched: "; var_dump($det);
|
||||||
|
echo "input 1: "; var_dump($input1);
|
||||||
|
echo "fetched: "; var_dump($rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutputChars($inout)
|
||||||
|
{
|
||||||
|
global $pdoParamTypes, $dataTypes, $lengths, $errors;
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
$conn = connect();
|
||||||
|
$tbname = "test_char_types";
|
||||||
|
$spname = "test_char_proc";
|
||||||
|
|
||||||
|
foreach ($dataTypes as $dataType) {
|
||||||
|
$maxtype = strpos($dataType, "(max)");
|
||||||
|
foreach ($lengths as $length) {
|
||||||
|
if ($maxtype !== false) {
|
||||||
|
$type = $dataType;
|
||||||
|
} else {
|
||||||
|
$type = "$dataType($length)";
|
||||||
|
}
|
||||||
|
trace("\nTesting $type:\n");
|
||||||
|
|
||||||
|
//create and populate table
|
||||||
|
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||||
|
createTable($conn, $tbname, $colMetaArr);
|
||||||
|
$input0 = str_repeat("1", $length);
|
||||||
|
$input1 = str_repeat("2", $length);
|
||||||
|
insertRow($conn, $tbname, array("c_det" => $input0,
|
||||||
|
"c_rand" => $input1));
|
||||||
|
|
||||||
|
// fetch with PDO::bindParam using a stored procedure
|
||||||
|
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||||
|
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||||
|
createProc($conn, $spname, $procArgs, $procCode);
|
||||||
|
|
||||||
|
// call stored procedure
|
||||||
|
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||||
|
foreach ($pdoParamTypes as $pdoParamType) {
|
||||||
|
$det = "";
|
||||||
|
$rand = "";
|
||||||
|
$stmt = $conn->prepare($outSql);
|
||||||
|
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||||
|
|
||||||
|
if ($inout) {
|
||||||
|
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||||
|
} else {
|
||||||
|
$paramType = $pdoParamType;
|
||||||
|
}
|
||||||
|
|
||||||
|
$len = $length;
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||||
|
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||||
|
$det = $rand = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->bindParam(1, $det, $paramType, $len);
|
||||||
|
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt->execute();
|
||||||
|
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($length < 64 && $pdoParamType != PDO::PARAM_STR) {
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
// For boolean values, they should all be bool(true)
|
||||||
|
// because all "string literals" are non-zeroes
|
||||||
|
if (!$det || !$rand) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// $pdoParamType = PDO::PARAM_INT
|
||||||
|
// Expect numeric values
|
||||||
|
if ($det != intval($input0) || $rand != intval($input1)) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ($det !== $input0 || $rand !== $input1) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||||
|
// Expected error IMSSP: "An invalid PHP type was specified
|
||||||
|
// as an output parameter. DateTime objects, NULL values, and
|
||||||
|
// streams cannot be specified as output parameters."
|
||||||
|
$found = strpos($message, $errors['IMSSP']);
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} elseif ($pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
if (isAEConnected()) {
|
||||||
|
// Expected error 22003: "Numeric value out of range"
|
||||||
|
$found = strpos($message, $errors['22003']);
|
||||||
|
} else {
|
||||||
|
// When not AE enabled, expected to fail to convert
|
||||||
|
// whatever char type to integers
|
||||||
|
$error = "Error converting data type $dataType to int";
|
||||||
|
$found = strpos($message, $error);
|
||||||
|
}
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($stmt);
|
||||||
|
unset($conn);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutputChars(false);
|
||||||
|
testOutputChars(true);
|
||||||
|
|
||||||
|
echo "Done\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
// drop the temporary table and stored procedure in case
|
||||||
|
// the test failed without dropping them
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
$tbname = "test_char_types";
|
||||||
|
$spname = "test_char_proc";
|
||||||
|
$conn = connect();
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
unset($conn);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Done
|
204
test/functional/pdo_sqlsrv/pdo_ae_output_param_datetimes.phpt
Normal file
204
test/functional/pdo_sqlsrv/pdo_ae_output_param_datetimes.phpt
Normal file
|
@ -0,0 +1,204 @@
|
||||||
|
--TEST--
|
||||||
|
Test for retrieving encrypted data of datetimes as output parameters
|
||||||
|
--DESCRIPTION--
|
||||||
|
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||||
|
--ENV--
|
||||||
|
PHPT_EXEC=true
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require('skipif_mid-refactor.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
|
||||||
|
$dataTypes = array("datetime2", "datetimeoffset", "time");
|
||||||
|
$precisions = array(/*0, */1, 2, 4, 7);
|
||||||
|
$inputValuesInit = array("datetime2" => array("0001-01-01 00:00:00", "9999-12-31 23:59:59"),
|
||||||
|
"datetimeoffset" => array("0001-01-01 00:00:00 -14:00", "9999-12-31 23:59:59 +14:00"),
|
||||||
|
"time" => array("00:00:00", "23:59:59"));
|
||||||
|
|
||||||
|
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.", "07006" => "Restricted data type attribute violation");
|
||||||
|
|
||||||
|
$pdoParamTypes = array(
|
||||||
|
PDO::PARAM_BOOL, // 5
|
||||||
|
PDO::PARAM_NULL, // 0
|
||||||
|
PDO::PARAM_INT, // 1
|
||||||
|
PDO::PARAM_STR, // 2
|
||||||
|
PDO::PARAM_LOB // 3
|
||||||
|
);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// compareDate() returns true when the date/time values are basically the same
|
||||||
|
// e.g. 00:00:00.000 is the same as 00:00:00
|
||||||
|
function compareDate($dtout, $dtin, $dataType)
|
||||||
|
{
|
||||||
|
if ($dataType == "datetimeoffset") {
|
||||||
|
$dtarr = explode(' ', $dtin);
|
||||||
|
if (strpos($dtout, $dtarr[0]) !== false && strpos($dtout, $dtarr[1]) !== false && strpos($dtout, $dtarr[2]) !== false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (strpos($dtout, $dtin) !== false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function printValues($msg, $det, $rand, $inputValues)
|
||||||
|
{
|
||||||
|
echo $msg;
|
||||||
|
echo "input 0: "; var_dump($inputValues[0]);
|
||||||
|
echo "fetched: "; var_dump($det);
|
||||||
|
echo "input 1: "; var_dump($inputValues[1]);
|
||||||
|
echo "fetched: "; var_dump($rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutputDatetimes($inout)
|
||||||
|
{
|
||||||
|
global $pdoParamTypes, $dataTypes, $precisions, $inputValuesInit, $errors;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn = connect();
|
||||||
|
|
||||||
|
$tbname = "test_datetimes_types";
|
||||||
|
$spname = "test_datetimes_proc";
|
||||||
|
|
||||||
|
foreach ($dataTypes as $dataType) {
|
||||||
|
foreach ($precisions as $precision) {
|
||||||
|
// change the input values depending on the precision
|
||||||
|
$inputValues[0] = $inputValuesInit[$dataType][0];
|
||||||
|
$inputValues[1] = $inputValuesInit[$dataType][1];
|
||||||
|
if ($precision != 0) {
|
||||||
|
if ($dataType == "datetime2") {
|
||||||
|
$inputValues[1] .= "." . str_repeat("9", $precision);
|
||||||
|
} else if ($dataType == "datetimeoffset") {
|
||||||
|
$inputPieces = explode(" ", $inputValues[1]);
|
||||||
|
$inputValues[1] = $inputPieces[0] . " " . $inputPieces[1] . "." . str_repeat("9", $precision) . " " . $inputPieces[2];
|
||||||
|
} else if ($dataType == "time") {
|
||||||
|
$inputValues[0] .= "." . str_repeat("0", $precision);
|
||||||
|
$inputValues[1] .= "." . str_repeat("9", $precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = "$dataType($precision)";
|
||||||
|
trace("\nTesting $type:\n");
|
||||||
|
|
||||||
|
//create and populate table
|
||||||
|
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||||
|
createTable($conn, $tbname, $colMetaArr);
|
||||||
|
|
||||||
|
$stmt = insertRow($conn, $tbname, array("c_det" => $inputValues[0], "c_rand" => $inputValues[1] ), null);
|
||||||
|
|
||||||
|
// fetch with PDO::bindParam using a stored procedure
|
||||||
|
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||||
|
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||||
|
createProc($conn, $spname, $procArgs, $procCode);
|
||||||
|
|
||||||
|
// call stored procedure
|
||||||
|
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||||
|
foreach ($pdoParamTypes as $pdoParamType) {
|
||||||
|
$det = 0;
|
||||||
|
$rand = 0;
|
||||||
|
$stmt = $conn->prepare($outSql);
|
||||||
|
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||||
|
|
||||||
|
if ($inout) {
|
||||||
|
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||||
|
} else {
|
||||||
|
$paramType = $pdoParamType;
|
||||||
|
}
|
||||||
|
|
||||||
|
$len = 2048;
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||||
|
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->bindParam(1, $det, $paramType, $len);
|
||||||
|
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt->execute();
|
||||||
|
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
// What follows only happens with OUTPUT parameter
|
||||||
|
if ($inout) {
|
||||||
|
echo "Any datetime type as INOUT param should have caused an exception!\n";
|
||||||
|
}
|
||||||
|
if ($pdoParamType == PDO::PARAM_INT) {
|
||||||
|
// Expect an integer, the first part of the date time string
|
||||||
|
$ch = ($dataType == "time")? ':' : '-';
|
||||||
|
$tmp0 = explode($ch, $inputValues[0]);
|
||||||
|
$tmp1 = explode($ch, $inputValues[1]);
|
||||||
|
|
||||||
|
if ($det != intval($tmp0[0]) || $rand != intval($tmp1[0])) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} elseif (!compareDate($det, $inputValues[0], $dataType) ||
|
||||||
|
!compareDate($rand, $inputValues[1], $dataType)) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:\n$message****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||||
|
// Expected error IMSSP: "An invalid PHP type was specified
|
||||||
|
// as an output parameter. DateTime objects, NULL values, and
|
||||||
|
// streams cannot be specified as output parameters."
|
||||||
|
$found = strpos($message, $errors['IMSSP']);
|
||||||
|
} elseif (isAEConnected()) {
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
// Expected error 07006: "Restricted data type attribute violation"
|
||||||
|
// What does this error mean?
|
||||||
|
// The data value returned for a parameter bound as
|
||||||
|
// SQL_PARAM_INPUT_OUTPUT or SQL_PARAM_OUTPUT could not
|
||||||
|
// be converted to the data type identified by the
|
||||||
|
// ValueType argument in SQLBindParameter.
|
||||||
|
$found = strpos($message, $errors['07006']);
|
||||||
|
} else {
|
||||||
|
$error = "Invalid character value for cast specification";
|
||||||
|
$found = strpos($message, $error);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
$error = "Operand type clash: int is incompatible with $dataType";
|
||||||
|
} else {
|
||||||
|
$error = "Error converting data type nvarchar to $dataType";
|
||||||
|
}
|
||||||
|
$found = strpos($message, $error);
|
||||||
|
}
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($stmt);
|
||||||
|
unset($conn);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutputDatetimes(false);
|
||||||
|
testOutputDatetimes(true);
|
||||||
|
|
||||||
|
echo "Done\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
// drop the temporary table and stored procedure in case
|
||||||
|
// the test failed without dropping them
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
$tbname = "test_datetimes_types";
|
||||||
|
$spname = "test_datetimes_proc";
|
||||||
|
$conn = connect();
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
unset($conn);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Done
|
242
test/functional/pdo_sqlsrv/pdo_ae_output_param_decimals.phpt
Normal file
242
test/functional/pdo_sqlsrv/pdo_ae_output_param_decimals.phpt
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
--TEST--
|
||||||
|
Test for retrieving encrypted data of decimals/numerics as output parameters
|
||||||
|
--DESCRIPTION--
|
||||||
|
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||||
|
--ENV--
|
||||||
|
PHPT_EXEC=true
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require('skipif_mid-refactor.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
|
||||||
|
$dataTypes = array("decimal", "numeric");
|
||||||
|
$precisions = array(1 => array(0, 1),
|
||||||
|
4 => array(0, 1, 4),
|
||||||
|
16 => array(0, 1, 4, 16),
|
||||||
|
38 => array(0, 1, 4, 16, 38));
|
||||||
|
$inputValuesInit = array(92233720368547758089223372036854775808, -92233720368547758089223372036854775808);
|
||||||
|
$inputPrecision = 38;
|
||||||
|
|
||||||
|
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.");
|
||||||
|
|
||||||
|
$pdoParamTypes = array(
|
||||||
|
PDO::PARAM_BOOL, // 5
|
||||||
|
PDO::PARAM_NULL, // 0
|
||||||
|
PDO::PARAM_INT, // 1
|
||||||
|
PDO::PARAM_STR, // 2
|
||||||
|
PDO::PARAM_LOB // 3
|
||||||
|
);
|
||||||
|
|
||||||
|
function printValues($msg, $det, $rand, $inputValues)
|
||||||
|
{
|
||||||
|
echo $msg;
|
||||||
|
echo "input 0: "; var_dump($inputValues[0]);
|
||||||
|
echo "fetched: "; var_dump($det);
|
||||||
|
echo "input 1: "; var_dump($inputValues[1]);
|
||||||
|
echo "fetched: "; var_dump($rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this function returns true if the floats are more different than expected
|
||||||
|
function compareFloats($actual, $expected)
|
||||||
|
{
|
||||||
|
$epsilon = 0.00001;
|
||||||
|
$diff = abs(($actual - $expected) / $expected);
|
||||||
|
return ($diff > $epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
// function compareIntegers() returns false when the fetched values
|
||||||
|
// are different from the expected inputs
|
||||||
|
function compareIntegers($det, $rand, $inputValues, $pdoParamType)
|
||||||
|
{
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
// See GitHub issue 707 - Fix this method when the problem is addressed
|
||||||
|
//
|
||||||
|
// Assume $pdoParamType is PDO::PARAM_BOOL or PDO::PARAM_INT
|
||||||
|
if (is_string($det)) {
|
||||||
|
return (!compareFloats(floatval($det), $inputValues[0])
|
||||||
|
&& !compareFloats(floatval($rand), $inputValues[1]));
|
||||||
|
} elseif ($pdoParamType == PDO::PARAM_INT) {
|
||||||
|
$input0 = floor($inputValues[0]); // the positive float
|
||||||
|
$input1 = ceil($inputValues[1]); // the negative float
|
||||||
|
|
||||||
|
return ($det == $input0 && $rand == $input1);
|
||||||
|
} else {
|
||||||
|
// $pdoParamType == PDO::PARAM_BOOL
|
||||||
|
// Expect bool(true) or bool(false) depending on the rounded input values
|
||||||
|
// But with AE enabled (aforementioned GitHub issue), the fetched values
|
||||||
|
// are floats instead, which should be fixed
|
||||||
|
$input0 = floor($inputValues[0]); // the positive float
|
||||||
|
$input1 = ceil($inputValues[1]); // the negative float
|
||||||
|
if (isAEConnected()) {
|
||||||
|
$det = boolval(floor($det));
|
||||||
|
$rand = boolval(ceil($rand));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ($det == boolval($input0) && $rand == boolval($input1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function compareDecimals() returns false when the fetched values
|
||||||
|
// are different from the inputs, based on precision, scale
|
||||||
|
function compareDecimals($det, $rand, $inputValues, $pdoParamType, $precision, $scale)
|
||||||
|
{
|
||||||
|
// Assume $pdoParamType is PDO::PARAM_STR
|
||||||
|
for ($i = 0; $i < 2; $i++) {
|
||||||
|
$inputStr = strval($inputValues[$i]);
|
||||||
|
$fetchedStr = ($i == 0) ? strval(floatval($det)) : strval(floatval($rand));
|
||||||
|
|
||||||
|
if ($precision == $scale) {
|
||||||
|
// compare up to $precision + digits left if radix point ('.') +
|
||||||
|
// 1 digit ('.') + possibly the negative sign
|
||||||
|
$len = $precision + 2 + $i;
|
||||||
|
} elseif ($scale > 0) {
|
||||||
|
// compare up to $precision + 1 digit ('.')
|
||||||
|
// + possibly the negative sign
|
||||||
|
$len = $precision + 1 + $i;
|
||||||
|
} else {
|
||||||
|
// in this case, $scale = 0
|
||||||
|
// compare up to $precision + possibly the negative sign
|
||||||
|
$len = $precision + $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("Comparing $len...");
|
||||||
|
$result = substr_compare($inputStr, $fetchedStr, 0, $len);
|
||||||
|
if ($result != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutputDecimals($inout)
|
||||||
|
{
|
||||||
|
global $pdoParamTypes, $dataTypes, $inputValuesInit, $precisions, $inputPrecision, $errors;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn = connect();
|
||||||
|
|
||||||
|
$tbname = "test_decimals_types";
|
||||||
|
$spname = "test_decimals_proc";
|
||||||
|
|
||||||
|
foreach ($dataTypes as $dataType) {
|
||||||
|
foreach ($precisions as $precision => $scales) {
|
||||||
|
foreach ($scales as $scale) {
|
||||||
|
// construct the input values depending on the precision and scale
|
||||||
|
$precDiff = $inputPrecision - ($precision - $scale);
|
||||||
|
$inputValues = $inputValuesInit;
|
||||||
|
foreach ($inputValues as &$inputValue) {
|
||||||
|
$inputValue = $inputValue / pow(10, $precDiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = "$dataType($precision, $scale)";
|
||||||
|
trace("\nTesting $type:\n");
|
||||||
|
|
||||||
|
//create and populate table
|
||||||
|
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||||
|
createTable($conn, $tbname, $colMetaArr);
|
||||||
|
|
||||||
|
$stmt = insertRow($conn, $tbname, array("c_det" => $inputValues[0], "c_rand" => $inputValues[1] ), null);
|
||||||
|
|
||||||
|
// fetch with PDO::bindParam using a stored procedure
|
||||||
|
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||||
|
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||||
|
createProc($conn, $spname, $procArgs, $procCode);
|
||||||
|
|
||||||
|
// call stored procedure
|
||||||
|
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||||
|
foreach ($pdoParamTypes as $pdoParamType) {
|
||||||
|
$det = $rand = 0.0;
|
||||||
|
$stmt = $conn->prepare($outSql);
|
||||||
|
|
||||||
|
$len = 2048;
|
||||||
|
// Do not initialize $det or $rand as empty strings
|
||||||
|
// See VSO 2915 for details
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||||
|
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||||
|
$det = $rand = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||||
|
if ($inout) {
|
||||||
|
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||||
|
} else {
|
||||||
|
$paramType = $pdoParamType;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->bindParam(1, $det, $paramType, $len);
|
||||||
|
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||||
|
if (!compareIntegers($det, $rand, $inputValues, $pdoParamType)) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// When $pdoParamType is PDO::PARAM_STR, the accuracies
|
||||||
|
// should have been preserved based on the original
|
||||||
|
// precision and scale, so compare the retrieved values
|
||||||
|
// against the input values with more details
|
||||||
|
if (!compareDecimals($det, $rand, $inputValues, $pdoParamType, $precision, $scale)) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||||
|
// Expected error IMSSP: "An invalid PHP type was specified
|
||||||
|
// as an output parameter. DateTime objects, NULL values, and
|
||||||
|
// streams cannot be specified as output parameters."
|
||||||
|
$found = strpos($message, $errors['IMSSP']);
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} elseif (!isAEConnected() && $precision >= 16 && $pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
// When not AE enabled, large numbers are expected to
|
||||||
|
// fail when converting to booleans
|
||||||
|
$error = "Error converting data type $dataType to int";
|
||||||
|
$found = strpos($message, $error);
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($stmt);
|
||||||
|
unset($conn);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutputDecimals(false);
|
||||||
|
testOutputDecimals(true);
|
||||||
|
|
||||||
|
echo "Done\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
// drop the temporary table and stored procedure in case
|
||||||
|
// the test failed without dropping them
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
$tbname = "test_decimals_types";
|
||||||
|
$spname = "test_decimals_proc";
|
||||||
|
$conn = connect();
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
unset($conn);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Done
|
181
test/functional/pdo_sqlsrv/pdo_ae_output_param_floats.phpt
Normal file
181
test/functional/pdo_sqlsrv/pdo_ae_output_param_floats.phpt
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
--TEST--
|
||||||
|
Test for retrieving encrypted data of floats as output parameters
|
||||||
|
--DESCRIPTION--
|
||||||
|
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||||
|
--ENV--
|
||||||
|
PHPT_EXEC=true
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require('skipif_mid-refactor.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
|
||||||
|
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.");
|
||||||
|
|
||||||
|
$pdoParamTypes = array(
|
||||||
|
PDO::PARAM_BOOL, // 5
|
||||||
|
PDO::PARAM_NULL, // 0
|
||||||
|
PDO::PARAM_INT, // 1
|
||||||
|
PDO::PARAM_STR, // 2
|
||||||
|
PDO::PARAM_LOB // 3
|
||||||
|
);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// this function returns true if the floats are more different than expected
|
||||||
|
function compareFloats($actual, $expected)
|
||||||
|
{
|
||||||
|
$epsilon = 0.00001;
|
||||||
|
$diff = abs(($actual - $expected) / $expected);
|
||||||
|
return ($diff > $epsilon);
|
||||||
|
}
|
||||||
|
|
||||||
|
function printValues($msg, $det, $rand, $inputValues)
|
||||||
|
{
|
||||||
|
echo $msg;
|
||||||
|
echo "input 0: "; var_dump($inputValues[0]);
|
||||||
|
echo "fetched: "; var_dump($det);
|
||||||
|
echo "input 1: "; var_dump($inputValues[1]);
|
||||||
|
echo "fetched: "; var_dump($rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutputFloats($fetchNumeric, $inout)
|
||||||
|
{
|
||||||
|
global $pdoParamTypes, $inputValues, $errors;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn = connect();
|
||||||
|
$conn->setAttribute(PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE, $fetchNumeric);
|
||||||
|
|
||||||
|
$tbname = "test_floats_types";
|
||||||
|
$spname = "test_floats_proc";
|
||||||
|
|
||||||
|
$bits = array(1, 12, 24, 36, 53);
|
||||||
|
|
||||||
|
foreach ($bits as $bit) {
|
||||||
|
$type = "float($bit)";
|
||||||
|
trace("\nTesting $type:\n");
|
||||||
|
|
||||||
|
$inputValues = array();
|
||||||
|
// create random input values
|
||||||
|
for ($i = 0; $i < 2; $i++) {
|
||||||
|
$mantissa = rand(1, 100000000);
|
||||||
|
$decimals = rand(1, 100000000);
|
||||||
|
$floatNum = $mantissa + $decimals / 10000000;
|
||||||
|
if ($i > 0) {
|
||||||
|
// make the second input negative
|
||||||
|
$floatNum *= -1;
|
||||||
|
}
|
||||||
|
array_push($inputValues, $floatNum);
|
||||||
|
}
|
||||||
|
//create and populate table
|
||||||
|
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||||
|
createTable($conn, $tbname, $colMetaArr);
|
||||||
|
insertRow($conn,
|
||||||
|
$tbname,
|
||||||
|
array("c_det" => new BindParamOp(1, $inputValues[0], 'PDO::PARAM_INT'),
|
||||||
|
"c_rand" => new BindParamOp(2, $inputValues[1], 'PDO::PARAM_INT')),
|
||||||
|
"prepareBindParam");
|
||||||
|
|
||||||
|
// fetch with PDO::bindParam using a stored procedure
|
||||||
|
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||||
|
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||||
|
createProc($conn, $spname, $procArgs, $procCode);
|
||||||
|
|
||||||
|
// call stored procedure
|
||||||
|
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||||
|
foreach ($pdoParamTypes as $pdoParamType) {
|
||||||
|
if ($pdoParamType == PDO::PARAM_INT && strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
|
||||||
|
// Bug 2876 in VSO: Linux - when retrieving a float as OUTPUT
|
||||||
|
// or INOUT parameter with PDO::PARAM_INT, the returned values
|
||||||
|
// are always single digits, regardless of the original floats
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$det = 0.0;
|
||||||
|
$rand = 0.0;
|
||||||
|
$stmt = $conn->prepare($outSql);
|
||||||
|
|
||||||
|
$len = 2048;
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||||
|
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||||
|
$det = 0;
|
||||||
|
$rand = 0;
|
||||||
|
}
|
||||||
|
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||||
|
|
||||||
|
if ($inout) {
|
||||||
|
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||||
|
} else {
|
||||||
|
$paramType = $pdoParamType;
|
||||||
|
}
|
||||||
|
$stmt->bindParam(1, $det, $paramType, $len);
|
||||||
|
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt->execute();
|
||||||
|
|
||||||
|
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
// for boolean values, they should all be bool(true)
|
||||||
|
// because all floats are non-zeroes
|
||||||
|
if (!$det || !$rand) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Compare the retrieved values against the input values
|
||||||
|
// if either of them is very different, print them all
|
||||||
|
if (compareFloats(floatval($det), $inputValues[0]) ||
|
||||||
|
compareFloats(floatval($rand), $inputValues[1])) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
|
||||||
|
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||||
|
// Expected error IMSSP: "An invalid PHP type was specified
|
||||||
|
// as an output parameter. DateTime objects, NULL values, and
|
||||||
|
// streams cannot be specified as output parameters."
|
||||||
|
$found = strpos($message, $errors['IMSSP']);
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
}
|
||||||
|
unset($stmt);
|
||||||
|
unset($conn);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutputFloats(false, false);
|
||||||
|
testOutputFloats(true, false);
|
||||||
|
testOutputFloats(false, true);
|
||||||
|
testOutputFloats(true, true);
|
||||||
|
|
||||||
|
echo "Done\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
// drop the temporary table and stored procedure in case
|
||||||
|
// the test failed without dropping them
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
$tbname = "test_floats_types";
|
||||||
|
$spname = "test_floats_proc";
|
||||||
|
$conn = connect();
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
unset($conn);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Done
|
193
test/functional/pdo_sqlsrv/pdo_ae_output_param_integers.phpt
Normal file
193
test/functional/pdo_sqlsrv/pdo_ae_output_param_integers.phpt
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
--TEST--
|
||||||
|
Test for retrieving encrypted data of integral types as output parameters
|
||||||
|
--DESCRIPTION--
|
||||||
|
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||||
|
--ENV--
|
||||||
|
PHPT_EXEC=true
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require('skipif_mid-refactor.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
|
||||||
|
$dataTypes = array("bit", "tinyint", "smallint", "int", "bigint");
|
||||||
|
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.", "22003" => "Numeric value out of range", "42000" => "Error converting data type bigint to int");
|
||||||
|
|
||||||
|
$pdoParamTypes = array(
|
||||||
|
PDO::PARAM_BOOL, // 5
|
||||||
|
PDO::PARAM_NULL, // 0
|
||||||
|
PDO::PARAM_INT, // 1
|
||||||
|
PDO::PARAM_STR, // 2
|
||||||
|
PDO::PARAM_LOB // 3
|
||||||
|
);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
function printValues($msg, $det, $rand, $inputValues)
|
||||||
|
{
|
||||||
|
echo $msg;
|
||||||
|
echo "input 0: "; var_dump($inputValues[0]);
|
||||||
|
echo "fetched: "; var_dump($det);
|
||||||
|
echo "input 1: "; var_dump($inputValues[1]);
|
||||||
|
echo "fetched: "; var_dump($rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateInputs($dataType)
|
||||||
|
{
|
||||||
|
// create random input values based on data types
|
||||||
|
// make the second input negative but only for some data types
|
||||||
|
if ($dataType == "bit") {
|
||||||
|
$inputValues = array(0, 1);
|
||||||
|
} elseif ($dataType == "tinyint") {
|
||||||
|
$inputValues = array();
|
||||||
|
for ($i = 0; $i < 2; $i++) {
|
||||||
|
$randomNum = rand(0, 255);
|
||||||
|
array_push($inputValues, $randomNum);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch ($dataType) {
|
||||||
|
case "smallint":
|
||||||
|
$max = 32767;
|
||||||
|
break;
|
||||||
|
case "int":
|
||||||
|
$max = 2147483647;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$max = getrandmax();
|
||||||
|
}
|
||||||
|
|
||||||
|
$inputValues = array();
|
||||||
|
for ($i = 0; $i < 2; $i++) {
|
||||||
|
$randomNum = rand(0, $max);
|
||||||
|
if ($i > 0) {
|
||||||
|
// make the second input negative but only for some data types
|
||||||
|
$randomNum *= -1;
|
||||||
|
}
|
||||||
|
array_push($inputValues, $randomNum);
|
||||||
|
if (traceMode()) {
|
||||||
|
echo "input: "; var_dump($inputValues[$i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $inputValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutputInts($inout)
|
||||||
|
{
|
||||||
|
global $pdoParamTypes, $dataTypes, $errors;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn = connect();
|
||||||
|
$tbname = "test_integers_types";
|
||||||
|
$spname = "test_integers_proc";
|
||||||
|
|
||||||
|
foreach ($dataTypes as $dataType) {
|
||||||
|
trace("\nTesting $dataType:\n");
|
||||||
|
|
||||||
|
//create and populate table
|
||||||
|
$colMetaArr = array(new ColumnMeta($dataType, "c_det"), new ColumnMeta($dataType, "c_rand", null, "randomized"));
|
||||||
|
createTable($conn, $tbname, $colMetaArr);
|
||||||
|
$inputValues = generateInputs($dataType);
|
||||||
|
insertRow($conn, $tbname, array("c_det" => $inputValues[0],
|
||||||
|
"c_rand" => $inputValues[1]));
|
||||||
|
|
||||||
|
// fetch with PDO::bindParam using a stored procedure
|
||||||
|
$procArgs = "@c_det $dataType OUTPUT, @c_rand $dataType OUTPUT";
|
||||||
|
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||||
|
createProc($conn, $spname, $procArgs, $procCode);
|
||||||
|
|
||||||
|
// call stored procedure
|
||||||
|
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||||
|
foreach ($pdoParamTypes as $pdoParamType) {
|
||||||
|
$det = 0;
|
||||||
|
$rand = 0;
|
||||||
|
$stmt = $conn->prepare($outSql);
|
||||||
|
|
||||||
|
$len = 2048;
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||||
|
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||||
|
}
|
||||||
|
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||||
|
|
||||||
|
if ($inout) {
|
||||||
|
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||||
|
} else {
|
||||||
|
$paramType = $pdoParamType;
|
||||||
|
}
|
||||||
|
$stmt->bindParam(1, $det, $paramType, $len);
|
||||||
|
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt->execute();
|
||||||
|
$errMsg = "****$dataType as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_STR) {
|
||||||
|
if ($det !== strval($inputValues[0]) || $rand !== strval($inputValues[1])) {
|
||||||
|
// comparisons between strings, use '!=='
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} elseif ($pdoParamType == PDO::PARAM_INT || $pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
// comparisons between integers and booleans, do not use '!=='
|
||||||
|
if ($det != $inputValues[0] || $rand != $inputValues[1]) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
$errMsg = "EXCEPTION: ****$dataType as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||||
|
// Expected error IMSSP: "An invalid PHP type was specified
|
||||||
|
// as an output parameter. DateTime objects, NULL values, and
|
||||||
|
// streams cannot be specified as output parameters."
|
||||||
|
$found = strpos($message, $errors['IMSSP']);
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} elseif ($dataType == "bigint" && ($pdoParamType == PDO::PARAM_INT || $pdoParamType == PDO::PARAM_BOOL)) {
|
||||||
|
if (isAEConnected()) {
|
||||||
|
// Expected error 22003: "Numeric value out of range"
|
||||||
|
// This is expected when converting big integer to integer or bool
|
||||||
|
$found = strpos($message, $errors['22003']);
|
||||||
|
} elseif ($pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
// Expected error 42000: "Error converting data type bigint to int"
|
||||||
|
// This is expected when not AE connected and converting big integer to bool
|
||||||
|
$found = strpos($message, $errors['42000']);
|
||||||
|
}
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printValues($errMsg, $det, $rand, $inputValues);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
}
|
||||||
|
unset($stmt);
|
||||||
|
unset($conn);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutputInts(false);
|
||||||
|
testOutputInts(true);
|
||||||
|
|
||||||
|
echo "Done\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
// drop the temporary table and stored procedure in case
|
||||||
|
// the test failed without dropping them
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
$tbname = "test_integers_types";
|
||||||
|
$spname = "test_integers_proc";
|
||||||
|
$conn = connect();
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
unset($conn);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Done
|
172
test/functional/pdo_sqlsrv/pdo_ae_output_param_nchar_size.phpt
Normal file
172
test/functional/pdo_sqlsrv/pdo_ae_output_param_nchar_size.phpt
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
--TEST--
|
||||||
|
Test for retrieving encrypted data of nchar types of various sizes as output parameters
|
||||||
|
--DESCRIPTION--
|
||||||
|
Use PDOstatement::bindParam with all PDO::PARAM_ types
|
||||||
|
Note: Because the maximum allowable table row size is 8060 bytes, 7 bytes of which are reserved for internal overhead. In other words, this allows up to two nvarchar() columns with length slightly
|
||||||
|
more than 2000 wide characters. Therefore, the max length in this test is 2010.
|
||||||
|
--ENV--
|
||||||
|
PHPT_EXEC=true
|
||||||
|
--SKIPIF--
|
||||||
|
<?php require('skipif_mid-refactor.inc'); ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
|
||||||
|
$dataTypes = array("nchar", "nvarchar", "nvarchar(max)");
|
||||||
|
$lengths = array(1, 8, 64, 512, 2010);
|
||||||
|
$errors = array("IMSSP" => "An invalid PHP type was specified as an output parameter. DateTime objects, NULL values, and streams cannot be specified as output parameters.", "22003" => "Numeric value out of range");
|
||||||
|
|
||||||
|
$pdoParamTypes = array(
|
||||||
|
PDO::PARAM_BOOL, // 5
|
||||||
|
PDO::PARAM_NULL, // 0
|
||||||
|
PDO::PARAM_INT, // 1
|
||||||
|
PDO::PARAM_STR, // 2
|
||||||
|
PDO::PARAM_LOB // 3
|
||||||
|
);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
function printValues($msg, $det, $rand, $input0, $input1)
|
||||||
|
{
|
||||||
|
echo $msg;
|
||||||
|
echo "input 0: "; var_dump($input0);
|
||||||
|
echo "fetched: "; var_dump($det);
|
||||||
|
echo "input 1: "; var_dump($input1);
|
||||||
|
echo "fetched: "; var_dump($rand);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testOutputNChars($inout)
|
||||||
|
{
|
||||||
|
global $pdoParamTypes, $dataTypes, $lengths, $errors;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$conn = connect();
|
||||||
|
$tbname = "test_nchar_types";
|
||||||
|
$spname = "test_nchar_proc";
|
||||||
|
|
||||||
|
foreach ($dataTypes as $dataType) {
|
||||||
|
$maxtype = strpos($dataType, "(max)");
|
||||||
|
foreach ($lengths as $length) {
|
||||||
|
if ($maxtype !== false) {
|
||||||
|
$type = $dataType;
|
||||||
|
} else {
|
||||||
|
$type = "$dataType($length)";
|
||||||
|
}
|
||||||
|
trace("\nTesting $type:\n");
|
||||||
|
|
||||||
|
//create and populate table
|
||||||
|
$colMetaArr = array(new ColumnMeta($type, "c_det"), new ColumnMeta($type, "c_rand", null, "randomized"));
|
||||||
|
createTable($conn, $tbname, $colMetaArr);
|
||||||
|
$input0 = str_repeat("1", $length);
|
||||||
|
$input1 = str_repeat("2", $length);
|
||||||
|
insertRow($conn, $tbname, array("c_det" => $input0,
|
||||||
|
"c_rand" => $input1));
|
||||||
|
|
||||||
|
// fetch with PDO::bindParam using a stored procedure
|
||||||
|
$procArgs = "@c_det $type OUTPUT, @c_rand $type OUTPUT";
|
||||||
|
$procCode = "SELECT @c_det = c_det, @c_rand = c_rand FROM $tbname";
|
||||||
|
createProc($conn, $spname, $procArgs, $procCode);
|
||||||
|
|
||||||
|
// call stored procedure
|
||||||
|
$outSql = getCallProcSqlPlaceholders($spname, 2);
|
||||||
|
foreach ($pdoParamTypes as $pdoParamType) {
|
||||||
|
$det = "";
|
||||||
|
$rand = "";
|
||||||
|
$stmt = $conn->prepare($outSql);
|
||||||
|
trace("\nParam $pdoParamType with INOUT = $inout\n");
|
||||||
|
|
||||||
|
if ($inout) {
|
||||||
|
$paramType = $pdoParamType | PDO::PARAM_INPUT_OUTPUT;
|
||||||
|
} else {
|
||||||
|
$paramType = $pdoParamType;
|
||||||
|
}
|
||||||
|
|
||||||
|
$len = $length;
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL || $pdoParamType == PDO::PARAM_INT) {
|
||||||
|
$len = PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE;
|
||||||
|
$det = $rand = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt->bindParam(1, $det, $paramType, $len);
|
||||||
|
$stmt->bindParam(2, $rand, $paramType, $len);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt->execute();
|
||||||
|
$errMsg = "****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
// When $length >= 64, a string is returned regardless of $pdoParamType
|
||||||
|
if ($length < 64 && $pdoParamType != PDO::PARAM_STR) {
|
||||||
|
if ($pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
// For boolean values, they should all be bool(true)
|
||||||
|
// because all "string literals" are non-zeroes
|
||||||
|
if (!$det || !$rand) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// $pdoParamType = PDO::PARAM_INT
|
||||||
|
// Expect numeric values
|
||||||
|
if ($det != intval($input0) || $rand != intval($input1)) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ($det !== $input0 || $rand !== $input1) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$message = $e->getMessage();
|
||||||
|
$errMsg = "EXCEPTION: ****$type as $pdoParamType failed with INOUT = $inout:****\n";
|
||||||
|
if ($pdoParamType == PDO::PARAM_NULL || $pdoParamType == PDO::PARAM_LOB) {
|
||||||
|
// Expected error IMSSP: "An invalid PHP type was specified
|
||||||
|
// as an output parameter. DateTime objects, NULL values, and
|
||||||
|
// streams cannot be specified as output parameters."
|
||||||
|
$found = strpos($message, $errors['IMSSP']);
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} elseif ($pdoParamType == PDO::PARAM_BOOL) {
|
||||||
|
if (isAEConnected()) {
|
||||||
|
// Expected error 22003: "Numeric value out of range"
|
||||||
|
$found = strpos($message, $errors['22003']);
|
||||||
|
} else {
|
||||||
|
// When not AE enabled, expected to fail to convert
|
||||||
|
// whatever char type to integers
|
||||||
|
$error = "Error converting data type $dataType to int";
|
||||||
|
$found = strpos($message, $error);
|
||||||
|
}
|
||||||
|
if ($found === false) {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printValues($errMsg, $det, $rand, $input0, $input1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unset($stmt);
|
||||||
|
unset($conn);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
testOutputNChars(false);
|
||||||
|
testOutputNChars(true);
|
||||||
|
|
||||||
|
echo "Done\n";
|
||||||
|
|
||||||
|
?>
|
||||||
|
--CLEAN--
|
||||||
|
<?php
|
||||||
|
// drop the temporary table and stored procedure in case
|
||||||
|
// the test failed without dropping them
|
||||||
|
require_once("MsCommon_mid-refactor.inc");
|
||||||
|
$tbname = "test_nchar_types";
|
||||||
|
$spname = "test_nchar_proc";
|
||||||
|
$conn = connect();
|
||||||
|
dropProc($conn, $spname);
|
||||||
|
dropTable($conn, $tbname);
|
||||||
|
unset($conn);
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Done
|
Loading…
Reference in a new issue