Merge pull request #299 from yitam/addNewTests

Adding new tests
This commit is contained in:
v-kaywon 2017-02-27 13:35:31 -08:00 committed by GitHub
commit 0eeaee2d0f
16 changed files with 3394 additions and 0 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,446 @@
<?php
define("_EPSILON", 0.00001);
define("_CHUNK_SIZE", 8192);
function StartTest($testName)
{
echo "\n...Starting '$testName' test...\n";
if (!extension_loaded("pdo_sqlsrv"))
{
die("pdo_sqlsrv driver cannot be loaded.");
}
}
function EndTest($testName)
{
echo "...Test '$testName' completed successfully.\n";
}
function GetTempTableName($table = '')
{
// A temporary table name with the '#' prefix will be automatically
// dropped once the connection is closed
$timestamp = round(microtime(true)*1000);
if (strlen($table) == 0)
return "#pdo_test_table" . $timestamp;
else
return $table . $timestamp;
}
function GetTempProcName($proc = '')
{
// A temporary stored procedure name with the '#' prefix will be
// automatically dropped once the connection is closed
$timestamp = round(microtime(true)*1000);
if (strlen($proc) == 0)
return "#php_test_proc" . $timestamp;
else
return $proc . $timestamp;
}
function CompareNumericData($actual, $expected)
{
if (! is_numeric($actual))
{
return false;
}
// only compare up to the length of the expected value, especially for floats
if (is_float($expected))
{
$len = strlen($expected);
$actual = substr($actual, 0, $len);
}
$f_actual = floatval($actual);
$f_expected = floatval($expected);
$matched = ($f_actual == $f_expected);
if (! $matched)
{
// compare floating point values
$diff = abs(($f_actual - $f_expected) / $f_expected);
$matched = ($diff < _EPSILON);
if (! $matched)
{
echo "Data corruption: values don't match\n";
}
}
return $matched;
}
function CheckData($colType, $actual, $expected)
{
$success = true;
if (IsBinary($colType))
{
$actual = bin2hex($actual);
}
if (is_numeric($expected))
{
if (! CompareNumericData($actual, $expected))
{
$success = false;
}
}
else
{
$actual = trim($actual);
$len = strlen($expected);
if (IsDateTime($colType))
{
if ($colType != 'time')
$len = min(strlen("YYYY-MM-DD HH:mm:ss"), $len);
else
$len = min(strlen("HH:mm:ss"), $len);
}
if (strncasecmp($actual, $expected, $len) != 0)
{
$success = false;
}
}
return ($success);
}
function CompareDataValue($colType, $rowIndex, $colName, $actual, $expected)
{
$matched = CheckData($colType, $actual, $expected);
if (! $matched)
{
echo "Data corruption on row $rowIndex column $colName\n";
echo "Expected: $expected\nActual: $actual\n";
}
return $matched;
}
function CompareData($stmt, $rowIndex, $colIndex, $actual, $expected)
{
if (is_null($actual))
{
if ($expected === "")
return true;
else
return false;
}
if ($actual === false)
{
echo ("Field $colName of row $rowIndex is missing\n");
}
$meta = $stmt->getColumnMeta($colIndex);
$colType = $meta['sqlsrv:decl_type'];
$colName = $meta['name'];
if (! IsUpdatable($colName))
{
return true; // do nothing for non-IsUpdatable fields
}
return CompareDataValue($colType, $rowIndex, $colName, $actual, $expected);
}
function CompareCharacterData($actual, $expected)
{
$matched = false;
if ($actual === $expected)
{
$matched = true;
}
else
{
$len = strlen($expected);
$result = strncmp($expected, $actual, $len);
if ($result == 0)
{
$matched = true;
}
}
//echo "Expected: $expected\nActual: $actual\n";
if (! $matched)
{
echo "Data corruption!! Expected: $expected\nActual: $actual\n";
}
return $matched;
}
function DumpMetadata($stmt)
{
$numFields = $stmt->columnCount();
for ($j = 0; $j < $numFields; $j++)
{
$meta = $stmt->getColumnMeta($j);
var_dump($meta);
}
}
function GetColumnData($stmt, $query, $rowIndex, $colIndex)
{
$skipCount = 0;
$data = "";
for ($j = 0; $j <= $colIndex; $j++)
{
$meta = $stmt->getColumnMeta($j);
$type = $meta['sqlsrv:decl_type'];
$name = $meta['name'];
if (!IsUpdatable($name))
{
$skipCount++;
}
else
{
if ($j == $colIndex)
{
$data = GetInsertData($query, $type, $rowIndex, $j + 1, $skipCount);
break;
}
}
}
return $data;
}
function InsertDataToArray($stmt, $query, $numFields, $rowIndex)
{
$dataArray = array();
$skipCount = 0;
for ($j = 0; $j < $numFields; $j++)
{
$meta = $stmt->getColumnMeta($j);
$type = $meta['sqlsrv:decl_type'];
$name = $meta['name'];
$colIndex = $j + 1;
if (!IsUpdatable($name))
{
$skipCount++;
array_push($dataArray, "");
}
else
{
$data = GetInsertData($query, $type, $rowIndex, $colIndex, $skipCount);
array_push($dataArray, $data);
}
}
return $dataArray;
}
function GetInsertData($query, $colType, $rowIndex, $colIndex, $skip)
{
$data = strstr($query, "((");
$pos = 1;
if ($data === false)
{
die("Failed to retrieve data on row $rowIndex");
}
$data = substr($data, 2);
while ($pos < ($colIndex - $skip))
{
$data = strstr($data, ", (");
$pos++;
if ($data === false)
{
die("Failed to retrieve data on column $pos");
}
$data = substr($data, 3);
}
// Is it's XML type, we can't use the closing bracket as the next delimiter
// because a bracket can be part of the xml data, unless the data is null
$str = ")";
$pos = strpos($data, $str);
if ($pos === false)
{
die("Failed to isolate data on row $rowIndex, column $pos");
}
$tmp = substr($data, 0, $pos);
if ((strcasecmp($tmp, "null") == 0) || strlen($tmp) == 0)
{
$tmp = "";
}
else if (IsXml($colType))
{
$str = ">')";
$pos = strpos($data, $str);
$tmp = substr($data, 0, $pos + 2);
}
$data = $tmp;
if (IsDataUnicode($colType, $data)) // this includes unicode data type and XML data that is in Unicode
{ // N'data'
$data = substr($data, 2, strlen($data) - 3);
}
else if (IsLiteral($colType))
{ // 'data'
$data = substr($data, 1, strlen($data) - 2);
}
else if (IsBinary($colType))
{ // 0xdata
$data = substr($data, 2);
}
return (trim($data));
}
function CompareBinaryStream($inputFile, $actual)
{
// open input file first
$stream = fopen($inputFile, "r");
$len = strlen($actual);
echo "Comparing data...\n";
$matched = true;
$numbytes = _CHUNK_SIZE;
$pos = 0;
while (! feof($stream) && $pos < $len)
{
$contents = fread($stream, $numbytes);
// if $actual is empty, check if $contents is also empty
$contents_len = strlen($contents);
if ($len == 0)
{
$matched = ($contents_len == 0);
break;
}
// Compare contents (case-sensitive)
$count = ($contents_len < $numbytes) ? $contents_len : $numbytes;
$result = substr_compare($actual, $contents, $pos, $count);
if ($result != 0)
{
$matched = false;
echo "Data corruption!!\nExpected: $contents\nActual:" . substr($actual, $pos, $count) . "\n";
break;
}
$pos += $count;
}
// close the data stream
fclose($stream);
return $matched;
}
function IsUpdatable($colName)
{
$pos = strpos($colName, "_");
$type = substr($colName, $pos + 1);
return (strcasecmp($type, "timestamp") != 0);
}
function IsDataUnicode($colType, $data)
{
if (IsUnicode($colType))
return true;
// This input string may be an XML string in unicode (i.e. // N'<xmldata>...</xmldata>')
$letterN = 'N';
$index = strpos($data, $letterN);
// Note the use of ===. Simply == would not work as expected
// because the position of letterN 'N' may be the 0th (first) character
// and strpos will return false if not found.
if ($index === 0) {
return true;
}
return false;
}
function IsUnicode($type)
{
switch ($type)
{
case 'nchar' :
case 'nvarchar' :
case 'ntext' :
return true;
default:
break;
}
return (false);
}
function IsXml($type)
{
return ($type == 'xml');
}
function IsBinary($type)
{
switch ($type)
{
case 'binary':
case 'varbinary':
case 'image':
return true;
default:
break;
}
return (false);
}
function IsDateTime($type)
{
switch ($type)
{
case 'datetime' :
case 'datetime2' :
case 'smalldatetime' :
case 'date' :
case 'time' :
case 'datetimeoffset' :
return true;
default:
break;
}
return (false);
}
function IsLiteral($type)
{
switch ($type)
{
case 'char' :
case 'nchar' :
case 'varchar' :
case 'nvarchar' :
case 'text' :
case 'ntext' :
case 'uniqueidentifier' :
case 'datetime' :
case 'datetime2' :
case 'smalldatetime' :
case 'date' :
case 'time' :
case 'datetimeoffset' :
case 'xml' :
return true;
default:
break;
}
return (false);
}
?>

View file

@ -0,0 +1,61 @@
--TEST--
Free statement twice
--FILE--
<?php
include 'tools.inc';
function CloseTwice()
{
require_once("autonomous_setup.php");
set_time_limit(0);
sqlsrv_configure('WarningsReturnAsErrors', 1);
sqlsrv_get_config('WarningsReturnAsErrors');
// Connect
$connectionInfo = array("UID"=>"$username", "PWD"=>"$password");
$conn = sqlsrv_connect($serverName, $connectionInfo);
if( !$conn ) { FatalError("Could not connect.\n"); }
$tableName = GetTempTableName();
$stmt = sqlsrv_query($conn, "CREATE TABLE $tableName ([c1_int] int, [c2_tinyint] tinyint)");
sqlsrv_free_stmt($stmt);
$stmt = sqlsrv_query($conn, "SELECT * FROM $tableName");
sqlsrv_free_stmt($stmt);
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
StartTest("sqlsrv_close_twice");
try
{
CloseTwice();
}
catch (Exception $e)
{
echo $e->getMessage();
}
echo "\nDone\n";
EndTest("sqlsrv_close_twice");
}
Repro();
?>
--EXPECTREGEX--

...Starting 'sqlsrv_close_twice' test...
Warning: sqlsrv_free_stmt\(\): supplied resource is not a valid ss_sqlsrv_stmt resource in .+sqlsrv_close_twice.php on line [0-9]+
Done
...Test 'sqlsrv_close_twice' completed successfully.

View file

@ -0,0 +1,103 @@
--TEST--
Test a complex query with IDENTITY_INSERT
--FILE--
<?php
include 'tools.inc';
function ComplexQuery()
{
require_once("autonomous_setup.php");
set_time_limit(0);
sqlsrv_configure('WarningsReturnAsErrors', 1);
sqlsrv_get_config('WarningsReturnAsErrors');
// Connect
$connectionInfo = array("UID"=>$username, "PWD"=>$password, "CharacterSet"=>"UTF-8");
$conn = sqlsrv_connect($serverName, $connectionInfo);
if( !$conn ) { FatalError("Could not connect.\n"); }
$tableName = GetTempTableName();
$stmt = sqlsrv_query($conn, "CREATE TABLE $tableName ([c1_int] int IDENTITY, [c2_tinyint] tinyint, [c3_smallint] smallint, [c4_bigint] bigint, [c5_varchar] varchar(512))");
sqlsrv_free_stmt($stmt);
$noExpectedRows = 0;
$noActualRows = 0;
$stmt = sqlsrv_query($conn, "SET IDENTITY_INSERT $tableName ON;");
sqlsrv_free_stmt($stmt);
$noExpectedRows++;
$stmt = sqlsrv_query($conn, "INSERT INTO $tableName (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_varchar) VALUES (1324944463, 105, 18521, 2022363960, 'üv£ª©*@*rãCaC|/ä*,,@ý©bvªäîCUBão_+ßZhUªî¢~ÖÜ/ª@ä+ßßar~Özr,aß/,bCaü<ÖÐhÐbß<î/ðzãý+bÜ:Zßöüª@BÖUß<U@¢Ö<hÖhubÄrÐÃ*.å|a/,ª¢ßOa@oubýãýý£îZ~,ä¢î|+ª¢rZUCrOu,B£åß|:£ªîoBärÐA/BzOoß<bvu~ßuîCãߢ¢îýA@aðuAa,UÐ.>Ußaåab|¢ª¢|ü£/ÃßzzuªãA.ªZUöß<©a>OzübBüÜ|bZ./öbvß*rbö>ß©r//~ÖCÜhð¢bßz:¢Ä+_Ã__£ý£Uýh:v¢bý,©Ü£©,A:Zh>ßåvö+Ä>Ã.ßvC|:Ü*Üü*åz|b.©©üAý@uU.oOÜýAÜÐÜð©OB|rrîbU<övoUßäZÃÖ<ÄåªAÄ.Ua*ÖOªB,åîzB:ÜhövÖZhýðüC')");
sqlsrv_free_stmt($stmt);
$stmt = sqlsrv_query($conn, "SET IDENTITY_INSERT $tableName OFF;");
sqlsrv_free_stmt($stmt);
$stmt = sqlsrv_query($conn, "INSERT INTO $tableName (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_varchar) VALUES (-1554807493, 253, -12809, -1698802997, 'ßöîÄ@v+oß+î|ruý*Ü¢ãÖ~.*ArABªßOBzUU£ßUuÜ<ðýr|b~_äaü/OÖzv.¢ä>>OÜ+¢vªzöªoB_ä+ߪrÜö£>U~ãÖð~ðýur,ÖvZh¢ªZ>vªUäåîz,>ÃräðäýðO_ä*a,ö+üÐß~bÃü¢<<+îýÐöäªO/zA+:îZ,öBÐü<î£îåhBÖzßÄ~,:>bð<~aÐãö¢*¢våvÃÐåî@a<vBãßÖä媢<üa.u:>_Äu£öa~våu>¢Bã©å:Aßã£Üvåö+aä£U<bUu*rv+@U_|ð@+v@Üßb|,.ªäÖ/*êýÄ¢¢Ö/+ä><¢b@|zbãÖ@ÃãUb|ÄB£©,~ßð©ðUßöZÜöî£Zz<>åäZßð©ßaÖÖ¢bð£ßÄ>îÃÃ.~z>h_ý~ÜrüÖBruß+ª©CB©O>rå,Chro,£ßbZ_ß©,ÃUu|ßåüÄ/ý*åu|~Ö.ßZUoä:~A~CZhðU|öZ:ä/£Ä*î©ÄhävhbrzîÐ@.rãß©@uÜ©~>ÖÜööCÄzÜCü+>oZÄÜ/ABßA_b|b¢bÜh<|uBr.B*rü>aCª|AÄ©@öÖßÖ~Ö<rÐ,ä@©|££.C.üå¢/rbªßî')");
$errors = sqlsrv_errors(SQLSRV_ERR_ALL);
$count1 = count($errors);
$e = $errors[0];
$value1 = $e['message'];
print "$value1\n";
$value2 = $e['code'];
print "$value2\n";
$value3 = $e['SQLSTATE'];
print "$value3\n";
$noExpectedRows++;
$stmt = sqlsrv_query($conn, "SET IDENTITY_INSERT $tableName ON;INSERT INTO $tableName (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_varchar) VALUES (1994559593, 129, -8455, -236232445, 'ߣ*ÐO+ö+<ã:>üoîzÄ¢zz~Ãýö|vUå>|CÄUü~>buÃv<ä~Ö+.ü*ªbuî_bBC©.oîCbåîÐÖUa~/U>öAäÐBu~ozîZ/zrOOä:ß©bßo.ü©A¢höÖoßÖü>r+A/ßaªrß:ª@|bhhªª/oå<Ö:rüa+oC¢~uÄü>/.ãbOöª_b@bbߢ|uzߪ֢~uäýub©ãaZäC£ÄrÖ,üöäu+Ãîö|||,U.BråãoýbüåöÃburöoî+>öä©î,u_öb©@C:ÜåÜîÜåAÖzýbð|Z<Ãý.£rîZ|/z@¢£AýZ,ßuZ*:b.AzТä¢üßöbvbväð|<**~Uv.Ð*Ä©B*ýCUöa¢åO©Ãß*ÃÃ|ÜðA@îÃßaB<hÜîaZoöå>öüahUUA+ߣ_u|~äö.©hr£oBo<äãüO+_å<OЪÖßßväzA,~u~Obbî@ßÃãÜää©,.bO:C£Ü,äUO¢åå**hÐ~UZ©ðh<abß*üÖîC.äßh~Uð<r*ßäv£î*@¢Cv/BÖhAüB~ýAå@Z@<a_O|<©ßb*CZO,o:ã+¢£ÃZC©B¢o+>O:Z~Üoîßzb£ª£A.AÖÜÄ._O_å£ß');SET IDENTITY_INSERT $tableName OFF;");
sqlsrv_free_stmt($stmt);
echo "Number of rows inserted: $noExpectedRows\n";
$stmt = sqlsrv_query($conn, "SELECT * FROM $tableName");
while ($result = sqlsrv_fetch($stmt))
{
$noActualRows++;
}
sqlsrv_free_stmt($stmt);
echo "Number of rows fetched: $noActualRows\n";
if ($noActualRows != $noExpectedRows)
{
echo("Number of rows does not match expected value\n");
}
sqlsrv_close($conn);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
StartTest("sqlsrv_statement_complex_query");
try
{
ComplexQuery();
}
catch (Exception $e)
{
echo $e->getMessage();
}
echo "\nDone\n";
EndTest("sqlsrv_statement_complex_query");
}
Repro();
?>
--EXPECTF--

...Starting 'sqlsrv_statement_complex_query' test...
[Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Cannot insert explicit value for identity column in table '%s' when IDENTITY_INSERT is set to OFF.
544
23000
Number of rows inserted: 2
Number of rows fetched: 2
Done
...Test 'sqlsrv_statement_complex_query' completed successfully.

View file

@ -0,0 +1,100 @@
--TEST--
Test insert various data types and fetch as strings
--FILE--
<?php
include 'tools.inc';
function ExplicitFetch()
{
include 'autonomous_setup.php';
set_time_limit(0);
sqlsrv_configure('WarningsReturnAsErrors', 1);
sqlsrv_get_config('WarningsReturnAsErrors');
// Connect
$connectionInfo = array("UID"=>$username, "PWD"=>$password, "CharacterSet"=>"UTF-8");
$conn = sqlsrv_connect($serverName, $connectionInfo);
if( !$conn ) { FatalError("Could not connect.\n"); }
$tableName = GetTempTableName();
$stmt = sqlsrv_query($conn, "CREATE TABLE [$tableName] ([c1_int] int, [c2_tinyint] tinyint, [c3_smallint] smallint, [c4_bigint] bigint, [c5_bit] bit, [c6_float] float, [c7_real] real, [c8_decimal] decimal(28,4), [c9_numeric] numeric(32,4), [c10_money] money, [c11_smallmoney] smallmoney, [c12_char] char(512), [c13_varchar] varchar(512), [c14_varchar_max] varchar(max), [c15_uniqueidentifier] uniqueidentifier, [c16_datetime] datetime, [c17_smalldatetime] smalldatetime, [c18_timestamp] timestamp)");
sqlsrv_free_stmt($stmt);
$numRows = 0;
$data = GetInputData(++$numRows);
$stmt = sqlsrv_query($conn, "INSERT INTO [$tableName] (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_bit, c6_float, c7_real, c8_decimal, c9_numeric, c10_money, c11_smallmoney, c12_char, c13_varchar, c14_varchar_max, c15_uniqueidentifier, c16_datetime, c17_smalldatetime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $data);
sqlsrv_free_stmt($stmt);
$data = GetInputData(++$numRows);
$stmt = sqlsrv_query($conn, "INSERT INTO [$tableName] (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_bit, c6_float, c7_real, c8_decimal, c9_numeric, c10_money, c11_smallmoney, c12_char, c13_varchar, c14_varchar_max, c15_uniqueidentifier, c16_datetime, c17_smalldatetime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $data);
sqlsrv_free_stmt($stmt);
$data = GetInputData(++$numRows);
$stmt = sqlsrv_query($conn, "INSERT INTO [$tableName] (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_bit, c6_float, c7_real, c8_decimal, c9_numeric, c10_money, c11_smallmoney, c12_char, c13_varchar, c14_varchar_max, c15_uniqueidentifier, c16_datetime, c17_smalldatetime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $data);
sqlsrv_free_stmt($stmt);
$data = GetInputData(++$numRows);
$stmt = sqlsrv_query($conn, "INSERT INTO [$tableName] (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_bit, c6_float, c7_real, c8_decimal, c9_numeric, c10_money, c11_smallmoney, c12_char, c13_varchar, c14_varchar_max, c15_uniqueidentifier, c16_datetime, c17_smalldatetime) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", $data);
sqlsrv_free_stmt($stmt);
$stmt = sqlsrv_query($conn, "SELECT * FROM $tableName ORDER BY c18_timestamp");
$metadata = sqlsrv_field_metadata($stmt);
$numFields = count($metadata);
$noActualRows = Verify($stmt, $metadata, $numFields, "utf-8");
if ($noActualRows !== $numRows)
{
echo "Number of Actual Rows $noActualRows is unexpected!\n";
}
sqlsrv_close($conn);
}
function GetInputData($index)
{
switch ($index)
{
case 1:
return array(array(-1512760629, null, null, null), array(167, null, null, null), array(-28589, null, null, null), array(-1991578776, null, null, null), array(0, null, null, null), array(1, null, null, null), array(0, null, null, null), array(0.0979, null, null, null), array(0.3095, null, null, null), array(0.8224, null, null, null), array(0.6794, null, null, null), array('~<auu*,/Öb£bbör,Aåbßå©+b_ãä¢ä*b<C.Ä/v£*,Buzößý~:ZÜb/Üå£îBðÃ.>Ö~.üoö©UßB.|ÃÄ£*/v|U/*bZ£ÄUÜß*+ööî*©ðü©bðr@éåbOý|©©hob/>Cz<Äå::Ð<¢ß+ü/:ª@zrß.¢Ü£bÜU©ÃßÜßðoß©r*bÜböOUvãahub£ãäªb>_ã£BOÜA©ãü/ߢß.ov:Ö<:_+uÜC:£oöü*BzC,Äö~Zî@/Z/r@/©<~.ã¢Aa</*bz.@åýBÄZÃA:zå<~öBbß|ªaýÃ,~><vBîv¢>ü>ý_zz@rÖ¢aU@,ABð/¢ß>z/ã@/ªUA~CoÄ,>bö|Ö>A,v+©CbC/Oo>©ßa©boAîÐvOo>ã|Cåöo+ÃhÖBAbo,+<ßã/£@å+ßAÜ@äÖÜOBäß~öu<aßß_bð¢ýý£_U:*Öä*©Übð,ãß,üððr+ß/U*ã¢ãüß:rAÜåz>*ã+a<îoo|¢üýoBaÃÜ£ãCaC@ha,äzäî¢ü@å£b~råîUbßr©ãßÐ:@UhAO>u*uýBbäZ£aý>v:ðC~ÜöåðzZ>O|Cä+£>öz./Ö+uÜ', null, null, null), array(',ßhr©+|v@,Ã+BZ|îAÐß_öýða_AoäAOÜ*ýC@hoBßßaä+ýöCäAä_Ä¢/Uî.äC©¢rÃuz¢*,ýß.Ðöðý@b£öb.OCý@>hðÖrCZb/Oªz¢A+ªÖäu<ßÜÄ/ÐßÖîbU:bÄÐã>/£ÜÃBÃ@Ð.r:ªª>©zî_ÄÄ:@A.+.aoÖ@¢åOåOBB|+Cvüa_+hz|~COoACAî¢+*Ä©*ýî~|.Äz|u+o~:<@>Arb:~£z<äbãv>Ðr©:ðýCößÖ¢UAîãý:Ã~.C*C¢uÖ*~CÄ*äAb>h@h_>,|u<<r|Ö><.,vå,.BAuo£_ãB.Örö.Ä>zoba~C©hArªB£Zü~oÃbb>î+ääÄCbÐýª*Üýburäßv/åOüA:Oß:obvz©ý/ßroäaª/bªvz©rÐ,ZäߢªÄ.ã.@z¢|ð*aCý©:ýÄövã<h+ÜC_ªÄßÜ.@b,Ä,,Ö+ÃüäCvUrÃ_Z,ªî|Üh|bbvýÐðÜoð@bªüb¢öª~åªAB@ðäb/.O@üvUh*z>,öAbö+ÖCb~uÖ£züî|_ö~*CÃ>+ý/_ß+ãÐz<u¢ã@bÖÖßß<r£_Oý+â,ÖhUv|Ðüð', null, null, null), array('ÄÖ@:OB*bA<rß_*rZÄ:u|:©u*~zü+vßBß_@bÐÄr+B£Z©hOð¢îbva@Ä©äb_oääCýßU+,ZAv<~@Bhðhabh©ÄbZaß~Cä£Ar_*@ü£@.ßߢ~£ªÃ>/|ÖÐA<arhbÄÜ<Üv/,UUAoªov£ªv+Ah.Ã*Zo|CðýÖ_h+åöÐöA@Or.*£*ã.<b:O©oa©A:o¢Ðz<U@@AuZ*î£Uããða*Ãüzo£ã|~äü+uîZß/ßåÐoãCZªBhOßößzb©ÃÜrZ~©¢Ãð£båb/¢äãbürã@|©Ðb@©Ü¢b©v|u@~CruB<î<UÐAÄ|öCÖ+äãOr||_hüðzª.ª@OBvÄãÐB+ªb/aaßCß@ZZ.ÐbzA~ÃBh|ªåãC__:©/î¢Ü<ªCC|@+äBßZCrßhßuho£üßýr~î>v©ob.©£v<OðaoÖv:ß~ÐîÐ.£:ZÖýߣªð_©AbOöÐî:|_©¢zCýîÃ+r¢äýÖåaÄߣÃä¢åU,+C©B@bÃv+rÐACoÖBBv,zéZrouðUÜÄîß+öÜäUªäoö~£|hý~£åªÖ+>öÃÃã:ðvC/@£Zð©O,åã@.u,BAÐbO£Z,Oü|Z/UBAß©ªA@býUuz.UýÖUöv|ª£B,Тßb*ÃУUðZäbãßOäAA>ãåUb,/Ä¢aä©:ð.öýr<Ðz@~b<öhÄ.CBÄ|ª¢|ä+ÜÃîüC¢,vãö£îãü.ZÄüUßßBuÐz>ðoBãZäB¢:ßã+.üÃOBOb@ZCZvî©ZA~©:O©£ÄuOý£Üßr_¢<+|ZhªýA©ßOßäãö£~bAÜ*©ÄÜv:aB|ZÄbªÃß|BýåýÃ.@ä:ð+*baOÖOÜvߣßAÃ~å>,bCOoa._~obböhãz*b©b|Büîã/aîzür.ßîhß*Ðr*£<ª~CÃz©ß>êîãövCr+Öa@u¢ü£ZAabü¢å*.b>,ÜhB*Bßvª>üüäÃh,:zhUý¢<.v£Ö@bÐ|/äÜÐ/r£Ã..*,ozbo,ãU/Avã@ÜzÖãÄ+zräö|CböÄoߣÖã©uzbr>+ÃãZ_/ruÖ©Öß.ðß/|ýÜbä/Ð,ßr:Ü~Ðßüh,ßî+ZoÜ/©oaÄ:>O|CÜov>z_£vÜhý:©aåߣaBðbUßa©OUЩ,Ðvr<ö¢Ã©bZUB_aßüaoCîß<B£b_*vßCvðª,/ÐurbUCýößÃüÄßuÃOBªÜ~vo~./v/ãöAz@hªbÖßBåßß@ZöBß_ACðO*ãßh|£ß£üÄhaÜ+:~uoö,ýÄüÖÖå¢ZªÖ,ÐaãýÃz:_Ba<îBÃ>_ª£UzåO|O¢äb,©a@Au*/að,ÜUÜ£ã,_ßåbv*A£+:>|:©+ßvbäb>/ÃÖv<¢råý_U*o£ßüýC*ýäÃÜãå|UaöýÄÜÖîCCCßßÄßÜ,îurZa|ãvö@B¢Öîî.ð+Oðaã<~v_Äär*£oBz墩vU<CÄÜv©v+rr.å*¢ä,bÖ£a<ãýb¢åö_:AZУCÐßZbrîao@£ß<Z_UðßäaUÜ¢C£o.ÐÐðoð©uuîAba|ÐaZ*+vhª.Z@u/Ð.*BÄ£îßOZu*ÄCub¢räßzvu<ZÖ+aßz//ö>ößåß*:CÖ_Ðba©oî_ßB©/C:oäßövåaåäß,rO/oßä.©~Ð@.vBrBU_*Ü_,@£Aa.oUЩäU£:ü>,ýUUÖ|Ä©:_ãbÜÖ+_Aãã©Ühß:U/ãb£o£©u¢å_B_Üßßý~>|B<ýz*rߪzÐuOßa*Ä¢aZîOãoäß/@baäÜ~zîhüäÜZöãbð', null, null, null), array('54e16f51-64f1-4d62-a028-582b553c2de5', null, null, null), array('2130-04-16 14:12:00.131', null, null, null), array('2032-05-10 23:32:00', null, null, null));
case 2:
return array(array(-1111886816, SQLSRV_PARAM_IN, null, null), array(27, SQLSRV_PARAM_IN, null, null), array(-20174, SQLSRV_PARAM_IN, null, null), array(-840346326, SQLSRV_PARAM_IN, null, null), array(0, SQLSRV_PARAM_IN, null, null), array(0, SQLSRV_PARAM_IN, null, null), array(0, SQLSRV_PARAM_IN, null, null), array(0.4880, SQLSRV_PARAM_IN, null, null), array(0.9184, SQLSRV_PARAM_IN, null, null), array(0.6916, SQLSRV_PARAM_IN, null, null), array(0.7257, SQLSRV_PARAM_IN, null, null), array('<ö©ååä,ääÐ*bhîvr<Cý¢î©ßZÐ_å©ÐZ,UC:<öa</©bU*Uö@u*AðaßÃBÄßh+o+üÐC~*böÃ:*OaÄ*|£z|+rZ_¢ßv~~a֩ߣZbÃ+CÜîä~|îÄÐaB+_b>~aöb/BzZÜ@öðß@_Ä££r__£>£Ð£ðbU<r<Äou£+ývUß<h+£¢BOrz<Ä*@öö@z*ÜoubZZ<u¢Zå+£,öÐb@haB_Öåöa@hOuZhA©>B~/ãbo.>îzöã*,ßå/+zuu.+BZßzA,aÖzüåão£©BãÄbä~ýooÜ,+äßÐ:UÃrz|vä,Bå~¢ä<_£uÜv<_O|ßBC¢_£Ahöª_¢oözCßýzöüý+zÄUÖhB@Uîbh/u/©zÐbÖ¢A*ã,Ãî£<>rUªßÐßîZîåb:+¢|A_BÃo©ªäu,*ýååbU:bÖÄß|¢>¢ÖaãrÃO©Äv+oßöZãª,+/.ãa/㣪,¢ðÐ<î¢b.£Ü©_r©vª@î:>ÖðB:OrBÜЪý|bßbÜ|åUOåîOãÄãuÐ|/îörB£ÃßZZÄ@Z©bÜB:.¢@b££U¢äÐvÐ+ý+uzÃb+üo+öv~_©~Uhbª,ßCb+UZö>Üü', SQLSRV_PARAM_IN, null, null), array('|öÐob*+ÐÖ<UU|ßbCªb¢ªuCüoUOü:Ü/>,..Ä¢ß@>îß*äî|å>~Oo+/o+*/ü|îî,ðö*ýåãob:zb|Äßîvb¢,Ã,UªbbrAbZ©uªª@ä,_ð©A*>Ðävä:|:oîö_rý©+vî©ßBßßb>üOö@Öoö*+î@ÐßrÖ<¢hÜZb._raUaýUUÄößßîU¢ð.ÐýrãBh¢>Äðz<©AÜ/|©Ö@>hüBCO~öýZ>äÄÐAzä~/b.ÜzbðÜbða++ªå/ð~ACÐî~©>./<Ööý<~ýuÃBÐãåo*h©ö£öîüZß:ZÐä_>Ðvî©<aBð_ß++OzOÖhö,ÜîÐä<_><h|OãhÄr+<öuÄ*AÐ.ä~_Üý¢Ähß<Ö~a.:Cü|ü++öu©ýöÐßîUbÐOzaåýÄ>_äbb©ö¢*b@BÐÜb+bî+åßAåîu|/A.Ä.~hvb:@zå|Ä,ªÃZß@v©ßvB@Bð:£öß@uðr££ðü<Ä¢äÖaßO.:rª/Ao,ª:ZbA+¢ß|>,*ßoöA+ãb|Aü@bÄð@a:+,<b_¢r*åöBbßZU£<.U>ouªýª+£ðr*Bã¢+rCðUU_ÖÃ>îö>r©v:U_v@vCÜ>', SQLSRV_PARAM_IN, null, null), array('ývC|ãv:<BCÄrhÄÐ<ÖÄAChü£ÜB~|Bbb*:ßb|>|öbÃAÖ~oÐA,~ßß,b:+ba¢+<vÄ+,aÜv/BhUîߣ+b.,>AbOýzvÄvý/a_är<ßüÃ,~,<¢Z/_î|/bv£¢C*.bÄABz@výb¢.Ä*ä,.AßC|/î~Ü,hãðo+îÐäbÄv£vUäO£rßhOu|Äå¢ßaÜýohvÄOÃ+ãÐÄ©ävoCÖÖ|v+ßÄÖ¢rîvuvÐBÐbb_C+~bOãß<C>zö.~CåUÐ.O<.©>v.h|ýªöÜO¢ý,o>B_ýu£hîüå£oääý©îbÐÄBßßÄU>@||Öß~ÐÄÜ£åruÖ_ªz@>.CÖöBZ_vÃb©zãÐÖC~*rBb/hB+ßÄäüO>@vrä+ܪ:<Uzb£BzA<>£öUB//üý©~zª©Z>~ob£ä,+ýîÖãÖ,@ýAÖu,*UU.ãÜå,BaCäªa|bðv.ªBvö+*ªÃª<©||+ZöU*ÖräüýUüÜåUÐß<bÖ*£vbZåbUBZð:<~@ZbzÄob_¢Caý~<*öÜýªßuÐAåö<ÃöÜÃbß>r,öÃ@ÜîÃßaobZzªîh@ðãÃ*Üvo+U>CÜöAO>,b.vvuÄB/Ðäã©hBA£ohýßä¢Ã@h_/|AbCåßð_@åuÃh~ðb.*ÄB,BCÜîrÃ@<ÄÜCÄZ|.©Öüãr|_Üð:ãuö|vo:/A<îZu©h/bßCBýäA@.©,äåß|+ã:+:|î:ªÃvUB>,_ZÄß>Уß<ýr/o¢Ü~|rî_:ÜZÃäo+@/ĪöAACbhbzãÄaü,uhÐßßBÐbOöðÖaAö*,h.Ö,v.h>Ä:<åbß/ßî:Ð/_Ã*ý|ÖbB+bChý<~¢uaüÖªzC©UOCC>öB~uîã:bÖã@zbh¢z*î¢Uß~î>üãr~©Ö,£ü¢/ý|îb¢C|<o:/|O@+îZ@åÃ+OBUb£å.a<å+/Ä¢Ö/ßýCvCÖA|ZabzãBhBöbß<©ýüuo<Ä~bC>åª><@Ö.u:bÄߣßbo,ÐU>£ßZÜßAîB©A:<o@OÐ+¢£+_ã,.ür*/BZ*ãߢäbZÄ£<äz~.ªu¢C£*ßÖBîüß/åߢÃ<a+Ä¢£|©B/£üo>rUýßÐ~uÜÖ<~Öî£b©.îAß,ZuÄýªb<|ðOÜð.Ö|:BbA<ÄvîCäÐîª:aÐö,CðAZßh@ÜrãZßß@î@rzãý*©Az~CäoäCî<ã|Zã@ovö_Ã>/ªzbuabuÃîöb<åÄÄÃv*îBöãýUrbýbbå<£OªÐvb¢oßîr|å@ãöß:ªÃOß.>Ü*ßaöbo£a>.vvý/¢£OCrÐvBÖ,COª<rväßCööU¢rÄÖ~_.B|©ßaüAa©OÜ@ub£ãå|Oßr|>oA>,Aü.:oÐãã:+~>oUOª*:ÄOü+ßO,ÄO|b>Ü_ªýAUТÜ_/ß,_üéö+îãªÜObªªvÜa>bÜö~bîouðäÐÃoÜOüZuÄbUOh©OÖ/ö:©<ãÖb+A:öîÜ>Ð/bBðª.å¢ZbbüUå¢Z.Z>uÜv,îöC/o_+zð~@ÜB~vhabß,/ÜÜß<.o_¢Zvöo©rü>ýÐbðÐo.ÖC_ÄCh>oüåöho*öÖ,ßãZ|ª/,Z©a*Ð:ê,A*ä:.<ßBývÐbßhAüÄBA@BO_B*ã>>ßU:v_ÜZªîð.uãO~zÄz<@ü,A*£BvãßÜC~ýzvÖã:_Aä/bÜÃß©î¢r.a+ü@:uB¢/>:ßhßãU_îã<UÜ/©_ZU£ã/,uª+Buaßã_ÐãB|.£ööä~CýßÐoUðZýhü<ÜaCuOÜТ', SQLSRV_PARAM_IN, null, null), array('29a27f4f-9e94-45a9-9110-812ef69ee37c', SQLSRV_PARAM_IN, null, null), array('4262-03-20 19:16:36.081', SQLSRV_PARAM_IN, null, null), array('2065-02-17 00:36:00', SQLSRV_PARAM_IN, null, null));
case 3:
return array(array(-1584712173, null, null, SQLSRV_SQLTYPE_INT), array(170, null, null, SQLSRV_SQLTYPE_TINYINT), array(25360, null, null, SQLSRV_SQLTYPE_SMALLINT), array(1352271629, null, null, SQLSRV_SQLTYPE_BIGINT), array(0, null, null, SQLSRV_SQLTYPE_BIT), array(0, null, null, SQLSRV_SQLTYPE_FLOAT), array(0, null, null, SQLSRV_SQLTYPE_REAL), array(0.3807, null, null, SQLSRV_SQLTYPE_DECIMAL(28,4)), array(0.4393, null, null, SQLSRV_SQLTYPE_NUMERIC(32,4)), array(0.8725, null, null, SQLSRV_SQLTYPE_MONEY), array(0.2057, null, null, SQLSRV_SQLTYPE_SMALLMONEY), array('ZÄßÃ|vbB/O<ouU*+ð>ýÖ~AABß©Ã@ÄÖßz~åz@ü.Ö<*~<B/Ob_ðð<öå<vUÃÃîîª|.Ã,oª+öã._Ö_.a~ðêªhªÜvã/Cªbßv>ãäßOÜÄv~Īb_ör*bvÃÖýZZ<ö¢.|Ð>ÜåaCAîâãßu/aå|@U*¢Bb*+bZr_.ã|,h_BöÄb.ðZ©//î_~v/ð/,bð¢/:@öãß+vÜv/båðöã:ã/z:£î<_ÐöC>.Ozrð©@rC~Bö,£o<:Ã*<bý_©¢Oß_b.Cåuß+BCäüv/£zvz,býÐýbAª£./£©ªÐäüoÐ:uĪvb+ªÄbb:©U*uhßßb*bZª.ð:<UU/<<ªßBÃ<Äâ>z_ªöÜ,z,ªboB,+öCr*¢î*<£~ýb:U|©Bh/ãÜÖý:obhå£+Z+r:o|v+bÐhãåaüÐöbãðöAÃ|ªOCÖO|Ü<ãvv¢ãýbý.ÐbÄÃðåü>/BbbÄ/véäý:@o>öÃaªÐ+îüýã_röýä©zhvÜ<Ã/CäaðoCB|å~~ÖaðvuC_hBrOrzÃßO©ZU.AvvåÖÐ/ÐãåZ©£,UãÖAîhUzªrö£Ãu+ð/v¢o_<ÐA@', null, null, SQLSRV_SQLTYPE_CHAR(512)), array('ÄßZrð@~ö:ü:£,CoÄ©böBAO,ð:aA>ãÜBÐ@./:A.Z/bÖÜ,>ßî>ýßß©b/<@/,Öî>BBÃäÐCüÃÐÃvÜ_AZ.ý/©C_>aö/£Böða©£,öý£B_ÜÃðßvh|î|.oB/öBÜö¢BÐ/bAAÜÄa£.ªA©z<£ýOÐrå._bÄÜß~Ä_ªý,|+BãîA~Cî@ü+@ÜüzCªr.rzåazUöCzBߪ©Bö+ü*ZãÖ@AC*UA¢..aÜü*ArÃz£B:ßßÄ+Ã/ãª+ßZ_Ü<ßäîýýî@ðÄÜßÃÖðova£ªOöÄzÖ©ãrabªÐUrår+Ü*©OöåBö|a©î:bß©ð~_C_o*hÃ@åBb|<åÄß@©ý.Ubª,O£Oz|üßbz£+bã¢a@>:aaîý_Ür£|hÃ@z<_hüÃü,öîZýuã_¢üå£<ðßAª>rC.Bî.©,ß*å|é*_B>CÄîÖÃU~ÃÃ>rª>/ð©Ö|~ZA>¢¢/@£bZuZößzðå~:/h@uÐoOrã<¢aîßüß<¢BZzO¢@.:rvÜo>ABzC/ÜßÖ::r©O/v*@üaäzßZhU@aßvüî:©ü~ðª©_b£ä£ãB@:bhCÄZÜzOUßoåîÜý><', null, null, SQLSRV_SQLTYPE_VARCHAR(512)), array('Üarä+Öã/ür:h:AÐbðÃov¢©+ß*C/ߣZ£,ozz@UuÜ,ääßBÐB+hhãäz*rîC©/@u*bßÃ|býhÄrãÃîÜ/ÜäUbuÜv£ß:*bü.räßÐ_bßbC_©Cr:ðao/|ßhU.+v<b.aUuAaÐ>+aö+ЪÄÖÄ,C|ãÄßvð>ovü:<:bý/båz£B>ö~ýrbãO/@ÄüoðrÃrüz_ã:@ð|@ZÐO©ä,Öabîhßbä©ýã<Ð>vhßÐäîaBUA/©:ÄÖBaÜ£zuhäz|.ð:åä¢bObuhö<ßö,£Öa<>**C|ýbß.UhZ<o:ý~u./,<,<¢o_üÄö~.ããbb~zzå_uÜßBä<Z+üß.+ªBaüå@.:BC<©Ð:¢B,.Uð@îhÃ~,ÖÃUªÐhOAUÐbBÄßð:/Bzh+/ãOý~~>ãÄü*,>ÖÄO@.*>ÃOåbvÃ/ýb<b,/a*ãb¢o|Ãr|ÜÄÄubuUðÄü©©UüCÄåh@Üuîöü>/äCîuÜß>¢C+|<*Üã|*.Ü*båöîv/O/*äÖÖÖ©+CA<räO¢ãÜh/ßÐöÃ~|Oh*ýOýü+¢bZUªßÐÃ/Ä_årðo<AoÖäª:>£Zr~ªz,ðA@ãuCzªO*ÄCzuoÄ*UüäöaUCÖO~£ö,uC,Aß>++Äbh/ý.o>Cv>ªäz¢:/ðß.BA_éßC~ÖZ:©*ý|ðÐ@AãövbZo+_î>ð¢äÄüvÃ@<ÜrZ~ÖããßvåÖÄÐîîö:ßöU@zvrBã©~ü+Äå/UÖã|,_U<*b£hßOÄüÖ_:Ðvö<ðb>îoUäîOåZ>ob.bZÄÜOu¢bZ£üªrãUohZZî<å¢br<O<v>Ä|î+<oa>ÜuzaOvr©©bðÐhOäoðOâ~Äbhßßö.Äã+bh£@bª:Ä*å|ßC_|+@ÃÐ/Z<.ðbOou,zßößÄã~>Ãß~<>*ÖaîöªU::Ðü/bªÖÄ:å/uzAbªý.Äüäãåoößh£ðoU|ýöåbý.¢uãÜuðoUOz©.ð_îvª¢äß<v<BßZ£äu+ha¢ªÜ<CbªöýÄ£ãý@UÄ©Ä*vrOö+ÜÖýðZZAßo£ß*Ö:|Ð.ßZªhA,@*u£<Ö,ðbUBîOäBÖ/C|ªÃzzr¢rbA|ü_öß~vUîZ@rßÃ<ß,ß+åZbä<ª:ÃOAAAvÄ+,BÐhCª~ããC¢+ßýä>ãßãOÐ>Bb+*åbuåvu@<Z+buÃÜZ<rÖãu©Ä*_ru:_¢åa©ßÜÄ>¢üã,äzÃ>/ªCbåvZ*rCÃOÖÄÃbßýã/+/:ðbßäuî<,*aãCªB,£*ª©:©b@ÖîZß~å<vhahrab/b/ÖÖ+Oîªbü/*@ãÃüÜã_bööCå>äÐÄB:å+~ð_uÄðÄ*ãzrão|ü::A,+<a<Czåv@<r>¢bbÖªZ:UäCru£ÐZÐöåvvbb@å~:/ðã©rä£ßªÖBß,oýß@UvÜã,Aoz¢Oð/_|Oohå_/rî*ªãh_¢h>Cvv|v¢ßªbîÃ*\/@Ã~bßar|ýü¢åbîÐUðO£Üãî~+ã,oÜîö>+UbÄ+ÖðÜ£Äý@>üÐßabîCð¢Cª¢CuU.ã:©b>U¢ýO+>ý.abã.B,B|oÃýã|Öh<bU@Ã,ßvz<aÄBãßÄ.C@ªbÖuAãhãÃÖ©rð@>@CCüzArß_ðBÃýÐ*ýªÐbhbÐäuÃ__C_©UbO¢zÄ~/ß>.vuZðhoC*Öb>å,.ßUîZß@bväÃa>+.£.oð|Ðß>|Z_+.ÜÜ~Ürßu_:ÃCýýza+ªð©ßÐÄ+î|z£¢ZâÜ/Bz>vðßÃhäOÐAö|/ßCü+å~Ãb/ÃuîO¢uÖb+~åa@BÃhü£ä@¢äªÖußOÐUåä/UbªÄî@_£/©Ã,©.vAvuîöß|ßߢhüßbAß>Ä<Ü:>ýu<BuBüOubß|h<aýîªÄvÜbÜ_Öª.ãr©r£ß_va:ãª:ã£,bouî|ß@ßäboÐî<ð*¢ÃCý~åoÖªOa_býU:hÄÄ,_ÃãbÄä*~£ß,_@>üÜÄ£ßOý<Z,ßüÐåßÄ~OÜ|ßöãbZÐ_~BÜß>A~a<Ö@î_.b.<UÐC', null, null, SQLSRV_SQLTYPE_VARCHAR('max')), array('55a1f242-dad9-4f8e-b839-364fb6e1ffec', null, null, SQLSRV_SQLTYPE_UNIQUEIDENTIFIER), array('7060-11-11 17:57:33.899', null, null, SQLSRV_SQLTYPE_DATETIME), array('1920-07-05 00:42:00', null, null, SQLSRV_SQLTYPE_SMALLDATETIME));
case 4:
return array(array(1640057440, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_INT), array(229, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_TINYINT), array(-13459, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_SMALLINT), array(-8557402, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_BIGINT), array(0, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_BIT), array(0, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_FLOAT), array(1, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_REAL), array(0.3122, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_DECIMAL(28,4)), array(0.3036, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_NUMERIC(32,4)), array(0.8606, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_MONEY), array(0.4224, SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_SMALLMONEY), array('uåîAZ©ÄZöäÜO@ÐðZ:r:vÜ@ýA/,O,ãBß>¢hð.Z>£Bߪ+¢ªZU/@@äB.orÐîå¢ð>*<äAv~,ß@ýü~+<oo+/hCÜåzuÐb:ðr@.åÄ¢<h>~*Ðå¢ý_å_bÄb~_<<ßÄ:o¢zrC<ªa~BäÐýA©ßB.Uhîß+rAÖå¢ýö.îîaýåUC¢/Aüöß©zÄaðÐ,b|||+vCO+~üA£ÄöãýbÜ_üßãCðã|_ÄbäÃU~***<¢¢höUãbözbÄ>Ðühr.vÐ:£_Ä~<ZÐvÜb+¢>@/o,a_abý_>ßr*å|bob¢îãBî~<üBÜouÄBar_üß.ÐÐ,©ýuÖUöäÐÐîZýªÃ*vß|~îZßZÜÐrh*~UÜ*î@OBÃßraUb:*/B/@OÄaãoßBãÃ<AAß@o>höBb@Uªý*|£U+ü*¢ß¢häUðOb/*.rßOrÖåüO<ý*aöCa@ªoä>ÐC.UO+ZUrÜA©Oã,ro+î+,Üå¢<¢rÐu.ªî|ãÃB,ða,ªÐüÄü©ßBÖß+uv>BöußÜ|h|aßohB*ovãu+@Ü£ßO©ßßBý:b+£bÐÖäªo:UAÐo_ã~>ö<ühåÖÐ<hbCýÜA~|Üß', SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_CHAR(512)), array('Aª./UbîvÐð££ãuzo@>î>å*v¢ß<OÃr<o.Ð*_å|bÄbü>a_>/ZÖ:åbbäz¢Ä*Ü¢ÜåubvÖUî@Ã:¢<Üß_.*Öh,o/uz.B_/Äã|Ü/öOÐ.ÐßU@ßbav~zAßu+ª£U¢<ýÖä©Ä>ßãåäbã¢ßýªöåä,*ubßß@¢><üCozÐЩäC_aauC/_<.ýuÜ£Ö,uCÜÃbåräZ,ðÐî@îbzÖã+ã,CB£ZzB¢vÄ*+Üb¢üýßU*oÄärãü@öîaß.|äý©bÖ|BuA©ª,C/ZB*ð~aÃÃvîü©+ªÃ+Ã_öuu¢ZöbÄuð©O¢Z@_uä|bu,äOÐÜbBr@|Ãüb/îr©ß.ååßÜabZ©hß+ãߪz|+Aå@äü>Ä+ýu|å¢z|bhr*ªbO©>/ö,hÐå+Öå_OßZ|ð,b.AäÐß_@ßß©.üüZäuA/aC|£CäßýbhÖÖªZö@ÃhßÖ£/å*örüßðU*~vhðv_Üðýðß<+bAbBa:ªÄ/vܪUuÄîîabãßO>:,Ãýðußßäö@vîhäÜ>£¢hý+zAZbaBðУ|å|ªÐ*:Ã>ª:ð£ÐüßÖbuªOOA>Bb©ÃärÐîhzö,+|C:Aö', SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_VARCHAR(512)), array('|:ÃZ*UvAÃC:+ãb@ÃÃÖãZä|Üzß~:rðß~ub>ö£+++ªðÃuaå~|zA:ÜvCãÃa©,@ÖßbCå|rz+Cåzz,U+OzÜ:rAhO<aZCußðüýã¢Üä|*:©vrOhh:åå>@ÃîözÐÃî©åvBb|Oî*<Ü<@¢ýzÜðßöAz|.UÖZUbb_åBüî<O~r£ýußýB.ýåÃ~o.îÖä*zäã*Uöãvöî,_Ä_hrÐOüß@~zãÜ.|@åhü*C~h*Ðä.A._ArA:Oo/ö©ÐÜbßÐ_ý~ã.*.ßðA/h,ß<äßð.ý_Cßzu,bö<U|bÖ/ßÐv|£bhuvaaAߢ<ßöä©ãr/Ov¢AU:*Ã<,.üAÖªuZ*ãZäßZOª:<©ZÄ.îu+|aö¢ßÃî~_££ßªÐrÄ~*aî~,ü//ßüÃ.Üü>Ö©O~Z©@o.vv£|ÜäÖ:~CbîzÜoA_OaÄuOÜÃobð_¢/îßã@zC*ä£öuuߣîª/îa_Ü>@:OB>ü.ÄörßorUbß<bÄ©|b>ý,hÜ|£A@b©/z.*u¢+<öaA.£/©_¢/üãBö:üOÄ+OãbîÃÐ@ßð©>U/+r¢b<ªÖÄCAaª|U|>å:o@vo£äB*©C£ÐåhO_>î*.@~ü£bßbzh>üzbr*ÐhO|ÖöCð¢b,oå.AÜ£o>ö~_£BãßßOOo*©©ß:,Z*ª:,£+|ãoîCÄzo~vÖO@bÐðoðÖ:ÖÐ>bü£<z~A|ðOb.O©åb>äOB.bUåu¢©Z:îîßüoBö<ua~|Äãa/Ã_vvävª~¢baÄÜUÃîÐCaZv:A~öªUäª_ÃuU:_b.Aª£ZU*bbUÄýzÃߪßÄhu@Ä*UaÖýB.ß:zĪ@Ä_,ýABö@ÃîU|îÐB/_Zz~ÄÄ*¢|vUÃvß,vÄOCb/ÐCh|r£+Örb,Z+îa.AßýOÖ:Üävuå@ýãЪAýßOoA@býä*Oå,ðî+å©,CåÃv*vvüÖãÜ+*Üv,bãuýZöråB~ýîzýoCo+<oz_ãîÖ_ZobýäBC|ß_£ÃbO©ßOÖZ,©Ü©©OüzBb_ý*UÜ£AßCÐåÜÜo£<>ZZ>_z©<C_ü©å£CbbZ+©åða~zößCb@¢/zBýªüÖ£b+£ÜUhãî.aÄå+@+B£oaå@@|/ªð|+ß©_bz£ZzUhÖ:>A/B*£vîöý*/öåC|ßro*~<CÖ>¢|Ärbä@/~,>b:bü££/ßzCC:_Ö@Aü.åAðêÐb|Äîhãa,>£>*hrÃðbZ/,@CO<_ß_AÃ+|.ä+îbö_Ã<CÐüåUoîÜÄöü¢Uurö,U+zZýÃCbb>ÜZªý_¢övÜhZr,ðÜzÖ,öh¢höÄÄo+OCAãßO©C<Bö:ýZü:ßbAý,_©öÖhðå£*îZ+vÜhÐz@AÄßZrßööã©Äh¢©Oý©<BB©Uß>hr©bÐ_ßÄ>~av~u:hßrBrörv£OvC©£uãÜî*oahärzãý©b©î./aüv:o~|öðAî:/hbU', SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_VARCHAR('max')), array('34eeff6c-7d28-4323-9e28-d6b499fde336', SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_UNIQUEIDENTIFIER), array('4191-02-05 02:41:51.953', SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_DATETIME), array('1975-12-01 15:24:00', SQLSRV_PARAM_IN, null, SQLSRV_SQLTYPE_SMALLDATETIME));
default:
return array();
}
}
function Repro()
{
StartTest("sqlsrv_data_types_explict_fetch");
try
{
ExplicitFetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
echo "\nDone\n";
EndTest("sqlsrv_data_types_explict_fetch");
}
Repro();
?>
--EXPECT--

...Starting 'sqlsrv_data_types_explict_fetch' test...
Comparing data in row 1
Comparing data in row 2
Comparing data in row 3
Comparing data in row 4
Done
...Test 'sqlsrv_data_types_explict_fetch' completed successfully.

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,72 @@
--TEST--
Free statement twice
--FILE--
<?php
include 'tools.inc';
function ExecuteTwice()
{
require_once("autonomous_setup.php");
set_time_limit(0);
sqlsrv_configure('WarningsReturnAsErrors', 1);
sqlsrv_get_config('WarningsReturnAsErrors');
// Connect
$connectionInfo = array("UID"=>$username, "PWD"=>$password);
$conn = sqlsrv_connect($serverName, $connectionInfo);
if( !$conn ) { FatalError("Could not connect.\n"); }
$tableName = GetTempTableName();
$stmt = sqlsrv_query($conn, "CREATE TABLE $tableName ([c1_int] int, [c2_tinyint] tinyint)");
sqlsrv_free_stmt($stmt);
$stmt = sqlsrv_query($conn, "SELECT * FROM $tableName");
sqlsrv_execute($stmt);
$errors = sqlsrv_errors(SQLSRV_ERR_ALL);
$e = $errors[0];
$value1 = $e['message'];
print "$value1\n";
$value2 = $e['code'];
print "$value2\n";
$value3 = $e['SQLSTATE'];
print "$value3\n";
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
StartTest("sqlsrv_statement_execute_twice");
try
{
ExecuteTwice();
}
catch (Exception $e)
{
echo $e->getMessage();
}
echo "\nDone\n";
EndTest("sqlsrv_statement_execute_twice");
}
Repro();
?>
--EXPECT--

...Starting 'sqlsrv_statement_execute_twice' test...
A statement must be prepared with sqlsrv_prepare before calling sqlsrv_execute.
-23
IMSSP
Done
...Test 'sqlsrv_statement_execute_twice' completed successfully.

View file

@ -0,0 +1,68 @@
--TEST--
Fetch missing row
--FILE--
<?php
include 'tools.inc';
function MissingRow_Fetch()
{
include 'autonomous_setup.php';
set_time_limit(0);
sqlsrv_configure('WarningsReturnAsErrors', 1);
sqlsrv_get_config('WarningsReturnAsErrors');
// Connect
$connectionInfo = array("UID"=>$username, "PWD"=>$password);
$conn = sqlsrv_connect($serverName, $connectionInfo);
if( !$conn ) { FatalError("Could not connect.\n"); }
$tableName = GetTempTableName();
$stmt = sqlsrv_query($conn, "CREATE TABLE $tableName ([c1_int] int, [c2_tinyint] tinyint, [c3_smallint] smallint, [c4_bigint] bigint, [c5_bit] bit, [c6_float] float, [c7_real] real, [c8_decimal] decimal(28,4), [c9_numeric] numeric(32,4), [c10_money] money, [c11_smallmoney] smallmoney, [c12_char] char(512), [c13_varchar] varchar(512), [c14_varchar_max] varchar(max), [c15_nchar] nchar(512), [c16_nvarchar] nvarchar(512), [c17_nvarchar_max] nvarchar(max), [c18_text] text, [c19_ntext] ntext, [c20_binary] binary(512), [c21_varbinary] varbinary(512), [c22_varbinary_max] varbinary(max), [c23_image] image, [c24_uniqueidentifier] uniqueidentifier, [c25_datetime] datetime, [c26_smalldatetime] smalldatetime, [c27_timestamp] timestamp, [c28_xml] xml, [c29_time] time, [c30_date] date, [c31_datetime2] datetime2, [c32_datetimeoffset] datetimeoffset)");
sqlsrv_free_stmt($stmt);
$stmt = sqlsrv_query($conn, "SELECT * FROM $tableName");
$result1 = sqlsrv_fetch($stmt);
$result2 = sqlsrv_fetch($stmt);
$errors = sqlsrv_errors(SQLSRV_ERR_ALL);
$e = $errors[0];
$value1 = $e['message'];
print "$value1\n";
$value2 = $e['code'];
print "$value2\n";
$value3 = $e['SQLSTATE'];
print "$value3\n";
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
}
function Repro()
{
StartTest("sqlsrv_fetch_missing_row");
try
{
MissingRow_Fetch();
}
catch (Exception $e)
{
echo $e->getMessage();
}
echo "\nDone\n";
EndTest("sqlsrv_fetch_missing_row");
}
Repro();
?>
--EXPECT--

...Starting 'sqlsrv_fetch_missing_row' test...
There are no more rows in the active result set. Since this result set is not scrollable, no more data may be retrieved.
-22
IMSSP
Done
...Test 'sqlsrv_fetch_missing_row' completed successfully.

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,112 @@
--TEST--
Test insertion with floats
--FILE--
<?php
include 'tools.inc';
function ExecData($withParams)
{
include 'autonomous_setup.php';
set_time_limit(0);
sqlsrv_configure('WarningsReturnAsErrors', 1);
sqlsrv_get_config('WarningsReturnAsErrors');
// Connect
$connectionInfo = array("UID"=>$username, "PWD"=>$password);
$conn = sqlsrv_connect($serverName, $connectionInfo);
if( !$conn ) { FatalError("Could not connect.\n"); }
$tableName = GetTempTableName();
$stmt = sqlsrv_query($conn, "CREATE TABLE $tableName ([c1_float] float, [c2_real] real)");
sqlsrv_free_stmt($stmt);
if ($withParams)
{
$stmt = sqlsrv_prepare($conn, "INSERT INTO $tableName (c1_float, c2_real) VALUES (?, ?)", array(array(&$v1, SQLSRV_PARAM_IN), array(&$v2, SQLSRV_PARAM_IN)));
}
else
{
$stmt = sqlsrv_prepare($conn, "INSERT INTO $tableName (c1_float, c2_real) VALUES (?, ?)", array(&$v1, &$v2));
}
$values = array();
$v1 = 1.0;
array_push($values, $v1);
$v2 = 2.0;
array_push($values, $v2);
sqlsrv_execute($stmt);
$v1 = 11.0;
array_push($values, $v1);
$v2 = 12.0;
array_push($values, $v2);
sqlsrv_execute($stmt);
$v1 = 21.0;
array_push($values, $v1);
$v2 = 22.0;
array_push($values, $v2);
sqlsrv_execute($stmt);
$v1 = 31.0;
array_push($values, $v1);
$v2 = 32.0;
array_push($values, $v2);
sqlsrv_execute($stmt);
$v1 = 41.0;
array_push($values, $v1);
$v2 = 42.0;
array_push($values, $v2);
sqlsrv_execute($stmt);
sqlsrv_free_stmt($stmt);
$idx = 0;
$stmt = sqlsrv_query($conn, "SELECT * FROM $tableName");
while ($result = sqlsrv_fetch($stmt))
{
for ($i = 0; $i < 2; $i++)
{
$value = sqlsrv_get_field($stmt, $i);
$expected = $values[$idx++];
$diff = abs(($value - $expected) / $expected);
if ($diff > _EPSILON)
{
echo "Value $value is unexpected\n";
}
}
}
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
}
function Repro()
{
StartTest("sqlsrv_statement_exec_param_floats");
try
{
ExecData(true);
ExecData(false);
}
catch (Exception $e)
{
echo $e->getMessage();
}
echo "\nDone\n";
EndTest("sqlsrv_statement_exec_param_floats");
}
Repro();
?>
--EXPECT--

...Starting 'sqlsrv_statement_exec_param_floats' test...
Done
...Test 'sqlsrv_statement_exec_param_floats' completed successfully.

View file

@ -0,0 +1,162 @@
--TEST--
Test insertion with floats
--FILE--
<?php
include 'tools.inc';
function ExecData($withParams)
{
include 'autonomous_setup.php';
set_time_limit(0);
sqlsrv_configure('WarningsReturnAsErrors', 1);
sqlsrv_get_config('WarningsReturnAsErrors');
// Connect
$connectionInfo = array("UID"=>$username, "PWD"=>$password);
$conn = sqlsrv_connect($serverName, $connectionInfo);
if( !$conn ) { FatalError("Could not connect.\n"); }
$tableName = GetTempTableName();
$stmt = sqlsrv_query($conn, "CREATE TABLE $tableName ([c1_int] int, [c2_smallint] smallint)");
sqlsrv_free_stmt($stmt);
if ($withParams)
{
$stmt = sqlsrv_prepare($conn, "INSERT INTO $tableName (c1_int, c2_smallint) VALUES (?, ?)", array(array(&$v1, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_INT), array(&$v2, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_INT)));
}
else
{
$stmt = sqlsrv_prepare($conn, "INSERT INTO $tableName (c1_int, c2_smallint) VALUES (?, ?)", array(array(&$v1), array(&$v2)));
}
$values = array();
$numRows = 0;
$v1 = 1;
array_push($values, $v1);
$v2 = 2;
array_push($values, $v2);
sqlsrv_execute($stmt);
$numRows++;
$v1 = 11;
array_push($values, $v1);
$v2 = 12;
array_push($values, $v2);
sqlsrv_execute($stmt);
$numRows++;
$v1 = 21;
array_push($values, $v1);
$v2 = 22;
array_push($values, $v2);
sqlsrv_execute($stmt);
$numRows++;
$v1 = 31;
array_push($values, $v1);
$v2 = 32;
array_push($values, $v2);
sqlsrv_execute($stmt);
$numRows++;
$v1 = 41;
array_push($values, $v1);
$v2 = 42;
array_push($values, $v2);
sqlsrv_execute($stmt);
$numRows++;
sqlsrv_free_stmt($stmt);
$idx = 0;
$stmt = sqlsrv_query($conn, "SELECT * FROM $tableName");
while ($result = sqlsrv_fetch($stmt))
{
for ($i = 0; $i < 2; $i++)
{
$value = sqlsrv_get_field($stmt, $i);
$expected = $values[$idx++];
if ($expected !== $value)
{
echo "Value $value is unexpected\n";
}
}
}
sqlsrv_free_stmt($stmt);
DeleteRows($conn, $numRows, $tableName);
sqlsrv_close($conn);
}
function DeleteRows($conn, $numRows, $tableName)
{
$stmt1 = sqlsrv_prepare($conn, "SELECT * FROM $tableName");
$stmt2 = sqlsrv_prepare($conn, "DELETE TOP(3) FROM $tableName");
$noExpectedRows = $numRows;
$noDeletedRows = 3;
while ($noExpectedRows > 0)
{
sqlsrv_execute($stmt1);
$noActualRows = 0;
while ($result = sqlsrv_fetch($stmt1))
{
$noActualRows++;
}
echo "Number of Actual Rows: $noActualRows\n";
if ($noActualRows != $noExpectedRows)
{
echo("Number of retrieved rows does not match expected value\n");
}
sqlsrv_execute($stmt2);
$noAffectedRows = sqlsrv_rows_affected($stmt2);
$noActualRows = ($noExpectedRows >= $noDeletedRows)? $noDeletedRows : $noExpectedRows;
echo "Number of Affected Rows: $noAffectedRows\n";
if ($noActualRows != $noAffectedRows)
{
echo("Number of deleted rows does not match expected value\n");
}
$noExpectedRows -= $noDeletedRows;
}
sqlsrv_free_stmt($stmt1);
sqlsrv_free_stmt($stmt2);
}
function Repro()
{
StartTest("sqlsrv_statement_exec_param_ints");
try
{
ExecData(true);
ExecData(false);
}
catch (Exception $e)
{
echo $e->getMessage();
}
echo "\nDone\n";
EndTest("sqlsrv_statement_exec_param_ints");
}
Repro();
?>
--EXPECT--

...Starting 'sqlsrv_statement_exec_param_ints' test...
Number of Actual Rows: 5
Number of Affected Rows: 3
Number of Actual Rows: 2
Number of Affected Rows: 2
Number of Actual Rows: 5
Number of Affected Rows: 3
Number of Actual Rows: 2
Number of Affected Rows: 2
Done
...Test 'sqlsrv_statement_exec_param_ints' completed successfully.

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,78 @@
--TEST--
Test stored procedure that returns a varchar
--FILE--
<?php
include 'tools.inc';
function StoredProc_varchar()
{
include 'autonomous_setup.php';
set_time_limit(0);
sqlsrv_configure('WarningsReturnAsErrors', 1);
sqlsrv_get_config('WarningsReturnAsErrors');
// Connect
$connectionInfo = array("UID"=>$username, "PWD"=>$password);
$conn = sqlsrv_connect($serverName, $connectionInfo);
if( !$conn ) { FatalError("Could not connect.\n"); }
$procName = GetTempProcName();
$tsql = "CREATE PROC $procName (@p1 VARCHAR(37) OUTPUT, @p2 VARCHAR(21), @p3 VARCHAR(14))
AS
BEGIN
SET @p1 = CONVERT(VARCHAR(37), @p2 + @p3)
END";
$stmt = sqlsrv_query($conn, $tsql);
sqlsrv_free_stmt($stmt);
$retValue = '';
$stmt = sqlsrv_prepare($conn, "{CALL $procName (?, ?, ?)}", array(array(&$retValue, SQLSRV_PARAM_OUT, null, SQLSRV_SQLTYPE_NVARCHAR(38)), array('Microsoft SQL Server ', SQLSRV_PARAM_IN), array('Driver for PHP', SQLSRV_PARAM_IN)));
$retValue = '';
sqlsrv_execute($stmt);
echo("$retValue\n");
$retValue = 'Microsoft SQL Server Driver for PH';
sqlsrv_execute($stmt);
echo("$retValue\n");
$retValue = 'ABCDEFGHIJKLMNOPQRSTUWXYZMicrosoft ';
sqlsrv_execute($stmt);
echo("$retValue\n");
$retValue = 'ABCDEFGHIJKLMNOPQRSTUWXYZ_Microsoft SQL Server Driver for PHP';
sqlsrv_execute($stmt);
echo("$retValue\n");
$retValue = 'Microsoft SQL Server Driver for';
sqlsrv_execute($stmt);
echo("$retValue\n");
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
}
function Repro()
{
StartTest("sqlsrv_stored_proc_varchar");
try
{
StoredProc_varchar();
}
catch (Exception $e)
{
echo $e->getMessage();
}
echo "\nDone\n";
EndTest("sqlsrv_stored_proc_varchar");
}
Repro();
?>
--EXPECT--

...Starting 'sqlsrv_stored_proc_varchar' test...
Microsoft SQL Server Driver for PHP
Microsoft SQL Server Driver for PHP
Microsoft SQL Server Driver for PHP
Microsoft SQL Server Driver for PHP
Microsoft SQL Server Driver for PHP
Done
...Test 'sqlsrv_stored_proc_varchar' completed successfully.

928
test/sqlsrv/tools.inc Normal file
View file

@ -0,0 +1,928 @@
<?php
// Numeric values that corresponds to a SQL type:
define("_SQL_BIGINT", -5);
define("_SQL_BINARY", -2);
define("_SQL_BIT", -7);
define("_SQL_CHAR", 1);
define("_SQL_TYPE_DATE", 91);
define("_SQL_TYPE_TIMESTAMP", 93);
define("_SQL_DECIMAL", 3);
define("_SQL_FLOAT", 6);
define("_SQL_LONGVARBINARY", -4);
define("_SQL_INTEGER", 4);
define("_SQL_WCHAR", -8);
define("_SQL_WLONGVARCHAR", -10);
define("_SQL_NUMERIC", 2);
define("_SQL_WVARCHAR", -9);
define("_SQL_REAL", 7);
define("_SQL_SMALLINT", 5);
define("_SQL_LONGVARCHAR", -1);
define("_SQL_TINYINT", -6);
define("_SQL_VARBINARY", -3);
define("_SQL_VARCHAR", 12);
define("_SQL_SS_XML", -152);
define("_SQL_GUID", -11);
define("_SQL_SS_TIME2", -154);
define("_SQL_SS_TIMESTAMPOFFSET", -155);
define("_CHUNK_SIZE", 8192);
define("_EPSILON", 0.00001);
function StartTest($testName)
{
echo "\n...Starting '$testName' test...\n";
if (!extension_loaded("sqlsrv"))
{
die("sqlsrv driver cannot be loaded.");
}
}
function EndTest($testName)
{
echo "...Test '$testName' completed successfully.\n";
}
function GetTempTableName($table = '')
{
// A temporary table name with the '#' prefix will be automatically
// dropped once the connection is closed
$timestamp = round(microtime(true)*1000);
if (strlen($table) == 0)
return "#php_test_table" . $timestamp;
else
return $table . $timestamp;
}
function GetTempProcName($proc = '')
{
// A temporary stored procedure name with the '#' prefix will be
// automatically dropped once the connection is closed
$timestamp = round(microtime(true)*1000);
if (strlen($proc) == 0)
return "#php_test_proc" . $timestamp;
else
return $proc . $timestamp;
}
function FatalError($errorMsg)
{
handle_errors();
die($errorMsg);
}
function handle_errors()
{
$errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
if(count($errors) == 0)
{
$errors = sqlsrv_errors(SQLSRV_ERR_ALL);
}
$count = count($errors);
for($i = 0; $i < $count; $i++)
{
echo $errors[$i]['message'];
}
}
function Verify($stmt, $metadata, $numFields, $encoding)
{
$i = 0;
while ($result = sqlsrv_fetch($stmt))
{
echo "Comparing data in row " . ++$i . "\n";
$data = GetInputData($i);
$dataArray = SimplifyDataArray($data, $metadata, $i);
for ($j = 0; $j < $numFields; $j++)
{
$value = sqlsrv_get_field($stmt, $j, SQLSRV_PHPTYPE_STRING($encoding));
CompareData($metadata, $i, $j, $value, $dataArray[$j], False, False);
}
}
// returns the number of rows fetched
return $i;
}
function ConvertDataToString($type, $data)
{
if ($data === null)
return "";
// Convert raw data to strings for datetime and binary types only
// Do nothing for other types
//
if (IsDateTime($type))
{
if ($type != _SQL_SS_TIME2)
return date_format( $data, 'Y-m-d H:i:s' );
else
return date_format( $data, 'H:i:s' );
}
else if (IsBinary($type))
{
return bin2hex($data);
}
else
{
return $data;
}
}
function CompareCharacterData($actual, $expected, $errorMode = false)
{
// $errorMode is true if an error is expected
$matched = false;
if ($actual === $expected)
{
$matched = true;
}
else
{
$len = strlen($expected);
$result = strncmp($expected, $actual, $len);
if ($result == 0)
{
$matched = true;
}
}
// echo "Expected: $expected\nActual: $actual\n";
if ($matched)
{
if ($errorMode)
{
echo "Data corruption expected...\n";
}
}
else
{
if (! $errorMode)
{
echo "Data corruption!! Expected: $expected\nActual: $actual\n";
}
}
return $matched;
}
function CompareNumericData($actual, $expected)
{
if (! is_numeric($actual))
{
return false;
}
// only compare up to the length of the expected value, especially for floats
if (is_float($expected))
{
$len = strlen($expected);
$actual = substr($actual, 0, $len);
}
$f_actual = floatval($actual);
$f_expected = floatval($expected);
$matched = ($f_actual == $f_expected);
if (! $matched)
{
// compare floating point values
$diff = abs(($f_actual - $f_expected) / $f_expected);
$matched = ($diff < _EPSILON);
if (! $matched)
{
echo "Data corruption: values don't match\n";
}
}
return $matched;
}
function CheckData($colType, $actual, $expected)
{
$success = true;
if (IsNumeric($colType))
{
if (! CompareNumericData($actual, $expected))
{
$success = false;
}
}
else
{
$actual = trim($actual);
$len = strlen($expected);
if (IsDateTime($colType))
{
if ($colType != _SQL_SS_TIME2)
$len = min(strlen("YYYY-MM-DD HH:mm:ss"), $len);
else
$len = min(strlen("HH:mm:ss"), $len);
}
if (strncasecmp($actual, $expected, $len) != 0)
{
$success = false;
}
}
return ($success);
}
function ReadBinaryStream($filename)
{
$handle = fopen($filename, "rb");
$contents = fread($handle, filesize($filename));
fclose($handle);
return $contents;
}
function ToByteArray($input)
{
// this should be int[] which can be converted
// to byte[] in C# since values are range of 0 - 255
return unpack('C*', $input);
}
function CompareByteArrays($actual, $expected)
{
$actualArray = ToByteArray($actual);
$expectedArray = ToByteArray($expected);
echo "Data read:\t";
print_r($actualArray);
echo "Expected:\t";
print_r($expectedArray);
}
function CompareDataStream($colType, $rowIndex, $colName, $stream, $expected)
{
$len = strlen($expected);
$matched = false;
if ($len == 0)
{
$contents = fread($stream, _CHUNK_SIZE);
$contents = trim($contents); // removes all whitespace
if (strlen($contents) == 0)
{
$matched = true;
}
}
else if ($len < _CHUNK_SIZE)
{
$contents = fread($stream, $len);
$matched = CompareDataValue($colType, $rowIndex, $colName, $contents, $expected);
}
else
{
$matched = true;
$pos = 0;
while (! feof($stream) && $pos < $len)
{
$contents = fread($stream, _CHUNK_SIZE);
$contents = ConvertDataToString($colType, $contents);
$contents_len = strlen($contents);
$result = substr_compare($expected, $contents, $pos, $contents_len, TRUE);
if ($result != 0)
{
break;
$matched = false;
}
$pos += $contents_len;
}
}
if (! $matched)
{
echo "Data corruption on row $rowIndex column $colName\n";
}
return $matched;
}
function CompareBinaryData($actual, $expected)
{
// this function assumes $actual is a stream of hex
$len = strlen($expected);
$pos = 0;
$matched = true;
while (! feof($actual) && $pos < $len)
{
$contents = fread($actual, _CHUNK_SIZE);
$result = 0;
$str = unpack("H*", $contents);
$contents = $str[1];
$contents_len = strlen($contents);
$count = $contents_len;
if ($len < ($pos + $contents_len))
{
$count = $len - $pos;
}
$result = substr_compare($expected, $contents, $pos, $count, TRUE);
if ($result != 0)
{
//echo "Expected: " . substr($expected, $pos, $count) . "\nActual: $contents\n";
$matched = false;
break;
}
$pos += $count;
}
return $matched;
}
function CompareStreamData($actual, $expected, $isUnicode)
{
// this function assumes $actual is a stream of character data
$matched = true;
// convert $expected to UCS-2LE (Little Endian)
$str = iconv("UTF-8", "UCS-2LE", $expected);
// every character of $str consists of two bytes but if
// it's unicode, the character of data is also two bytes
$shift = 1;
if ($isUnicode)
$shift = 2;
$len = strlen($str);
$pos = 0;
while ($matched && ! feof($actual) && $pos < $len)
{
$contents = fread($actual, _CHUNK_SIZE);
$contents_len = strlen($contents);
$i = 0;
while ($matched && $i < $contents_len && $pos < $len)
{
if ($contents[$i] != $str[$pos])
{
//echo "Expected at [$pos]: $str[$pos]\nActual at [$i]: $contents[$i]\n";
$matched = false;
break;
}
$pos += 2;
$i += $shift;
}
}
return $matched;
}
function CompareBinaryStream($metadata, $rowIndex, $colIndex, $actual, $expected)
{
// unlike CompareDataStream(), this method assumes $actual is a stream
// and no non-updatable fields (timestamp column)
if (is_null($actual))
{
if ($expected === "")
return true;
else
return false;
}
$colName = $metadata[$colIndex]['Name'];
$colType = $metadata[$colIndex]['Type'];
$matched = false;
if (IsBinary($colType))
{
$matched = CompareBinaryData($actual, $expected);
}
else
{
// stream of characters
$matched = CompareStreamData($actual, $expected, IsUnicode($colType));
}
if (! $matched)
{
echo "Data not matching on row $rowIndex column $colName\n";
}
return $matched;
}
function CompareStringToFile($rowIndex, $colName, $actual, $file, $isBinary)
{
$matched = true;
$pos = 0;
while ($matched && ! feof($file))
{
$expected = fread($file, _CHUNK_SIZE);
if ($isBinary)
{
$str = unpack("H*", $expected);
$expected = $str[1];
}
$len = strlen($expected);
$contents = substr($actual, $pos, $len);
$result = strcasecmp($expected, $contents);
$matched = ($result == 0);
$pos += $len;
}
if (! $matched)
{
echo "Data not matching on row $rowIndex column $colName\n";
}
return $matched;
}
function CompareStreamToFile($rowIndex, $colName, $stream, $file, $colType)
{
// This function is complicated because it's comparing two stream data
// one from stream resource and one from a file
// Moreover, the data can be binary or character/unicode character
$isBinary = IsBinary($colType);
$matched = true;
while ($matched && ! feof($file) && ! feof ($stream))
{
$expected = fread($file, _CHUNK_SIZE);
$actual = fread($stream, _CHUNK_SIZE);
if ($isBinary)
{
$str = unpack("H*", $expected);
$expected = $str[1];
$str = unpack("H*", $actual);
$actual = $str[1];
$matched = ($expected == $actual);
}
else
{
// not reading binary hex data here
// similar to CompareStreamData(), except comparing two chunks at a time
// first convert $expected to UCS-2LE (Little Endian)
$expected = iconv("UTF-8", "UCS-2LE", $expected);
// every character of $expected consists of two bytes but if
// it's unicode, the character of data is also two bytes
$shift = 1;
if (IsUnicode($colType))
$shift = 2;
$i = 0;
$pos = 0;
$data_len = strlen($actual);
while ($matched && $i < $data_len)
{
if ($actual[$i] != $expected[$pos])
{
echo "Expected at [$pos]: $expected[$pos]\nActual at [$i]: $actual[$i]\n";
$matched = false;
break;
}
$pos += 2;
$i += $shift;
}
}
}
if (! $matched)
{
echo "Data not matching on row $rowIndex column $colName\n";
}
return $matched;
}
function CompareDataValue($colType, $rowIndex, $colName, $actual, $expected, $bConvert = true)
{
if ($bConvert)
{
$actual = ConvertDataToString($colType, $actual);
}
$matched = CheckData($colType, $actual, $expected);
if (! $matched)
{
echo "Data corruption on row $rowIndex column $colName\n";
echo "Expected: $expected\nActual: $actual\n";
}
return $matched;
}
function CompareData($metadata, $rowIndex, $colIndex, $actual, $expected, $isStream, $bConvert = true)
{
if (is_null($actual))
{
if ($expected === "")
return true;
else
return false;
}
$colName = $metadata[$colIndex]['Name'];
$colType = $metadata[$colIndex]['Type'];
if ($actual === false)
{
FatalError("Field $colName of row $rowIndex is missing\n");
}
if (! IsUpdatable($colName))
{
return true; // do nothing for non-IsUpdatable fields
}
if ($isStream)
{
return CompareDataStream($colType, $rowIndex, $colName, $actual, $expected);
}
else
{
return CompareDataValue($colType, $rowIndex, $colName, $actual, $expected, $bConvert);
}
}
function CompareLOBToFile($rowIndex, $colType, $colName, $actual, $filename, $readStream)
{
$isBinary = IsBinary($colType);
$mode = ($isBinary)? "rb" : "r";
$file = fopen($filename, $mode);
echo "...reading LOB data from '$filename'...";
$matched = false;
if ($readStream)
{
$matched = CompareStreamToFile($rowIndex, $colName, $actual, $file, $colType);
}
else
{
$matched = CompareStringToFile($rowIndex, $colName, $actual, $file, $isBinary);
}
fclose($file);
return $matched;
}
function VerifyLOBData($metadata, $rowIndex, $colIndex, $lobColumn, $actual, $expected, $filename, $readStream)
{
$colName = $metadata[$colIndex]['Name'];
$colType = $metadata[$colIndex]['Type'];
$matched = false;
if ($readStream && IsStreamable($colType))
{
if ($colIndex != $lobColumn)
{
echo "...reading binary stream...";
$matched = CompareBinaryStream($metadata, $rowIndex, $colIndex, $actual, $expected);
}
else
{
$matched = CompareLOBToFile($rowIndex, $colType, $colName, $actual, $filename, true);
}
}
else
{
if ($colIndex != $lobColumn)
{
echo "...reading string value...";
$matched = CompareDataValue($colType, $rowIndex, $colName, $actual, $expected, false);
}
else
{
$matched = CompareLOBToFile($rowIndex, $colType, $colName, $actual, $filename, false);
}
}
return $matched;
}
function SimplifyDataArray($data, $metadata, $row)
{
$dataArray = array();
$numFields = count($metadata);
$skipCount = 0;
for ($j = 0; $j < $numFields; $j++)
{
$colName = $metadata[$j]['Name'];
$colType = $metadata[$j]['Type'];
if (!IsUpdatable($colName))
{
$skipCount++;
array_push($dataArray, "");
}
else
{
// only need the first element of each array
$value = $data[$j - $skipCount][0];
if (is_a($value, 'DateTime'))
{
$value = date_format( $value, 'Y-m-d H:i:s' );
}
array_push($dataArray, $value);
}
}
return $dataArray;
}
function InsertDataToArray($query, $metadata, $row)
{
$dataArray = array();
$numFields = count($metadata);
$skipCount = 0;
for ($j = 0; $j < $numFields; $j++)
{
$colName = $metadata[$j]['Name'];
$type = $metadata[$j]['Type'];
$col = $j + 1;
if (!IsUpdatable($colName))
{
$skipCount++;
array_push($dataArray, "");
}
else
{
$data = GetInsertData($query, $type, $row, $col, $skipCount);
array_push($dataArray, $data);
}
}
return $dataArray;
}
function GetInsertData($query, $colType, $rowIndex, $colIndex, $skip)
{
$data = strstr($query, "((");
$pos = 1;
if ($data === false)
{
die("Failed to retrieve data on row $rowIndex");
}
$data = substr($data, 2);
while ($pos < ($colIndex - $skip))
{
$data = strstr($data, ", (");
$pos++;
if ($data === false)
{
die("Failed to retrieve data on column $pos");
}
$data = substr($data, 3);
}
// Is it's XML type, we can't use the closing bracket as the next delimiter
// because a bracket can be part of the xml data, unless the data is null
$str = ")";
$pos = strpos($data, $str);
if ($pos === false)
{
die("Failed to isolate data on row $rowIndex, column $pos");
}
$tmp = substr($data, 0, $pos);
if ((strcasecmp($tmp, "null") == 0) || strlen($tmp) == 0)
{
$tmp = "";
}
else if (IsXml($colType))
{
$str = ">')";
$pos = strpos($data, $str);
$tmp = substr($data, 0, $pos + 2);
}
$data = $tmp;
if (IsDataUnicode($colType, $data)) // this includes unicode data type and XML data that is in Unicode
{ // N'data'
$data = substr($data, 2, strlen($data) - 3);
}
else if (IsLiteral($colType))
{ // 'data'
$data = substr($data, 1, strlen($data) - 2);
}
else if (IsBinary($colType))
{ // 0xdata
$data = substr($data, 2);
}
return (trim($data));
}
function IsStreamable($type)
{
switch ($type)
{
case _SQL_CHAR: // char
return true;
case _SQL_WCHAR: // nchar
return true;
case _SQL_VARCHAR: // varchar
return true;
case _SQL_WVARCHAR: // nvarchar
return true;
case _SQL_LONGVARCHAR: // text
return true;
case _SQL_WLONGVARCHAR: // ntext
return true;
case _SQL_BINARY: // binary
return true;
case _SQL_VARBINARY: // varbinary
return true;
case _SQL_LONGVARBINARY: // image
return true;
case _SQL_SS_XML: // xml
return true;
default:
break;
}
return (false);
}
function IsNumeric($type)
{
switch ($type)
{
case _SQL_INTEGER : // int
return true;
case _SQL_TINYINT : // tinyint
return true;
case _SQL_SMALLINT : // smallint
return true;
case _SQL_BIGINT : // bigint
return true;
case _SQL_BIT : // bit
return true;
case _SQL_FLOAT : // float
return true;
case _SQL_REAL : // real
return true;
case _SQL_DECIMAL : // decimal
return true;
case _SQL_NUMERIC : // numeric, money, smallmoney
return true;
default: break;
}
return (false);
}
function IsChar($type)
{
switch ($type)
{
case _SQL_WCHAR: // nchar
return true;
case _SQL_VARCHAR: // varchar
return true;
case _SQL_WVARCHAR: // nvarchar
return true;
case _SQL_LONGVARCHAR: // text
return true;
case _SQL_WLONGVARCHAR: // ntext
return true;
case _SQL_SS_XML: // xml
return true;
default:
break;
}
return (false);
}
function IsBinary($type)
{
switch ($type)
{
case _SQL_BINARY: // binary
return true;
case _SQL_VARBINARY: // varbinary
return true;
case _SQL_LONGVARBINARY: // image
return true;
default:
break;
}
return (false);
}
function IsDateTime($type)
{
switch ($type)
{
case _SQL_TYPE_TIMESTAMP: // datetime, smalldatetime
return true;
case _SQL_TYPE_DATE: // date
return true;
case _SQL_SS_TIME2: // time
return true;
case _SQL_SS_TIMESTAMPOFFSET: // datetimeoffset
return true;
default:
break;
}
return (false);
}
function IsDataUnicode($colType, $data)
{
if (IsUnicode($colType))
return true;
// This input string may be an XML string in unicode (i.e. // N'<xmldata>...</xmldata>')
$letterN = 'N';
$index = strpos($data, $letterN);
// Note the use of ===. Simply == would not work as expected
// because the position of letterN 'N' may be the 0th (first) character
// and strpos will return false if not found.
if ($index === 0) {
return true;
}
return false;
}
function IsUnicode($type)
{
switch ($type)
{
case _SQL_WCHAR: // nchar
return true;
case _SQL_WVARCHAR: // nvarchar
return true;
case _SQL_WLONGVARCHAR: // ntext
return true;
default:
break;
}
return (false);
}
function IsXml($type)
{
return ($type == _SQL_SS_XML);
}
function IsUpdatable($colName)
{
$pos = strpos($colName, "_");
$type = substr($colName, $pos + 1);
return (strcasecmp($type, "timestamp") != 0);
}
function IsLiteral($type)
{
switch ($type)
{
case _SQL_CHAR: // char
return true;
case _SQL_WCHAR: // nchar
return true;
case _SQL_VARCHAR: // varchar
return true;
case _SQL_WVARCHAR: // nvarchar
return true;
case _SQL_LONGVARCHAR: // text
return true;
case _SQL_WLONGVARCHAR: // ntext
return true;
case _SQL_GUID: // uniqueidentifier
return true;
case _SQL_TYPE_TIMESTAMP: // datetime, smalldatetime
return true;
case _SQL_TYPE_DATE: // date
return true;
case _SQL_SS_TIME2: // time
return true;
case _SQL_SS_TIMESTAMPOFFSET: // datetimeoffset
return true;
case _SQL_SS_XML: // xml
return true;
default:
break;
}
return (false);
}
?>