sqlsrv TC tests

This commit is contained in:
yitam 2017-05-03 16:00:31 -07:00
parent ca50a21bd8
commit 135545799a
48 changed files with 5037 additions and 1 deletions

View file

@ -1095,7 +1095,7 @@ function handle_errors()
{
for($i = 0; $i < $count; $i++)
{
echo ($errors[$i]['message']."\n");
trace ($errors[$i]['message']."\n");
}
}
}

View file

@ -0,0 +1,35 @@
--TEST--
Driver Loading Test
--DESCRIPTION--
Loads the PHP driver to check whether it is operational or not by checking if SQLSRV is enabled in phpinfo()
--ENV--
PHPT_EXEC=true
--FILE--
<?php
include 'MsCommon.inc';
function Info()
{
ob_start();
phpinfo();
$data = ob_get_contents();
ob_clean();
return $data;
}
$testName = "Driver Loading";
StartTest($testName);
preg_match ( '/sqlsrv support.*/', Info(), $matches );
var_dump( $matches );
EndTest($testName);
?>
--EXPECT--
array(1) {
[0]=>
string(25) "sqlsrv support => enabled"
}
Test "Driver Loading" completed successfully.

View file

@ -0,0 +1,60 @@
--TEST--
Driver Setup Test
--DESCRIPTION--
Verifies the logging facility by checking the ability to set
and retrieve the values of “LogSubsystem” and "LogSeverity”
parameters.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function LoggingSetup()
{
$testName = "Driver Logging Setup";
StartTest($testName);
Configure('LogSubsystems', -1);
Configure('LogSubsystems', 1);
Configure('LogSubsystems', 2);
Configure('LogSubsystems', 4);
Configure('LogSubsystems', 8);
Configure('LogSubsystems', 0);
Configure('LogSeverity', -1);
Configure('LogSeverity', 1);
Configure('LogSeverity', 2);
Configure('LogSeverity', 4);
Configure('LogSubsystems', SQLSRV_LOG_SYSTEM_OFF);
Configure('LogSeverity', SQLSRV_LOG_SEVERITY_ERROR);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
LoggingSetup();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
sqlsrv_configure('WarningsReturnAsError', 0);
Repro();
?>
--EXPECT--
Test "Driver Logging Setup" completed successfully.

View file

@ -0,0 +1,71 @@
--TEST--
Connection Test
--DESCRIPTION--
Checks whether the driver can successfully establish a database connection.
Verifies as well that invalid connection attempts fail as expected.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ConnectionTest()
{
include 'MsSetup.inc';
$testName = "Connection";
StartTest($testName);
Setup();
// Invalid connection attempt => errors are expected
Trace("Invalid connection attempt (to a non-existing server) ....\n");
$conn1 = sqlsrv_connect('InvalidServerName');
if ($conn1 === false)
{
handle_errors();
}
else
{
die("Invalid connection attempt should have failed.");
}
// Valid connection attempt => no errors are expected
Trace("\nValid connection attempt (to $server) ....\n");
$conn2 = Connect();
$errors = sqlsrv_errors(SQLSRV_ERR_ERRORS);
if(count($errors) != 0)
{
die("No errors were expected on valid connection attempts.");
}
sqlsrv_close($conn2);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ConnectionTest();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Connection" completed successfully.

View file

@ -0,0 +1,80 @@
--TEST--
Client Info Test
--DESCRIPTION--
Verifies the functionality of "sqlsrv_client_info”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ClientInfo()
{
include 'MsSetup.inc';
$testName = "Connection - Client Info";
StartTest($testName);
Setup();
$conn1 = Connect();
$clientinfo1 = sqlsrv_client_info($conn1);
$count1 = count($clientinfo1);
if ($count1 != 4)
{
die("Unexpected size for client_info array: ".$count1);
}
$driverName = 'DriverDllName';
$uname = php_uname();
if (IsWindows())
{
$driverName = 'DriverDllName';
}
else // other than Windows
{
$driverName = 'DriverName';
}
ShowInfo($clientinfo1, 'ExtensionVer');
ShowInfo($clientinfo1, $driverName);
ShowInfo($clientinfo1, 'DriverVer');
ShowInfo($clientinfo1, 'DriverODBCVer');
sqlsrv_close($conn1);
EndTest($testName);
}
function ShowInfo($clientInfo, $infoTag)
{
$info = $clientInfo[$infoTag];
Trace("$infoTag\t= $info\n");
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ClientInfo();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Connection - Client Info" completed successfully.

View file

@ -0,0 +1,73 @@
--TEST--
Server Info Test
--DESCRIPTION--
Verifies the functionality of “sqlsrv_server_info”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ServerInfo()
{
include 'MsSetup.inc';
$testName = "Connection - Server Info";
StartTest($testName);
Setup();
$conn1 = Connect();
$serverinfo1 = sqlsrv_server_info($conn1);
$count1 = count($serverinfo1);
if ($count1 != 3)
{
die("Unexpected size for server_info array: ".$count1);
}
ShowInfo($serverinfo1, 'CurrentDatabase');
ShowInfo($serverinfo1, 'SQLServerName');
ShowInfo($serverinfo1, 'SQLServerVersion');
sqlsrv_close($conn1);
EndTest($testName);
}
function ShowInfo($serverInfo, $infoTag)
{
$info = $serverInfo[$infoTag];
if (TraceMode())
{
echo "$infoTag\t";
if (strlen($infoTag) <= 15)
{
echo "\t";
}
echo "$info\n";
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ServerInfo();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Connection - Server Info" completed successfully.

View file

@ -0,0 +1,90 @@
--TEST--
Connection Close Test
--DESCRIPTION--
Verifies that a connection can be closed multiple times and
that resources are invalidated when connection is closed.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ConnectionClose()
{
include 'MsSetup.inc';
$testName = "Connection - Close";
StartTest($testName);
Setup();
$noRows = 5;
$conn1 = Connect();
CreateTable($conn1, $tableName);
InsertRows($conn1, $tableName, $noRows);
// Close connection twice
for ($i = 0; $i < 2; $i++)
{
$ret = sqlsrv_close($conn1);
if ($ret === false)
{
die("Unexpected return for sqlsrv_close: $ret");
}
}
// Invalid Query
$stmt1 = sqlsrv_query($conn1, "SELECT * FROM [$tableName]");
if ($stmt1)
{
die("Select query should fail when connection is closed");
}
// Invalid Statement
$conn2 = Connect();
$stmt2 = SelectFromTable($conn2, $tableName);
sqlsrv_close($conn2);
if (sqlsrv_fetch($stmt2))
{
die("Fetch should fail when connection is closed");
}
$conn3 = Connect();
DropTable($conn3, $tableName);
sqlsrv_close($conn3);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ConnectionClose();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTREGEX--
Warning: sqlsrv_close\(\): supplied resource is not a valid ss_sqlsrv_conn resource in .*TC24_Close.php on line 21
Warning: sqlsrv_query\(\): supplied resource is not a valid ss_sqlsrv_conn resource in .*TC24_Close.php on line 29
Warning: sqlsrv_fetch\(\): supplied resource is not a valid ss_sqlsrv_stmt resource in .*TC24_Close.php on line 39
Test "Connection - Close" completed successfully.

View file

@ -0,0 +1,70 @@
--TEST--
Simple Query Test
--DESCRIPTION--
Basic verification of query statements (via "sqlsrv_query"):
- Establish a connection
- Creates a table (including all 28 SQL types currently supported)
- Executes a SELECT query (on the empty table)
- Verifies the outcome
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function SimpleQuery()
{
include 'MsSetup.inc';
$testName = "Statement - Simple Query";
StartTest($testName);
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
Trace("Executing SELECT query on $tableName ...");
$stmt1 = SelectFromTable($conn1, $tableName);
$rows = RowCount($stmt1);;
sqlsrv_free_stmt($stmt1);
Trace(" $rows rows retrieved.\n");
if ($rows > 0)
{
die("Table $tableName, expected to be empty, has $rows rows.");
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
SimpleQuery();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Statement - Simple Query" completed successfully.

View file

@ -0,0 +1,104 @@
--TEST--
Delete Query Test
--DESCRIPTION--
Executes several INSERT queries followed by DELETE queries and
validates the outcome reported by "sqlsrv_rows_affected".
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function DeleteQuery()
{
include 'MsSetup.inc';
$testName = "Statement - Delete Query";
StartTest($testName);
Setup();
$conn1 = Connect();
$noRows = 10;
CreateTable($conn1, $tableName);
$noRowsInserted = InsertRows($conn1, $tableName, $noRows);
$row = 1;
$keyValue = "0";
while ($row <= $noRowsInserted)
{
$stmt1 = SelectFromTable($conn1, $tableName);
if (sqlsrv_fetch($stmt1) === false)
{
FatalError("Failed to retrieve 1st row of data from test table");
}
$keyValue = sqlsrv_get_field($stmt1, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
sqlsrv_free_stmt($stmt1);
Trace("Deleting rows from $tableName ...");
$delRows = 1;
if (strlen($keyValue) == 0)
{
$stmt2 = ExecuteQuery($conn1, "DELETE TOP(1) FROM [$tableName]");
$cond = "(top row)";
}
else
{
$cond = "(c1_int = $keyValue)";
$stmt3 = SelectFromTableEx($conn1, $tableName, $cond);
$delRows = RowCount($stmt3);
sqlsrv_free_stmt($stmt3);
$stmt2 = ExecuteQuery($conn1, "DELETE FROM [$tableName] WHERE $cond");
}
$numRows1 = sqlsrv_rows_affected($stmt2);
sqlsrv_free_stmt($stmt2);
Trace(" $numRows1 row".(($numRows1 > 1) ? "s" : " ")." $cond.\n");
if ($numRows1 != $delRows)
{
die("Unexpected row count at delete: $numRows1 instead of $delRows");
}
$row += $numRows1;
}
$stmt3 = ExecuteQuery($conn1, "DELETE TOP(1) FROM [$tableName]");
$numRows2 = sqlsrv_rows_affected($stmt3);
sqlsrv_free_stmt($stmt3);
if ($numRows2 > 0)
{
die("Unexpected row count at delete: $numRows2");
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
DeleteQuery();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Statement - Delete Query" completed successfully.

View file

@ -0,0 +1,90 @@
--TEST--
Complex Query Test
--DESCRIPTION--
Verifies the behavior of INSERT queries with and without the IDENTITY flag set.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ComplexQuery()
{
include 'MsSetup.inc';
$testName = "Statement - Complex Query";
StartTest($testName);
Setup();
$conn1 = Connect();
$dataTypes = "[c1_int] int IDENTITY, [c2_tinyint] tinyint, [c3_smallint] smallint, [c4_bigint] bigint, [c5_varchar] varchar(512)";
CreateTableEx($conn1, $tableName, $dataTypes);
Execute($conn1, true, "SET IDENTITY_INSERT [$tableName] ON;");
Execute($conn1, true, "INSERT INTO [$tableName] (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_varchar) VALUES (-204401468, 168, 4787, 1583186637, 'î<ÄäC~zããa.Oa._ߣ*©<u_ßßCÃoa äãäÐßa+OühäobUa:zB_CÖ@~UÄz+ÃîÐ//Z@üo_:r,o¢ÃrßzoZß*ߪªå~ U¢a>£ÃZUÄ/ä_ZãðäåhüCã+/.obî|ößß,ð¢ðð:ÄÐ:*/>+/¢aö.öÄ<ð:>äO~*~ßÄzå¢<ª£ðý.O,>Ü,åbü@böhýC*<<hbÖä*o©¢h¢Ðüa+A/_@b/ÃBýBªß@ã~zÖZýC@äU_ßUßhvU*a@ÃðÄ:ªZAßAb£U_¢ßbãä:üåãorýÃߪ_ãÐÖªzãðåãoaü <ß~zZªaB.+åA¢ãÖ><î:/Ur î¢UßåOaÄ:a|++ª©.r~:/+ä|©ýo++v_@BZ:©©AßCð.©/Ab<,îß>UãÜÜöbb|ßÐߣ:î<<bîöa+,<_aÄ._ª>Ü<|ÖzÃz@>¢ª:a,CÜr__ª.<öÜCã+UÖU¢_üzü bÃ~ßo|, .î,b/U>äýaBZ@Ü£: bÖvýb>Ã/ÜÃ@üÖ/äb¢+r:Zß>ÐÜ|üu©ßZAC:Cßh *.ã£_ýîu|Urå.:aAUv@u>@<Öü.<ãZ böZAÜÖ£oüÐä*,ü:ðä')");
Execute($conn1, true, "SET IDENTITY_INSERT [$tableName] OFF;");
Execute($conn1, false,"INSERT INTO [$tableName] (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_varchar) VALUES (1264768176, 111, 23449, 1421472052, 'uå©C@bðUOv~,©v,BZÜ*oh>zb_åÐä<@*OOå_Ö<ãuß/oßr <ðãbÜUßÜÃÖÄ~¢~£ bÜ©î.uÜТª:|_ÐüÄBÐbüåßÃv@,<CßOäv~:+,CZîvhC/oßUuößa<å>©/Ub,+AЩî:ÖrýB+~~ßßßãÜ+_<vO@ ßÃüÖîaCzÐîå@:rý.~vh~r.ÃbÃã©å_îCär BÖÜ:BbUväåöZ+|,CîaAöC,aîbb*UÜßßA hCu¢hOb ð|ßC.<C<.aBßvuÃÖå,AÐa>ABðöU/O<ÖãüªOãuߣ~uÖ+ßÄrbî/:ÖÖo /_ÃO:uÃzðUvã£Aã_BÐ/>UCr,Äå aÄÐaãvÖZ@ªr*_::~/+.å~ð©aÄßbz*z<~rU~O+Z|A<_Büß©¢ö ::.Übýüßr/örh¢:ääU äOA~Aîr<¢äv¢Ä+hC/vßoUª+Oãªã*ð¢Bö.Zbh/ä,åä>*öðßUßý>aªbBbvßãÖ/bã|ýÖ u.zý©~äðzÐU.UA*a*.¢>î rß ~Cüßaö+rª~ß@aã/ÐCß*a,ªÄbb<o+v.åu<£B<îBZßåu£/_>*~')");
Execute($conn1, true, "SET IDENTITY_INSERT [$tableName] ON;INSERT INTO [$tableName] (c1_int, c2_tinyint, c3_smallint, c4_bigint, c5_varchar) VALUES (-411114769, 198, 1378, 140345831, 'Ü@ßaörêA*ÐüßA>_hOüv@|h~O<¢+*ÃÐCbazÜaåZ/Öö:ýãuöÐaz£ÐAh+u+rß:| U*¢ªåßÄÐ_vî@@~ChÐö_å*AAýBö¢B,ßbßå.ÃB+u*CAvÜ,ã>ªßCU<åî©ürz¢@ör¢*Öub¢BåaÜ@ª.äBv¢o~ ßýo oîu/>ÜÐÄ,ð,ðaOÖå>ðC:öZ>ßåð©<ð¢+£r.bO.©,uAßr><ov:,ÄßîåÃ+å./||CUÜÜ_ÖĪh~<ã_å/hbý Ä©uBuß<Ö@boÖýBãCÜA/öÄ:© ßUü*ývuß.Bãååo_übýr_üß>ÐÃÜ£B¢AªvaîvýßCÜUß åvöuª><îÐUC*aÖU©rªhr+>|äýî|oðröУ<ª<Ö|AªohäAî_vu~:~£Ãhü+ÃBuÄð ü@Z+Ä@hÖî¢|@bU£_ü/£ |:¢zb>@Uß© Ãão Ö@ãÐBã_öBOBÄÐhCÜb~Ö>îü rýåüUzuãrbzß/ªîUÐð©uå.ß@£__vBb©/Ür¢Öuåz£ä*å£/*ÃO');SET IDENTITY_INSERT [$tableName] OFF;");
$stmt1 = SelectFromTable($conn1, $tableName);
$rowCount = RowCount($stmt1);
sqlsrv_free_stmt($stmt1);
if ($rowCount != 2)
{
die("Table $tableName has $rowCount rows instead of 2.");
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function Execute($conn, $expectedOutcome, $query)
{
Trace("Executing query ".ltrim(substr($query, 0, 40))." ... ");
$stmt = ExecuteQueryEx($conn, $query, true);
if ($stmt === false)
{
Trace("failed.\n");
$actualOutcome = false;
}
else
{
Trace("succeeded.\n");
sqlsrv_free_stmt($stmt);
$actualOutcome = true;
}
if ($actualOutcome != $expectedOutcome)
{
die("Unexpected query execution outcome.");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ComplexQuery();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Statement - Complex Query" completed successfully.

View file

@ -0,0 +1,122 @@
--TEST--
Prepare and Execute Test
--DESCRIPTION--
Checks the data returned by a query first prepared and then executed multiple times.
Validates that a prepared statement can be successfully executed more than once.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function PrepareAndExecute($noPasses)
{
include 'MsSetup.inc';
$testName = "Statement - Prepare and Execute";
StartTest($testName);
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
InsertRows($conn1, $tableName, 1);
$values = array();
$fieldlVal = "";
// Prepare reference values
Trace("Execute a direct SELECT query on $tableName ...");
$stmt1 = SelectFromTable($conn1, $tableName);
$numFields1 = sqlsrv_num_fields($stmt1);
sqlsrv_fetch($stmt1);
for ($i = 0; $i < $numFields1; $i++)
{
if (UseUTF8Data()){
$fieldVal = sqlsrv_get_field($stmt1, $i, SQLSRV_PHPTYPE_STRING('UTF-8'));
}
else{
$fieldVal = sqlsrv_get_field($stmt1, $i, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
}
if ($fieldVal === false)
{
FatalError("Failed to retrieve field $i");
}
$values[$i] = $fieldVal;
}
sqlsrv_free_stmt($stmt1);
Trace(" $numFields1 fields retrieved.\n");
// Prepare once and execute several times
Trace("Prepare a SELECT query on $tableName ...");
$stmt2 = PrepareQuery($conn1, "SELECT * FROM [$tableName]");
$numFields2 = sqlsrv_num_fields($stmt2);
Trace(" $numFields2 fields expected.\n");
if ($numFields2 != $numFields1)
{
SetUTF8Data(false);
die("Incorrect number of fields: $numFields2");
}
for ($j = 0; $j < $noPasses; $j++)
{
Trace("Executing the prepared query ...");
sqlsrv_execute($stmt2);
sqlsrv_fetch($stmt2);
for ($i = 0; $i < $numFields2; $i++)
{
if (UseUTF8Data()){
$fieldVal = sqlsrv_get_field($stmt2, $i, SQLSRV_PHPTYPE_STRING('UTF-8'));
}
else{
$fieldVal = sqlsrv_get_field($stmt2, $i, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
}
if ($fieldVal === false)
{
FatalError("Failed to retrieve field $i");
}
if ($values[$i] != $fieldVal)
{
SetUTF8Data(false);
die("Incorrect value for field $i at iteration $j");
}
}
Trace(" $numFields2 fields verified.\n");
}
sqlsrv_free_stmt($stmt2);
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
if (! IsWindows())
{
SetUTF8Data(true);
}
try
{
PrepareAndExecute(5);
}
catch (Exception $e)
{
echo $e->getMessage();
}
SetUTF8Data(false);
}
Repro();
?>
--EXPECT--
Test "Statement - Prepare and Execute" completed successfully.

View file

@ -0,0 +1,71 @@
--TEST--
Statement Cancel Test
--DESCRIPTION--
Verifies that “sqlsrv_cancel” discards any pending data in current result set
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Cancel()
{
include 'MsSetup.inc';
$testName = "Statement - Cancel";
StartTest($testName);
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
InsertRows($conn1, $tableName, 5);
Trace("Executing SELECT query on $tableName ...");
$stmt1 = SelectFromTable($conn1, $tableName);
if (sqlsrv_fetch($stmt1) === false)
{
FatalError("Failed to retrieve data from test table");
}
Trace(" data fetched successfully.\n");
Trace("Cancel statement and attempt another fetch (expected to fail) ...\n");
sqlsrv_cancel($stmt1);
if (sqlsrv_fetch($stmt1) === false)
{
handle_errors();
}
else
{
die("No succesfull data fetch expectd after statement cancel");
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Cancel();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Statement - Cancel" completed successfully.

View file

@ -0,0 +1,81 @@
--TEST--
Statement Close Test
--DESCRIPTION--
Verifies that a statement can be closed more than once without
triggering an error condition.
Validates that a closed statement cannot be reused.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Close()
{
include 'MsSetup.inc';
$testName = "Statement - Close";
StartTest($testName);
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
Trace("Executing SELECT query on $tableName ...");
$stmt1 = SelectFromTable($conn1, $tableName);
Trace(" successfull.\n");
sqlsrv_free_stmt($stmt1);
Trace("Attempting to retrieve the number of fields after statement was closed ...\n");
if (sqlsrv_num_fields($stmt1) === false)
{
handle_errors();
}
else
{
die("A closed statement cannot be reused.");
}
Trace("\nClosing the statement again (no error expected) ...\n");
if (sqlsrv_free_stmt($stmt1) === false)
{
FatalError("A statement can be closed multiple times.");
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Close();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTREGEX--
Warning: sqlsrv_num_fields\(\): supplied resource is not a valid ss_sqlsrv_stmt resource in .*TC36_Close.php on line 21
Warning: sqlsrv_free_stmt\(\): supplied resource is not a valid ss_sqlsrv_stmt resource in .*TC36_Close.php on line 32
Test "Statement - Close" completed successfully.

View file

@ -0,0 +1,89 @@
--TEST--
Query Timeout Test
--DESCRIPTION--
Verifies the functionality of QueryTimeout option for both “sqlsrv_query”
and “sqlsrv_prepare”.
Executes a batch query that is expected to time out because it includes
a request to delay the server execution (via WAITFOR DELAY) for a duration
longer than the query timeout.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function QueryTimeout()
{
include 'MsSetup.inc';
$testName = "Statement - Query Timeout";
StartTest($testName);
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
Trace("Executing batch queries requiring 3 seconds with 1 second timeout.\n");
$query = "WAITFOR DELAY '00:00:03'; SELECT * FROM [$tableName]";
$option = array('QueryTimeout' => 1);
// Test timeout with sqlsrv_query()
Trace("\tDirect execution ...");
$stmt1 = sqlsrv_query($conn1, $query, null, $option);
if ($stmt1 === false)
{
Trace(" query timed out (as expected).\n");
}
else
{
die("Query was expected to time out");
}
// Test timeout with sqlsrv_prepare()/sqlsrv_execute()
Trace("\tPrepared execution ...");
$stmt2 = sqlsrv_prepare($conn1, $query, null, $option);
if ($stmt2 === false)
{
FatalError("Query preparation failed: $query");
}
$execOutcome = sqlsrv_execute($stmt2);
if ($execOutcome === false)
{
Trace(" query timed out (as expected).\n");
}
else
{
die("Query execution was expected to time out");
}
sqlsrv_free_stmt($stmt2);
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
QueryTimeout();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Statement - Query Timeout" completed successfully.

View file

@ -0,0 +1,84 @@
--TEST--
Invalid Query Test
--DESCRIPTION--
Verifies of "sqlsrv_query" response to invalid query attempts
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function InvalidQuery()
{
include 'MsSetup.inc';
$testName = "Statement - Invalid Query";
StartTest($testName);
Setup();
$conn1 = Connect();
// Invalid Query
$stmt1 = sqlsrv_query($conn1, "INVALID QUERY");
if ($stmt1)
{
die("Invalid query should have failed.");
}
$dataType = "[c1] int, [c2] int";
CreateTableEx($conn1, $tableName, $dataType);
// Invalid PHPTYPE parameter
$stmt2 = sqlsrv_query($conn1, "INSERT INTO [$tableName] (c1, c2) VALUES (?, ?)",
array(1, array(2, SQLSRV_PARAM_IN, 'SQLSRV_PHPTYPE_UNKNOWN')));
if ($stmt2)
{
die("Insert query with invalid parameter should have failed.");
}
// Invalid option
$stmt3 = sqlsrv_query($conn1, "INSERT INTO [$tableName] (c1, c2) VALUES (?, ?)", array(1, 2),
array('doSomething' => 1));
if ($stmt3)
{
die("Insert query with invalid option should have failed.");
}
// Invalid select
DropTable($conn1, $tableName);
$stmt4 = sqlsrv_query($conn1, "SELECT * FROM [$tableName]");
if ($stmt4)
{
die("Select query should have failed.");
}
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
InvalidQuery();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Statement - Invalid Query" completed successfully.

View file

@ -0,0 +1,124 @@
--TEST--
Cursor Mode Test
--DESCRIPTION--
Verifies the functionality associated with scrollable resultsets.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function CursorTest($noRows1, $noRows2)
{
include 'MsSetup.inc';
$testName = "Statement - Cursor Mode";
StartTest($testName);
Setup();
$conn1 = Connect();
$cursor = "";
for ($k = 0; $k < 4; $k++)
{
switch ($k)
{
case 0: $cursor = SQLSRV_CURSOR_FORWARD; break;
case 1: $cursor = SQLSRV_CURSOR_STATIC; break;
case 2: $cursor = SQLSRV_CURSOR_DYNAMIC; break;
case 3: $cursor = SQLSRV_CURSOR_KEYSET; break;
default: break;
}
ScrollableFetch($conn1, $tableName, $noRows1, $noRows2, $cursor);
}
sqlsrv_close($conn1);
EndTest($testName);
}
function ScrollableFetch($conn, $tableName, $noRows1, $noRows2, $cursor)
{
$colIndex = "c27_timestamp";
CreateTable($conn, $tableName);
CreateUniqueIndex($conn, $tableName, $colIndex);
$stmt1 = SelectFromTable($conn, $tableName);
if (sqlsrv_has_rows($stmt1))
{
die("Table $tableName is expected to be empty...");
}
sqlsrv_free_stmt($stmt1);
$noRows = InsertRows($conn, $tableName, $noRows1);
$query = "SELECT * FROM [$tableName] ORDER BY $colIndex";
$options = array('Scrollable' => $cursor);
$stmt2 = SelectQueryEx($conn, $query, $options);
if (!sqlsrv_has_rows($stmt2))
{
die("Table $tableName is not expected to be empty...");
}
if (($cursor == SQLSRV_CURSOR_STATIC) ||
($cursor == SQLSRV_CURSOR_KEYSET))
{
$numRows = sqlsrv_num_rows($stmt2);
if ($numRows != $noRows)
{
die("Unexpected row count for $cursor: $numRows instead of $noRows\n");
}
}
while (($noRows > 0) && sqlsrv_fetch($stmt2))
{
// consume the result set
$noRows--;
}
if ($noRows2 > 0)
{
$extraRows = InsertRows($conn, $tableName, $noRows2);
if ($cursor == SQLSRV_CURSOR_DYNAMIC)
{
$noRows += $extraRows;
}
}
while (sqlsrv_fetch($stmt2))
{
// consume the result set
$noRows--;
}
sqlsrv_free_stmt($stmt2);
if ($noRows != 0)
{
die("Unexpected row count for $cursor: $noRows\n");
}
DropTable($conn, $tableName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
CursorTest(10, 5);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Statement - Cursor Mode" completed successfully.

View file

@ -0,0 +1,93 @@
--TEST--
Fetch Metadata Test
--DESCRIPTION--
Verifies that "sqlsrv_field_metadata returns" the same number of fields
as "sqlsrv_num_fields".
Verifies the metadata array (NAME, TYPE, SIZE, PRECISION, SCALE and NULLABLE)
for all SQL types currently supported (28 types).
Validates functionality with statement in both prepared and executed state.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchMetadata()
{
include 'MsSetup.inc';
$testName = "Fetch - Metadata";
StartTest($testName);
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
InsertRow($conn1, $tableName);
$stmt1 = SelectFromTable($conn1, $tableName);
$numFields = sqlsrv_num_fields($stmt1);
Trace("Expecting $numFields fields...\n");
$metadata = sqlsrv_field_metadata($stmt1);
$count = count($metadata);
if ($count != $numFields)
{
die("Unexpected metadata size: ".$count);
}
for ($k = 0; $k < $count; $k++)
{
Trace(" ".($k + 1)."\t");
ShowMetadata($metadata, $k, 'Name');
ShowMetadata($metadata, $k, 'Size');
ShowMetadata($metadata, $k, 'Precision');
ShowMetadata($metadata, $k, 'Scale');
ShowMetadata($metadata, $k, 'Nullable');
Trace("\n");
}
sqlsrv_free_stmt($stmt1);
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function ShowMetadata($mdArray, $field, $info)
{
$mdInfo = $mdArray[$field][$info];
$refInfo = GetMetadata($field + 1, $info);
Trace("[$info=$mdInfo]");
if ($mdInfo != $refInfo)
{
die ("Unexpected metadata value for $info in field ".($field + 1).": $mdInfo instead of $refInfo");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchMetadata();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Fetch - Metadata" completed successfully.

View file

@ -0,0 +1,83 @@
--TEST--
Fetch Field Test
--DESCRIPTION--
Verifies the ability to successfully retrieve field data via "sqlsrv_get_field" by
retrieving fields from a table including rows with all supported SQL types (28 types).
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchFields()
{
include 'MsSetup.inc';
$testName = "Fetch - Field";
StartTest($testName);
Setup();
if (! IsWindows())
$conn1 = ConnectUTF8();
else
$conn1 = Connect();
CreateTable($conn1, $tableName);
$noRows = 10;
$noRowsInserted = InsertRows($conn1, $tableName, $noRows);
$stmt1 = SelectFromTable($conn1, $tableName);
$numFields = sqlsrv_num_fields($stmt1);
Trace("Retrieving $noRowsInserted rows with $numFields fields each ...");
for ($i = 0; $i < $noRowsInserted; $i++)
{
$row = sqlsrv_fetch($stmt1);
if ($row === false)
{
FatalError("Row $i is missing");
}
for ($j = 0; $j < $numFields; $j++)
{
$fld = sqlsrv_get_field($stmt1, $j);
if ($fld === false)
{
FatalError("Field $j of Row $i is missing\n");
}
}
}
sqlsrv_free_stmt($stmt1);
Trace(" completed successfully.\n");
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchFields();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Fetch - Field" completed successfully.

View file

@ -0,0 +1,137 @@
--TEST--
Fetch Field Data Test verifies the data retrieved via "sqlsrv_get_field"
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchFields()
{
include 'MsSetup.inc';
$testName = "Fetch - Field Data";
StartTest($testName);
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
$startRow = 1;
$noRows = 20;
InsertRowsByRange($conn1, $tableName, $startRow, $startRow + $noRows - 1);
$query = "SELECT * FROM [$tableName] ORDER BY c27_timestamp";
$stmt1 = SelectQuery($conn1, $query);
$numFields = sqlsrv_num_fields($stmt1);
Trace("Retrieving $noRows rows with $numFields fields each ...");
for ($i = 0; $i < $noRows; $i++)
{
$row = sqlsrv_fetch($stmt1);
if ($row === false)
{
FatalError("Row $i is missing");
}
$skipCount = 0;
for ($j = 0; $j < $numFields; $j++)
{
if (UseUTF8Data()){
$fld = sqlsrv_get_field($stmt1, $j, SQLSRV_PHPTYPE_STRING('UTF-8'));
}
else{
$fld = sqlsrv_get_field($stmt1, $j, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
}
if ($fld === false)
{
FatalError("Field $j of Row $i is missing");
}
$col = $j + 1;
if (!IsUpdatable($col))
{
$skipCount++;
}
else // should check data even if $fld is null
{
$data = GetInsertData($startRow + $i, $col, $skipCount);
if (!CheckData($col, $fld, $data))
{
SetUTF8Data(false);
die("Data corruption on row ".($startRow + $i)." column $col");
}
}
}
}
sqlsrv_free_stmt($stmt1);
Trace(" completed successfully.\n");
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function CheckData($col, $actual, $expected)
{
$success = true;
if (IsNumeric($col))
{
if (floatval($actual) != floatval($expected))
{
$success = false;
}
}
else
{
$actual = trim($actual);
$len = strlen($expected);
if (IsDateTime($col))
{
$len = min(strlen("YYYY-MM-DD HH:mm:ss"), $len);
}
if (strncasecmp($actual, $expected, $len) != 0)
{
$success = false;
}
}
if (!$success)
{
Trace("\nData error\nExpected:\n$expected\nActual:\n$actual\n");
}
return ($success);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
if (! IsWindows())
{
SetUTF8Data(true);
}
try
{
FetchFields();
}
catch (Exception $e)
{
echo $e->getMessage();
}
SetUTF8Data(false);
}
Repro();
?>
--EXPECT--
Test "Fetch - Field Data" completed successfully.

View file

@ -0,0 +1,217 @@
--TEST--
Fetch Array Test
--DESCRIPTION--
Verifies data retrieval via “sqlsrv_fetch_array”,
by checking all fetch type modes.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchRow($minFetchMode, $maxFetchMode)
{
include 'MsSetup.inc';
$testName = "Fetch - Array";
StartTest($testName);
if (!IsMarsSupported())
{
EndTest($testName);
return;
}
Setup();
if (! IsWindows())
$conn1 = ConnectUTF8();
else
$conn1 = Connect();
CreateTable($conn1, $tableName);
$noRows = 10;
$numFields = 0;
InsertRows($conn1, $tableName, $noRows);
for ($k = $minFetchMode; $k <= $maxFetchMode; $k++)
{
$stmt1 = SelectFromTable($conn1, $tableName);
$stmt2 = SelectFromTable($conn1, $tableName);
if ($numFields == 0)
{
$numFields = sqlsrv_num_fields($stmt1);
}
else
{
$count = sqlsrv_num_fields($stmt1);
if ($count != $numFields)
{
SetUTF8Data(false);
die("Unexpected number of fields: $count");
}
}
switch ($k)
{
case 1: // fetch array - numeric mode
FetchArray($stmt1, $stmt2, SQLSRV_FETCH_NUMERIC, $noRows, $numFields);
break;
case 2: // fetch array - associative mode
FetchArray($stmt1, $stmt2, SQLSRV_FETCH_ASSOC, $noRows, $numFields);
break;
case 3: // fetch array - both numeric & associative
FetchArray($stmt1, $stmt2, SQLSRV_FETCH_BOTH, $noRows, $numFields);
break;
default: // default
FetchArray($stmt1, $stmt2, null, $noRows, $numFields);
break;
}
sqlsrv_free_stmt($stmt1);
sqlsrv_free_stmt($stmt2);
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function FetchArray($stmt, $stmtRef, $mode, $rows, $fields)
{
$size = $fields;
$fetchMode = $mode;
if ($fetchMode == SQLSRV_FETCH_NUMERIC)
{
Trace("\tRetrieving $rows arrays of size $size (Fetch Mode = NUMERIC) ...\n");
}
else if ($fetchMode == SQLSRV_FETCH_ASSOC)
{
Trace("\tRetrieving $rows arrays of size $size (Fetch Mode = ASSOCIATIVE) ...\n");
}
else if ($fetchMode == SQLSRV_FETCH_BOTH)
{
$size = $fields * 2;
Trace("\tRetrieving $rows arrays of size $size (Fetch Mode = BOTH) ...\n");
}
else
{
$fetchMode = null;
$size = $fields * 2;
Trace("\tRetrieving $rows arrays of size $size (Fetch Mode = DEFAULT) ...\n");
}
for ($i = 0; $i < $rows; $i++)
{
if ($fetchMode == null)
{
$row = sqlsrv_fetch_array($stmt);
}
else
{
$row = sqlsrv_fetch_array($stmt, $fetchMode);
}
if ($row === false)
{
FatalError("Row $i is missing");
}
$rowSize = count($row);
if ($rowSize != $size)
{
SetUTF8Data(false);
die("Row array has an incorrect size: ".$rowSize);
}
$rowRref = sqlsrv_fetch($stmtRef);
for ($j = 0; $j < $fields; $j++)
{
if (!CheckData($row, $stmtRef, $j, $fetchMode))
{
SetUTF8Data(false);
die("Data corruption on row ".($i + 1)." column ".($j + 1));
}
}
}
}
function CheckData($row, $stmt, $index, $mode)
{
$success = true;
$col = $index + 1;
$actual = (($mode == SQLSRV_FETCH_ASSOC) ? $row[GetColName($col)] : $row[$index]);
$expected = null;
if (!IsUpdatable($col))
{
// do not check the timestamp
}
else if (IsNumeric($col) || IsDateTime($col))
{
$expected = sqlsrv_get_field($stmt, $index);
if ($expected != $actual)
{
$success = false;
}
}
else if (IsBinary($col))
{
$expected = sqlsrv_get_field($stmt, $index, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
$actual = bin2hex($actual);
if (strcasecmp($actual, $expected) != 0)
{
$success = false;
}
}
else // if (IsChar($col))
{
if (UseUTF8Data()){
$expected = sqlsrv_get_field($stmt, $index, SQLSRV_PHPTYPE_STRING('UTF-8'));
}
else{
$expected = sqlsrv_get_field($stmt, $index, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
}
if (strcmp($actual, $expected) != 0)
{
$success = false;
}
}
if (!$success)
{
Trace("\nData error\nExpected:\n$expected\nActual:\n$actual\n");
}
return ($success);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
if (! IsWindows())
{
SetUTF8Data(true);
}
try
{
FetchRow(1, 4);
}
catch (Exception $e)
{
echo $e->getMessage();
}
SetUTF8Data(false);
}
Repro();
?>
--EXPECT--
Test "Fetch - Array" completed successfully.

View file

@ -0,0 +1,168 @@
--TEST--
Fetch Object Test
--DESCRIPTION--
Verifies data retrieval via “sqlsrv_fetch_object”.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
class TestClass
{
function __construct($a1, $a2, $a3)
{
}
}
function FetchRow($minFetchMode, $maxFetchMode)
{
include 'MsSetup.inc';
$testName = "Fetch - Object";
StartTest($testName);
Setup();
if (! IsWindows())
$conn1 = ConnectUTF8();
else
$conn1 = Connect();
CreateTable($conn1, $tableName);
$noRows = 10;
$noRowsInserted = InsertRows($conn1, $tableName, $noRows);
$actual = null;
$expected = null;
$numFields = 0;
for ($k = $minFetchMode; $k <= $maxFetchMode; $k++)
{
$stmt1 = SelectFromTable($conn1, $tableName);
if ($numFields == 0)
{
$numFields = sqlsrv_num_fields($stmt1);
}
else
{
$count = sqlsrv_num_fields($stmt1);
if ($count != $numFields)
{
die("Unexpected number of fields: $count");
}
}
switch ($k)
{
case 0: // fetch array (to retrieve reference values)
$expected = FetchArray($stmt1, $noRowsInserted, $numFields);
break;
case 1: // fetch object (without class)
$actual = FetchObject($stmt1, $noRowsInserted, $numFields, false);
CheckData($noRowsInserted, $numFields, $actual, $expected);
break;
case 2: // fetch object (with class)
$actual = FetchObject($stmt1, $noRowsInserted, $numFields, true);
CheckData($noRowsInserted, $numFields, $actual, $expected);
break;
default: // default
break;
}
sqlsrv_free_stmt($stmt1);
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function FetchObject($stmt, $rows, $fields, $useClass)
{
Trace("\tRetrieving $rows objects with $fields fields each ...\n");
$values = array();
for ($i = 0; $i < $rows; $i++)
{
if ($useClass)
{
$obj = sqlsrv_fetch_object($stmt, "TestClass", array(1, 2, 3));
}
else
{
$obj = sqlsrv_fetch_object($stmt);
}
if ($obj === false)
{
FatalError("Row $i is missing");
}
$values[$i] = $obj;
}
return ($values);
}
function FetchArray($stmt, $rows, $fields)
{
$values = array();
for ($i = 0; $i < $rows; $i++)
{
$row = sqlsrv_fetch_array($stmt);
if ($row === false)
{
FatalError("Row $i is missing");
}
$values[$i] = $row;
}
return ($values);
}
function CheckData($rows, $fields, $actualValues, $expectedValues)
{
if (($actualValues != null) && ($expectedValues != null))
{
for ($i = 0; $i < $rows; $i++)
{
for ($j = 0; $j < $fields; $j++)
{
$colName = GetColName($j + 1);
$actual = $actualValues[$i]->$colName;
$expected = $expectedValues[$i][$colName];
if ($actual != $expected)
{
die("Data corruption on row ".($i + 1)." column ".($j + 1).": $expected => $actual");
}
}
}
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchRow(0, 2);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Fetch - Object" completed successfully.

View file

@ -0,0 +1,122 @@
--TEST--
Fetch Next Result Test
--DESCRIPTION--
Verifies the functionality of “sqlsvr_next_result”
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchFields()
{
include 'MsSetup.inc';
$testName = "Fetch - Next Result";
StartTest($testName);
if (!IsMarsSupported())
{
EndTest($testName);
return;
}
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
$noRows = 10;
InsertRows($conn1, $tableName, $noRows);
$stmt1 = SelectQuery($conn1, "SELECT * FROM [$tableName]");
$stmt2 = SelectQuery($conn1, "SELECT * FROM [$tableName]; SELECT * FROM [$tableName]");
if (sqlsrv_next_result($stmt2) === false)
{
FatalError("Failed to retrieve next result set");
}
$numFields1 = sqlsrv_num_fields($stmt1);
$numFields2 = sqlsrv_num_fields($stmt2);
if ($numFields1 != $numFields2)
{
SetUTF8Data(false);
die("Unexpected number of fields: $numField1 => $numFields2");
}
Trace("Retrieving $noRows rows with $numFields1 fields each ...");
for ($i = 0; $i < $noRows; $i++)
{
$row1 = sqlsrv_fetch($stmt1);
$row2 = sqlsrv_fetch($stmt2);
if (($row1 === false) || ($row2 === false))
{
FatalError("Row $i is missing");
}
for ($j = 0; $j < $numFields1; $j++)
{
if (UseUTF8Data()){
$fld1 = sqlsrv_get_field($stmt1, $j, SQLSRV_PHPTYPE_STRING('UTF-8'));
$fld2 = sqlsrv_get_field($stmt2, $j, SQLSRV_PHPTYPE_STRING('UTF-8'));
}
else {
$fld1 = sqlsrv_get_field($stmt1, $j, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
$fld2 = sqlsrv_get_field($stmt2, $j, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
}
if (($fld1 === false) || ($fld2 === false))
{
FatalError("Field $j of Row $i is missing");
}
if ($fld1 != $fld2)
{
SetUTF8Data(false);
die("Data corruption on row ".($i + 1)." column ".($j + 1)." $fld1 => $fld2");
}
}
}
if (sqlsrv_next_result($stmt1) ||
sqlsrv_next_result($stmt2))
{
SetUTF8Data(false);
die("No more results were expected");
}
sqlsrv_free_stmt($stmt1);
sqlsrv_free_stmt($stmt2);
Trace(" completed successfully.\n");
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
if (! IsWindows())
{
SetUTF8Data(true);
}
try
{
FetchFields();
}
catch (Exception $e)
{
echo $e->getMessage();
}
SetUTF8Data(false);
}
Repro();
?>
--EXPECT--
Test "Fetch - Next Result" completed successfully.

View file

@ -0,0 +1,94 @@
--TEST--
Parameterized Query Test
--DESCRIPTION--
Verifies that ability to execute a parameterized INSERT query.
The query behavior is checked for all updateable data types.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ParamQuery($minType, $maxType)
{
include 'MsSetup.inc';
$testName = "Parameterized Query";
StartTest($testName);
Setup();
$conn1 = Connect();
for ($k = $minType; $k <= $maxType; $k++)
{
$data = GetSampleData($k);
if ($data != null)
{
$sqlType = GetSqlType($k);
$phpDriverType = GetDriverType($k, strlen($data));
$dataType = "[c1] int, [c2] $sqlType";
$dataOptions = array($k, array($data, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), $phpDriverType));
TraceData($sqlType, $data);
CreateQueryTable($conn1, $tableName, $dataType, "c1, c2", "?, ?", $dataOptions);
CheckData($conn1, $tableName, 2, $data);
DropTable($conn1, $tableName);
}
}
sqlsrv_close($conn1);
EndTest($testName);
}
function CreateQueryTable($conn, $table, $dataType, $dataCols, $dataValues, $dataOptions)
{
CreateTableEx($conn, $table, $dataType);
InsertRowEx($conn, $table, $dataCols, $dataValues, $dataOptions);
}
function CheckData($conn, $table, $cols, $expectedValue)
{
$stmt = SelectFromTable($conn, $table);
if (!sqlsrv_fetch($stmt))
{
die("Table $tableName was not expected to be empty.");
}
$numFields = sqlsrv_num_fields($stmt);
if ($numFields != $cols)
{
die("Table $tableName was expected to have $cols fields.");
}
$actualValue = sqlsrv_get_field($stmt, 1, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
sqlsrv_free_stmt($stmt);
if (strncmp($actualValue, $expectedValue, strlen($expectedValue)) != 0)
{
die("Data corruption: $expectedValue => $actualValue.");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ParamQuery(1, 28);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Parameterized Query" completed successfully.

View file

@ -0,0 +1,178 @@
--TEST--
Fetch Scrollabale Data Test
--DESCRIPTION--
Verifies data retrieval with scrollable result sets.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function FetchRow($noRows)
{
include 'MsSetup.inc';
$testName = "Fetch - Scrollable";
StartTest($testName);
Setup();
if (! IsWindows())
$conn1 = ConnectUTF8();
else
$conn1 = Connect();
CreateTable($conn1, $tableName);
$noRowsInserted = InsertRows($conn1, $tableName, $noRows);
$actual = null;
$expected = null;
// fetch array (to retrieve reference values)
$stmt1 = SelectFromTable($conn1, $tableName);
$numFields = sqlsrv_num_fields($stmt1);
$expected = FetchArray($stmt1, $noRowsInserted, $numFields);
sqlsrv_free_stmt($stmt1);
$query = "SELECT * FROM [$tableName]";
// fetch object - FORWARD cursor
$options = array('Scrollable' => SQLSRV_CURSOR_FORWARD);
$stmt2 = SelectQueryEx($conn1, $query, $options);
$actual = FetchObject($stmt2, $noRowsInserted, $numFields, SQLSRV_SCROLL_NEXT);
sqlsrv_free_stmt($stmt2);
CheckData($noRowsInserted, $numFields, $actual, $expected);
// fetch object - STATIC cursor
$options = array('Scrollable' => SQLSRV_CURSOR_STATIC);
$stmt2 = SelectQueryEx($conn1, $query, $options);
$actual = FetchObject($stmt2, $noRowsInserted, $numFields, SQLSRV_SCROLL_RELATIVE);
sqlsrv_free_stmt($stmt2);
CheckData($noRowsInserted, $numFields, $actual, $expected);
// fetch object - DYNAMIC cursor
$options = array('Scrollable' => SQLSRV_CURSOR_DYNAMIC);
$stmt2 = SelectQueryEx($conn1, $query, $options);
$actual = FetchObject($stmt2, $noRowsInserted, $numFields, SQLSRV_SCROLL_ABSOLUTE);
sqlsrv_free_stmt($stmt2);
CheckData($noRowsInserted, $numFields, $actual, $expected);
// fetch object - KEYSET cursor
$options = array('Scrollable' => SQLSRV_CURSOR_KEYSET);
$stmt2 = SelectQueryEx($conn1, $query, $options);
$actual = FetchObject($stmt2, $noRowsInserted, $numFields, SQLSRV_SCROLL_PRIOR, 0);
sqlsrv_free_stmt($stmt2);
CheckData($noRowsInserted, $numFields, $actual, $expected);
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function FetchArray($stmt, $rows, $fields)
{
$values = array();
for ($i = 0; $i < $rows; $i++)
{
$row = sqlsrv_fetch_array($stmt);
if ($row === false)
{
FatalError("Row $i is missing");
}
$values[$i] = $row;
}
return ($values);
}
function FetchObject($stmt, $rows, $fields, $dir)
{
Trace("\tRetrieving $rows objects with $fields fields each ...\n");
$values = array();
for ($i = 0; $i < $rows; $i++)
{
if ($dir == SQLSRV_SCROLL_NEXT)
{
$obj = sqlsrv_fetch_object($stmt, null, null, $dir);
}
else if ($dir == SQLSRV_SCROLL_PRIOR)
{
if ($i == 0)
{
$obj = sqlsrv_fetch_object($stmt, null, null, SQLSRV_SCROLL_LAST);
}
else
{
$obj = sqlsrv_fetch_object($stmt, null, null, $dir);
}
}
else if ($dir == SQLSRV_SCROLL_ABSOLUTE)
{
$obj = sqlsrv_fetch_object($stmt, null, null, $dir, $i);
}
else if ($dir == SQLSRV_SCROLL_RELATIVE)
{
$obj = sqlsrv_fetch_object($stmt, null, null, $dir, 1);
}
if ($obj === false)
{
FatalError("Row $i is missing");
}
if ($dir == SQLSRV_SCROLL_PRIOR)
{
$values[$rows - $i - 1] = $obj;
}
else
{
$values[$i] = $obj;
}
}
return ($values);
}
function CheckData($rows, $fields, $actualValues, $expectedValues)
{
if (($actualValues != null) && ($expectedValues != null))
{
for ($i = 0; $i < $rows; $i++)
{
for ($j = 0; $j < $fields; $j++)
{
$colName = GetColName($j + 1);
$actual = $actualValues[$i]->$colName;
$expected = $expectedValues[$i][$colName];
if ($actual != $expected)
{
die("Data corruption on row ".($i + 1)." column ".($j + 1).": $expected => $actual");
}
}
}
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
FetchRow(10);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Fetch - Scrollable" completed successfully.

View file

@ -0,0 +1,175 @@
--TEST--
Stream Read Test
--DESCRIPTION--
Verifies that all SQL types defined as capable of streaming (13 types)
can be successfully retrieved as streams.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function StreamRead($noRows, $startRow)
{
include 'MsSetup.inc';
$testName = "Stream - Read";
StartTest($testName);
Setup();
if (! IsWindows())
$conn1 = ConnectUTF8();
else
$conn1 = Connect();
CreateTable($conn1, $tableName);
InsertRowsByRange($conn1, $tableName, $startRow, $startRow + $noRows - 1);
$query = "SELECT * FROM [$tableName] ORDER BY c27_timestamp";
$stmt1 = SelectQuery($conn1, $query);
$numFields = sqlsrv_num_fields($stmt1);
for ($row = 1; $row <= $noRows; $row++)
{
if (!sqlsrv_fetch($stmt1))
{
FatalError("Failed to fetch row ".$row);
}
Trace("\nStreaming row $row:\n");
$skipCount = 0;
for ($j = 0; $j < $numFields; $j++)
{
$col = $j + 1;
if (!IsUpdatable($col))
{
$skipCount++;
}
if (IsStreamable($col))
{
VerifyStream($stmt1, $startRow + $row - 1, $j, $skipCount);
}
}
}
sqlsrv_free_stmt($stmt1);
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function VerifyStream($stmt, $row, $colIndex, $skip)
{
$col = $colIndex + 1;
if (IsStreamable($col))
{
$type = GetSqlType($col);
if (IsBinary($col))
{
$stream = sqlsrv_get_field($stmt, $colIndex, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
}
else
{
if (UseUTF8Data()){
$stream = sqlsrv_get_field($stmt, $colIndex, SQLSRV_PHPTYPE_STREAM('UTF-8'));
}
else{
$stream = sqlsrv_get_field($stmt, $colIndex, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_CHAR));
}
}
if ($stream === false)
{
FatalError("Failed to read field $col: $type");
}
else
{
$value = '';
if ($stream)
{
while (!feof($stream))
{
$value .= fread($stream, 8192);
}
fclose($stream);
$data = GetInsertData($row, $col, $skip);
if (!CheckData($col, $value, $data))
{
SetUTF8Data(false);
Trace("Data corruption on row $row column $col\n");
die("Data corruption on row $row column $col\n");
}
}
TraceData($type, "".strlen($value)." bytes");
}
}
}
function CheckData($col, $actual, $expected)
{
$success = true;
if (IsBinary($col))
{
$actual = bin2hex($actual);
if (strncasecmp($actual, $expected, strlen($expected)) != 0)
{
$success = false;
}
}
else
{
if (strncasecmp($actual, $expected, strlen($expected)) != 0)
{
if ($col != 19)
{ // skip ntext
$pos = strpos($actual, $expected);
if (($pos === false) || ($pos > 1))
{
$success = false;
}
}
}
}
if (!$success)
{
Trace("\nData error\nExpected:\n$expected\nActual:\n$actual\n");
}
return ($success);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
if (! IsWindows())
{
SetUTF8Data(true);
}
try
{
StreamRead(20, 1);
}
catch (Exception $e)
{
echo $e->getMessage();
}
SetUTF8Data(false);
}
Repro();
?>
--EXPECT--
Test "Stream - Read" completed successfully.

View file

@ -0,0 +1,177 @@
--TEST--
Stream Send Test
--DESCRIPTION--
Verifies that all SQL types defined as capable of streaming (13 types)
can be successfully uploaded as streams.
Verifies that streams can be sent either directly at execution or
via sqlsrv_send_stream_data (i.e. after execution).
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function SendStream($minType, $maxType, $atExec)
{
include 'MsSetup.inc';
$testName = "Stream - ".($atExec ? "Send at Execution" : "Send after Execution");
StartTest($testName);
Setup();
$conn1 = Connect();
for ($k = $minType; $k <= $maxType; $k++)
{
switch ($k)
{
case 1: // int
case 2: // tinyint
case 3: // smallint
case 4: // bigint
case 5: // bit
case 6: // float
case 7: // real
case 8: // decimal
case 9: // numeric
case 10:// money
case 11:// smallmoney
case 27:// timestamp
$data = null;
break;
case 12:// char
case 15:// nchar
$data = "The quick brown fox jumps over the lazy dog";
break;
case 13:// varchar
case 16:// nvarchar
$data = "The quick brown fox jumps over the lazy dog 9876543210";
break;
case 14:// varchar(max)
case 17:// nvarchar(max)
$data = "The quick brown fox jumps over the lazy dog 0123456789";
break;
case 18:// text
case 19:// ntext
$data = "0123456789 The quick brown fox jumps over the lazy dog";
break;
case 20:// binary
$data = "0123456789";
break;
case 21:// varbinary
$data = "01234567899876543210";
break;
case 22:// varbinary(max)
$data = "98765432100123456789";
break;
case 23:// image
$data = "01234567899876543210";
$phpType = SQLSRV_SQLTYPE_IMAGE;
break;
case 24:// uniqueidentifier
$data = "12345678-9012-3456-7890-123456789012";
break;
case 25:// datetime
case 26:// smalldatetime
$data = date("Y-m-d");
break;
case 28:// xml
$data = "<XmlTestData><Letters1>The quick brown fox jumps over the lazy dog</Letters1><Digits1>0123456789</Digits1></XmlTestData>";
break;
default:
die("Unknown data type: $k.");
break;
}
if ($data != null)
{
$fname1 = fopen($fileName, "w");
fwrite($fname1, $data);
fclose($fname1);
$fname2 = fopen($fileName, "r");
$sqlType = GetSqlType($k);
$phpDriverType = GetDriverType($k, strlen($data));
$dataType = "[c1] int, [c2] $sqlType";
$dataOptions = array($k, array($fname2, SQLSRV_PARAM_IN, null, $phpDriverType));
TraceData($sqlType, $data);
CreateQueryTable($conn1, $tableName, $dataType, "c1, c2", "?, ?", $dataOptions, $atExec);
CheckData($conn1, $tableName, 2, $data);
fclose($fname2);
}
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function CreateQueryTable($conn, $table, $dataType, $dataCols, $dataValues, $dataOptions, $execMode)
{
CreateTableEx($conn, $table, $dataType);
InsertStream($conn, $table, $dataCols, $dataValues, $dataOptions, $execMode);
}
function CheckData($conn, $table, $cols, $expectedValue)
{
$stmt = SelectFromTable($conn, $table);
if (!sqlsrv_fetch($stmt))
{
FatalError("Table $tableName was not expected to be empty.");
}
$numFields = sqlsrv_num_fields($stmt);
if ($numFields != $cols)
{
die("Table $tableName was expected to have $cols fields.");
}
$actualValue = sqlsrv_get_field($stmt, 1, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
sqlsrv_free_stmt($stmt);
if (strncmp($actualValue, $expectedValue, strlen($expectedValue)) != 0)
{
die("Data corruption: $expectedValue => $actualValue.");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
SendStream(12, 28, true); // send stream at execution
SendStream(12, 28, false); // send stream after execution
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Stream - Send at Execution" completed successfully.
Test "Stream - Send after Execution" completed successfully.

View file

@ -0,0 +1,128 @@
--TEST--
Stream Cancel Test
--DESCRIPTION--
Verifies that a stream is invalidated by:
- fetching next row
- cancelling or closing the statement
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function CancelStream()
{
include 'MsSetup.inc';
$testName = "Stream - Cancel";
StartTest($testName);
Setup();
$conn1 = Connect();
$noRows = 5;
CreateTable($conn1, $tableName);
InsertRows($conn1, $tableName, $noRows);
$stmt1 = SelectFromTable($conn1, $tableName);
// Expired stream
$stream1 = GetStream($stmt1);
sqlsrv_fetch($stmt1);
CheckStream($stream1);
// Cancelled statement
$stream2 = GetStream($stmt1);
sqlsrv_cancel($stmt1);
CheckStream($stream2);
// Closed statement
$stmt2 = SelectFromTable($conn1, $tableName);
$stream3 = GetStream($stmt2);
sqlsrv_free_stmt($stmt2);
CheckStream($stream3);
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function GetStream($stmt)
{
$stream = null;
if (!sqlsrv_fetch($stmt))
{
FatalError("Failed to fetch row ".$row);
}
while ($stream == null)
{
$col = rand(11, 22); // select a streamable field
if (!IsStreamable($col + 1))
{
die("Failed to select a streamable field.");
}
$type = GetSqlType($col + 1);
Trace("Selected streamable type: $type ...\n");
$stream = sqlsrv_get_field($stmt, $col, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
if ($stream === false)
{
FatalError("Failed to read field $col: $type");
}
}
return ($stream);
}
function CheckStream($stream)
{
$bytesRead = 0;
try
{
$value = fread($stream, 8192);
$bytesRread = strlen($value);
}
catch (Exception $e)
{
$bytesRead = 0;
Trace($e->getMessage());
}
if ($bytesRead > 0)
{
die("Invalid stream should not return any data.");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
CancelStream();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTREGEX--
|Warning: fread\(\): supplied argument is not a valid stream resource in .+\\TC53_StreamCancel.php on line 86|Warning: fread\(\): expects parameter 1 to be resource, null given in .+\\TC53_StreamCancel.php on line 86
|Warning: fread\(\): supplied argument is not a valid stream resource in .+\\TC53_StreamCancel.php on line 86|Warning: fread\(\): expects parameter 1 to be resource, null given in .+\\TC53_StreamCancel.php on line 86
|Warning: fread\(\): supplied argument is not a valid stream resource in .+\\TC53_StreamCancel.php on line 86|Warning: fread\(\): expects parameter 1 to be resource, null given in .+\\TC53_StreamCancel.php on line 86
Test "Stream - Cancel" completed successfully.

View file

@ -0,0 +1,149 @@
--TEST--
Stream Prepared Test
--DESCRIPTION--
Verifies that all SQL types defined as capable of streaming (13 types)
can be successfully uploaded as streams via sqlsrv_prepare/sqlsvr_query.
Validates that a warning message is issued when parameters are not passed by reference.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function SendStream($minType, $maxType)
{
include 'MsSetup.inc';
$testName = "Stream - Prepared Send";
StartTest($testName);
Setup();
$conn1 = Connect();
for ($k = $minType; $k <= $maxType; $k++)
{
switch ($k)
{
case 12: // char
case 13: // varchar
case 14: // varchar(max)
case 15: // nchar
case 16: // nvarchar
case 17: // nvarchar(max)
case 18: // text
case 19: // ntext
$data = "The quick brown fox jumps over the lazy dog 0123456789";
break;
case 20: // binary
case 21: // varbinary
case 22: // varbinary(max)
case 23: // image
$data = "01234567899876543210";
break;
default:
die("Unexpected data type: $k.");
break;
}
$fname1 = fopen($fileName, "w");
fwrite($fname1, $data);
fclose($fname1);
$fname2 = fopen($fileName, "r");
$sqlType = GetSqlType($k);
$phpDriverType = GetDriverType($k, strlen($data));
$dataType = "[c1] int, [c2] $sqlType";
$dataOptions = array(array($k, SQLSRV_PARAM_IN),
array(&$fname2, SQLSRV_PARAM_IN, null, $phpDriverType));
TraceData($sqlType, $data);
CreateTableEx($conn1, $tableName, $dataType);
InsertData($conn1, $tableName, "c1, c2", "?, ?", $dataOptions);
CheckData($conn1, $tableName, 2, $data);
fclose($fname2);
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function InsertData($conn, $tableName, $dataCols, $dataValues, $dataOptions)
{
$sql = "INSERT INTO [$tableName] ($dataCols) VALUES ($dataValues)";
$stmt = sqlsrv_prepare($conn, $sql, $dataOptions);
if ($stmt === false)
{
FatalError("Failed to prepare insert query: ".$sql);
}
$outcome = sqlsrv_execute($stmt);
if ($outcome === false)
{
FatalError("Failed to execute prepared query: ".$sql);
}
while (sqlsrv_send_stream_data($stmt))
{
}
$numRows = sqlsrv_rows_affected($stmt);
sqlsrv_free_stmt($stmt);
if ($numRows != 1)
{
die("Unexpected row count at insert: ".$numRows);
}
}
function CheckData($conn, $table, $cols, $expectedValue)
{
$stmt = SelectFromTable($conn, $table);
if (!sqlsrv_fetch($stmt))
{
FatalError("Table $tableName was not expected to be empty.");
}
$numFields = sqlsrv_num_fields($stmt);
if ($numFields != $cols)
{
die("Table $tableName was expected to have $cols fields.");
}
$actualValue = sqlsrv_get_field($stmt, 1, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
sqlsrv_free_stmt($stmt);
if (strncmp($actualValue, $expectedValue, strlen($expectedValue)) != 0)
{
die("Data corruption: $expectedValue => $actualValue.");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
SendStream(12, 23);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECTREGEX--
Test "Stream - Prepared Send" completed successfully.

View file

@ -0,0 +1,186 @@
--TEST--
Streaming Scrollable ResultSets Test
--DESCRIPTION--
Verifies the streaming behavior with scrollable resultsets.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function StreamScroll($noRows, $startRow)
{
include 'MsSetup.inc';
$testName = "Stream - Scrollable";
StartTest($testName);
Setup();
if (! IsWindows())
$conn1 = ConnectUTF8();
else
$conn1 = Connect();
CreateTable($conn1, $tableName);
InsertRowsByRange($conn1, $tableName, $startRow, $startRow + $noRows - 1);
$query = "SELECT * FROM [$tableName] ORDER BY c27_timestamp";
$options = array('Scrollable' => SQLSRV_CURSOR_STATIC);
$stmt1 = SelectQueryEx($conn1, $query, $options);
$numFields = sqlsrv_num_fields($stmt1);
$row = $noRows;
while ($row >= 1)
{
if ($row == $noRows)
{
if (!sqlsrv_fetch($stmt1, SQLSRV_SCROLL_LAST))
{
FatalError("Failed to fetch row ".$row);
}
}
else
{
if (!sqlsrv_fetch($stmt1, SQLSRV_SCROLL_PRIOR))
{
FatalError("Failed to fetch row ".$row);
}
}
Trace("\nStreaming row $row:\n");
$skipCount = 0;
for ($j = 0; $j < $numFields; $j++)
{
$col = $j + 1;
if (!IsUpdatable($col))
{
$skipCount++;
}
if (IsStreamable($col))
{
VerifyStream($stmt1, $startRow + $row - 1, $j, $skipCount);
}
}
$row--;
}
sqlsrv_free_stmt($stmt1);
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function VerifyStream($stmt, $row, $colIndex, $skip)
{
$col = $colIndex + 1;
if (IsStreamable($col))
{
$type = GetSqlType($col);
if (IsBinary($col))
{
$stream = sqlsrv_get_field($stmt, $colIndex, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
}
else
{
if (UseUTF8Data()){
$stream = sqlsrv_get_field($stmt, $colIndex, SQLSRV_PHPTYPE_STREAM('UTF-8'));
}
else{
$stream = sqlsrv_get_field($stmt, $colIndex, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_CHAR));
}
}
if ($stream === false)
{
FatalError("Failed to read field $col: $type");
}
else
{
$value = '';
if ($stream)
{
while (!feof($stream))
{
$value .= fread($stream, 8192);
}
fclose($stream);
$data = GetInsertData($row, $col, $skip);
if (!CheckData($col, $value, $data))
{
Trace("Data corruption on row $row column $col\n");
SetUTF8Data(false);
die("Data corruption on row $row column $col\n");
}
}
TraceData($type, "".strlen($value)." bytes");
}
}
}
function CheckData($col, $actual, $expected)
{
$success = true;
if (IsBinary($col))
{
$actual = bin2hex($actual);
if (strncasecmp($actual, $expected, strlen($expected)) != 0)
{
$success = false;
}
}
else
{
if (strncasecmp($actual, $expected, strlen($expected)) != 0)
{
if ($col != 19)
{
// skip ntext
$pos = strpos($actual, $expected);
if (($pos === false) || ($pos > 1))
{
$success = false;
}
}
}
}
if (!$success)
{
Trace("\nData error\nExpected:\n$expected\nActual:\n$actual\n");
}
return ($success);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
if (! IsWindows())
{
SetUTF8Data(true);
}
try
{
StreamScroll(20, 1);
}
catch (Exception $e)
{
echo $e->getMessage();
}
SetUTF8Data(false);
}
Repro();
?>
--EXPECT--
Test "Stream - Scrollable" completed successfully.

View file

@ -0,0 +1,108 @@
--TEST--
Transaction Execution Test
--DESCRIPTION--
Verifies the basic transaction behavior in the context of INSERT queries.
Two types of sequences are explored:
Begin -> Commit
Begin -> Rollback
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Transaction()
{
include 'MsSetup.inc';
$testName = "Transaction - Execution";
StartTest($testName);
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
$noRows = 10;
ExecTransaction($conn1, false, $tableName, $noRows); // rollback
ExecTransaction($conn1, true, $tableName, $noRows); // submit
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
EndTest($testName);
}
function ExecTransaction($conn, $mode, $tableName, $noRows)
{
if ($mode === true)
{
Trace("\nSUBMIT sequence:\n\t");
}
else
{
Trace("\nROLLBACK sequence:\n\t");
}
sqlsrv_begin_transaction($conn);
$noRowsInserted = InsertRows($conn, $tableName, $noRows);
if ($mode === true)
{
Trace("\tTransaction submit...");
sqlsrv_commit($conn);
}
else
{
Trace("\tTransaction rollback...");
sqlsrv_rollback($conn);
}
$rowCount = 0;
$stmt = SelectFromTable($conn, $tableName);
while (sqlsrv_fetch($stmt))
{
$rowCount++;
}
sqlsrv_free_stmt($stmt);
Trace(" rows effectively inserted: $rowCount.\n");
if ($mode === true)
{ // commit: expected to fetch all inserted rows
if ($rowCount != $noRowsInserted)
{
die("An incorrect number of rows was fetched. Expected: ".$noRows);
}
}
else
{ // rollback: no row should have been inserted
if ($rowCount > 0)
{
die("No row should have been fetched after rollback");
}
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Transaction();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Transaction - Execution" completed successfully.

View file

@ -0,0 +1,84 @@
--TEST--
Transaction Disconnect Test
--DESCRIPTION--
Validates that a closing a connection during a transaction will
implicitly rollback the database changes attempted by the transaction.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Transaction()
{
include 'MsSetup.inc';
$testName = "Transaction - Disconnect";
StartTest($testName);
Setup();
$conn1 = Connect();
CreateTable($conn1, $tableName);
$noRows = 10;
// Insert rows and disconnect before the transaction is commited (implicit rollback)
Trace("\nBegin transaction...\n");
sqlsrv_begin_transaction($conn1);
InsertRows($conn1, $tableName, $noRows);
Trace("Disconnect prior to commit...\n\n");
sqlsrv_close($conn1);
// Insert rows and commit the transaction
$conn2 = Connect();
Trace("Begin transaction...\n");
sqlsrv_begin_transaction($conn2);
$noRowsInserted = InsertRows($conn2, $tableName, $noRows);
Trace("Transaction commit...\n");
sqlsrv_commit($conn2);
$rowCount = 0;
$stmt1 = SelectFromTable($conn2, $tableName);
while (sqlsrv_fetch($stmt1))
{
$rowCount++;
}
sqlsrv_free_stmt($stmt1);
Trace("\nRows effectively inserted through both transactions: ".$rowCount."\n");
if ($rowCount != $noRowsInserted)
{
die("An incorrect number of rows was fetched. Expected: ".$noRowsInserted);
}
DropTable($conn2, $tableName);
sqlsrv_close($conn2);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Transaction();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Transaction - Disconnect" completed successfully.

View file

@ -0,0 +1,166 @@
--TEST--
Transaction Boundaries Test
--DESCRIPTION--
Validates that a transaction is bound to a connection.
Test has several steps as follows:
- Two concurrent connections initiate interlaced transactions.
- Through each {connection, transaction} pair a number of rows
are inserted into the same table.
- Verifies that the table has expected number of rows.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Transaction($steps)
{
include 'MsSetup.inc';
$testName = "Transaction - Boundaries";
StartTest($testName);
Setup();
$conn1 = Connect();
$conn2 = Connect();
CreateTable($conn1, $tableName);
$noRows1 = 2; // inserted rows
$noRows2 = 3;
$noRows = 0; // expected rows
for ($k = 0; $k < $steps; $k++)
{
switch ($k)
{
case 0: // nested commit
sqlsrv_begin_transaction($conn1);
sqlsrv_begin_transaction($conn2);
InsertRows($conn1, $tableName, $noRows1);
InsertRows($conn2, $tableName, $noRows2);
sqlsrv_commit($conn2);
sqlsrv_commit($conn1);
$noRows += ($noRows1 + $noRows2);
break;
case 1: // nested rollback
sqlsrv_begin_transaction($conn1);
sqlsrv_begin_transaction($conn2);
InsertRows($conn1, $tableName, $noRows1);
InsertRows($conn2, $tableName, $noRows2);
sqlsrv_rollback($conn2);
sqlsrv_rollback($conn1);
break;
case 2: // nested commit & rollback
sqlsrv_begin_transaction($conn1);
sqlsrv_begin_transaction($conn2);
InsertRows($conn1, $tableName, $noRows1);
InsertRows($conn2, $tableName, $noRows2);
sqlsrv_rollback($conn2);
sqlsrv_commit($conn1);
$noRows += $noRows1;
break;
case 3: // interleaved commit
sqlsrv_begin_transaction($conn1);
InsertRows($conn1, $tableName, $noRows1);
sqlsrv_begin_transaction($conn2);
sqlsrv_commit($conn1);
InsertRows($conn2, $tableName, $noRows2);
sqlsrv_commit($conn2);
$noRows += ($noRows1 + $noRows2);
break;
case 4: // interleaved insert
sqlsrv_begin_transaction($conn1);
InsertRows($conn1, $tableName, $noRows1);
sqlsrv_begin_transaction($conn2);
InsertRows($conn2, $tableName, $noRows2);
sqlsrv_commit($conn1);
sqlsrv_commit($conn2);
$noRows += ($noRows1 + $noRows2);
break;
case 5: // interleaved insert & commit
sqlsrv_begin_transaction($conn1);
sqlsrv_begin_transaction($conn2);
InsertRows($conn1, $tableName, $noRows1);
sqlsrv_commit($conn1);
InsertRows($conn2, $tableName, $noRows2);
sqlsrv_commit($conn2);
$noRows += ($noRows1 + $noRows2);
break;
case 6: // interleaved execution with commit & rollback
sqlsrv_begin_transaction($conn1);
InsertRows($conn1, $tableName, $noRows1);
sqlsrv_begin_transaction($conn2);
InsertRows($conn2, $tableName, $noRows2);
sqlsrv_commit($conn2);
sqlsrv_rollback($conn1);
$noRows += $noRows2;
break;
case 7: // mixed execution
sqlsrv_begin_transaction($conn1);
InsertRows($conn1, $tableName, $noRows1);
InsertRows($conn2, $tableName, $noRows2);
sqlsrv_commit($conn1);
$noRows += ($noRows1 + $noRows2);
break;
default:// no transaction
InsertRows($conn1, $tableName, $noRows1);
InsertRows($conn2, $tableName, $noRows2);
$noRows += ($noRows1 + $noRows2);
break;
}
}
$rowCount = 0;
$stmt1 = SelectFromTable($conn1, $tableName);
while (sqlsrv_fetch($stmt1))
{
$rowCount++;
}
sqlsrv_free_stmt($stmt1);
Trace("Row insertion attempts through all the transactions: ".$steps * ($noRows1 + $noRows2)."\n");
Trace("Rows effectively inserted through all the transactions: ".$rowCount."\n");
if ($rowCount != $noRows)
{
die("An incorrect number of rows was fetched. Expected: ".$noRows);
}
DropTable($conn1, $tableName);
sqlsrv_close($conn1);
sqlsrv_close($conn2);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Transaction(9);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Transaction - Boundaries" completed successfully.

View file

@ -0,0 +1,122 @@
--TEST--
Transaction with Stored Procedure Test
--DESCRIPTION--
Verifies the basic transaction behavior in the context of an
INSERT query performed within a stored procedure.
Two types of sequences are explored.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function Transaction($minType, $maxType)
{
include 'MsSetup.inc';
$testName = "Transaction - Stored Proc";
StartTest($testName);
Setup();
$conn1 = Connect();
$colName = "c1";
for ($k = $minType; $k <= $maxType; $k++)
{
switch ($k)
{
case 20: // binary
case 21: // varbinary
case 22: // varbinary(max)
$data = null;
break;
default:
$data = GetSampleData($k);
break;
}
if ($data != null)
{
$sqlType = GetSqlType($k);
CreateTableEx($conn1, $tableName, "[$colName] $sqlType");
CreateTransactionProc($conn1, $tableName, $colName, $procName, $sqlType);
$noRows = ExecTransactionProc($conn1, $procName, $data, true);
if ($noRows != 1)
{
die("$sqlType: Incorrect row count after commit: $noRows");
}
$noRows = ExecTransactionProc($conn1, $procName, $data, false);
if ($noRows != 2)
{
die("$sqlType: Incorrect row count after rollback: $noRows");
}
$noRows = NumRows($conn1, $tableName);
if ($noRows != 1)
{
die("$sqlType: Incorrect total row count: $noRows");
}
DropProc($conn1, $procName);
DropTable($conn1, $tableName);
}
}
sqlsrv_close($conn1);
EndTest($testName);
}
function CreateTransactionProc($conn, $tableName, $colName, $procName, $sqlType)
{
$procArgs = "@p1 $sqlType, @p2 INT OUTPUT";
$procCode = "SET NOCOUNT ON; INSERT INTO [$tableName] ($colName) VALUES (@p1) SET @p2 = (SELECT COUNT(*) FROM [$tableName])";
CreateProc($conn, $procName, $procArgs, $procCode);
}
function ExecTransactionProc($conn, $procName, $data, $commitMode)
{
$retValue = -1;
$callArgs = array(array($data, SQLSRV_PARAM_IN), array(&$retValue, SQLSRV_PARAM_OUT));
sqlsrv_begin_transaction($conn);
$stmt = CallProc($conn, $procName, "?, ?", $callArgs);
if ($commitMode === true)
{ // commit
sqlsrv_commit($conn);
}
else
{ // rollback
sqlsrv_rollback($conn);
}
return ($retValue);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
Transaction(1, 28);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Transaction - Stored Proc" completed successfully.

View file

@ -0,0 +1,84 @@
--TEST--
Stored Proc Call Test
--DESCRIPTION--
Verifies the ability to create and subsequently call a stored procedure.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function StoredProc()
{
include 'MsSetup.inc';
$testName = "Stored Proc Call";
$data1 = "Microsoft SQL Server ";
$data2 = "Driver for PHP";
StartTest($testName);
Setup();
$conn1 = Connect();
ExecProc($conn1, $procName, "CHAR", $data1, $data2);
ExecProc($conn1, $procName, "VARCHAR", $data1, $data2);
ExecProc($conn1, $procName, "NCHAR", $data1, $data2);
ExecProc($conn1, $procName, "NVARCHAR", $data1, $data2);
sqlsrv_close($conn1);
EndTest($testName);
}
function ExecProc($conn, $procName, $sqlType, $inValue1, $inValue2)
{
$len1 = strlen($inValue1);
$len2 = strlen($inValue2);
$len = $len1 + $len2;
$sqlTypeIn1 = "$sqlType($len1)";
$sqlTypeIn2 = "$sqlType($len2)";
$sqlTypeOut = "$sqlType($len)";
$expected = "$inValue1$inValue2";
$actual = "";
$procArgs = "@p1 $sqlTypeOut OUTPUT, @p2 $sqlTypeIn1, @p3 $sqlTypeIn2";
$procCode = "SET @p1 = CONVERT($sqlTypeOut, @p2 + @p3)";
$callArgs = array(array(&$actual, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_CHAR($len)),
array($inValue1, SQLSRV_PARAM_IN),
array($inValue2, SQLSRV_PARAM_IN));
CreateProc($conn, $procName, $procArgs, $procCode);
CallProc($conn, $procName, "?, ?, ?", $callArgs);
DropProc($conn, $procName);
if (strncmp($actual, $expected, strlen($expected)) != 0)
{
die("Data corruption: $expected => $actual.");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
StoredProc();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Stored Proc Call" completed successfully.

View file

@ -0,0 +1,84 @@
--TEST--
Stored Function Test
--DESCRIPTION--
Verifies the ability to create and subsequently call a stored procedure.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function StoredFunc()
{
include 'MsSetup.inc';
$testName = "Stored Function";
$data1 = "Microsoft SQL Server ";
$data2 = "Driver for PHP";
StartTest($testName);
Setup();
$conn1 = Connect();
ExecFunc($conn1, $procName, "CHAR", $data1, $data2);
ExecFunc($conn1, $procName, "VARCHAR", $data1, $data2);
ExecFunc($conn1, $procName, "NCHAR", $data1, $data2);
ExecFunc($conn1, $procName, "NVARCHAR", $data1, $data2);
sqlsrv_close($conn1);
EndTest($testName);
}
function ExecFunc($conn, $funcName, $sqlType, $inValue1, $inValue2)
{
$len1 = strlen($inValue1);
$len2 = strlen($inValue2);
$len = $len1 + $len2;
$sqlTypeIn1 = "$sqlType($len1)";
$sqlTypeIn2 = "$sqlType($len2)";
$sqlTypeOut = "$sqlType($len)";
$expected = "$inValue1$inValue2";
$actual = "";
$funcArgs = "@p1 $sqlTypeIn1, @p2 $sqlTypeIn2";
$funcCode = "RETURN (CONVERT($sqlTypeOut, @p1 + @p2))";
$callArgs = array(array(&$actual, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_CHAR($len)),
array($inValue1, SQLSRV_PARAM_IN),
array($inValue2, SQLSRV_PARAM_IN));
CreateFunc($conn, $funcName, $funcArgs, $sqlTypeOut, $funcCode);
CallFunc($conn, $funcName, "?, ?", $callArgs);
DropFunc($conn, $funcName);
if (strncmp($actual, $expected, strlen($expected)) != 0)
{
die("Data corruption: $expected => $actual.");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
StoredFunc();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Stored Function" completed successfully.

View file

@ -0,0 +1,146 @@
--TEST--
Stored Proc Call Test
--DESCRIPTION--
Verifies the ability to create and subsequently call a stored procedure.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function StoredProc()
{
include 'MsSetup.inc';
$testName = "Stored Proc Call";
StartTest($testName);
Setup();
$conn1 = Connect();
$step = 0;
$dataStr = "The quick brown fox jumps over the lazy dog.";
$dataInt = 0;
// Scenario #1: using a null buffer
$step++;
if (!ExecProc1($conn1, $procName, $dataStr, 40, 0))
{
die("Execution failure at step $step.");
}
// Scenario #2: using a pre-allocated buffer
$step++;
if (!ExecProc1($conn1, $procName, $dataStr, 25, 1))
{
die("Execution failure at step $step.");
}
// Scenario #3: specifying an exact return size
$step++;
if (!ExecProc1($conn1, $procName, $dataStr, 0, 2))
{
die("Execution failure at step $step.");
}
// Scenario #4: specifying a larger return size
$step++;
if (!ExecProc1($conn1, $procName, $dataStr, 50, 2))
{
die("Execution failure at step $step.");
}
// Scenario #5: returning a value
$step++;
if (!ExecProc2($conn1, $procName, $dataInt))
{
die("Execution failure at step $step.");
}
sqlsrv_close($conn1);
EndTest($testName);
}
function ExecProc1($conn, $procName, $dataIn, $extraSize, $phpInit)
{
$inValue = trim($dataIn);
$outValue = null;
$lenData = strlen($inValue);
$len = $lenData + $extraSize;
$procArgs = "@p1 VARCHAR($len) OUTPUT";
$procCode = "SET @p1 = '$inValue'";
if ($phpInit == 1)
{
$outValue = "";
for ($i = 0; $i < $len; $i++)
{ // fill the buffer with "A"
$outValue = $outValue."A";
}
}
$callArgs = array(array(&$outValue, SQLSRV_PARAM_OUT,
SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR),
SQLSRV_SQLTYPE_VARCHAR($lenData + 1)));
CreateProc($conn, $procName, $procArgs, $procCode);
CallProc($conn, $procName, "?", $callArgs);
DropProc($conn, $procName);
if ($inValue != trim($outValue))
{
Trace("Data corruption: [$inValue] => [$outValue]\n");
return (false);
}
return (true);
}
function ExecProc2($conn, $procName, $dataIn)
{
$procArgs = "@p1 INT";
$procCode = "SET NOCOUNT ON; SELECT 199 IF @p1 = 0 RETURN 11 ELSE RETURN 22";
$retValue = -1;
$callArgs = array(array(&$retValue, SQLSRV_PARAM_OUT), array($dataIn, SQLSRV_PARAM_IN));
CreateProc($conn, $procName, $procArgs, $procCode);
$stmt = CallProcEx($conn, $procName, "? = ", "?", $callArgs);
DropProc($conn, $procName);
$row = sqlsrv_fetch_array($stmt);
$count = count($row);
sqlsrv_next_result($stmt);
sqlsrv_free_stmt($stmt);
if (($row === false) || ($count <= 0) || ($row[0] != 199) ||
(($retValue != 11) && ($retValue != 22)))
{
Trace("Row count = $count, Returned value = $retValue\n");
return (false);
}
return (true);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
StoredProc();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Stored Proc Call" completed successfully.

View file

@ -0,0 +1,121 @@
--TEST--
Stored Proc Query Test
--DESCRIPTION--
Verifies the data retrieved via a store procedure to validate behavior
of queries including SQLSRV_PARAM_OUT qualifiers.
Checks all numeric data types (i.e. 10 SQL types).
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ProcQuery($minType, $maxType)
{
include 'MsSetup.inc';
$testName = "Stored Proc Query";
StartTest($testName);
Setup();
$conn1 = Connect();
for ($k = $minType; $k <= $maxType; $k++)
{
switch ($k)
{
case 1: // TINYINT
ExecProcQuery($conn1, $procName, "TINYINT", 11, 12, 23);
break;
case 2: // SMALLINT
ExecProcQuery($conn1, $procName, "SMALLINT", 4.3, 5.5, 9);
break;
case 3: // INT
ExecProcQuery($conn1, $procName, "INT", 3.2, 4, 7);
break;
case 4: // BIGINT
ExecProcQuery($conn1, $procName, "BIGINT", 5.2, 3.7, 8);
break;
case 5: // FLOAT
ExecProcQuery($conn1, $procName, "FLOAT", 2.5, 5.25, 7.75);
break;
case 6: // REAL
ExecProcQuery($conn1, $procName, "REAL", 3.4, 6.6, 10);
break;
case 7: // DECIMAL
ExecProcQuery($conn1, $procName, "DECIMAL", 2.1, 5.3, 7);
break;
case 8: // NUMERIC
ExecProcQuery($conn1, $procName, "NUMERIC", 2.8, 5.4, 8);
break;
case 9: // SMALLMONEY
ExecProcQuery($conn1, $procName, "SMALLMONEY", 10, 11.7, 21.7);
break;
case 10:// MONEY
ExecProcQuery($conn1, $procName, "MONEY", 22.3, 16.1, 38.4);
break;
default:// default
break;
}
}
sqlsrv_close($conn1);
EndTest($testName);
}
function ExecProcQuery($conn, $procName, $dataType, $inData1, $inData2, $outData)
{
$procArgs = "@p1 $dataType, @p2 $dataType, @p3 $dataType OUTPUT";
$procCode = "SELECT @p3 = CONVERT($dataType, @p1 + @p2)";
CreateProc($conn, $procName, $procArgs, $procCode);
$callArgs = "?, ?, ?";
$callResult = 0.0;
$callValues = array($inData1, $inData2, array(&$callResult, SQLSRV_PARAM_OUT));
CallProc($conn, $procName, $callArgs, $callValues);
DropProc($conn, $procName);
TraceData($dataType, "".$inData1." + ".$inData2." = ".$callResult);
if ($callResult != $outData)
{
die("Expected result for ".$dataType." was ".$outData);
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ProcQuery(1, 10);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Stored Proc Query" completed successfully.

View file

@ -0,0 +1,105 @@
--TEST--
Data Roundtrip via Stored Proc
--DESCRIPTION--
Verifies that data is not corrupted through a roundtrip via a store procedure.
Checks all character data types.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function StoredProcRoundtrip($minType, $maxType)
{
include 'MsSetup.inc';
$testName = "Stored Proc Roundtrip";
StartTest($testName);
Setup();
$conn1 = Connect();
$data = "The quick brown fox jumps over the lazy dog 0123456789";
$dataSize = strlen($data);
for ($i = $minType; $i <= $maxType; $i++)
{
$dataTypeIn = GetSqlType($i);
$phpTypeIn = GetDriverType($i, $dataSize);
for ($j = $minType; $j <= $maxType; $j++)
{
$k = $j;
switch ($j)
{ // avoid LOB types as output
case 14: // varchar(max)
case 18: // text
$k = 13; // varchar
break;
case 17: // nvarchar(max)
case 19: // ntext
$k = 16; // nvarchar
break;
default:
break;
}
$dataTypeOut = GetSqlType($k);
$phpTypeOut = GetDriverType($k, 512);
ExecProcRoundtrip($conn1, $procName, $dataTypeIn, $dataTypeOut, $phpTypeIn, $phpTypeOut, $data);
}
}
sqlsrv_close($conn1);
EndTest($testName);
}
function ExecProcRoundtrip($conn, $procName, $dataTypeIn, $dataTypeOut, $phpTypeIn, $phpTypeOut, $dataIn)
{
$procArgs = "@p1 $dataTypeIn, @p2 $dataTypeOut OUTPUT";
$procCode = "SELECT @p2 = CONVERT($dataTypeOut, @p1)";
CreateProc($conn, $procName, $procArgs, $procCode);
$callArgs = "?, ?";
$callResult = "";
$callValues = array(array($dataIn, SQLSRV_PARAM_IN, null, $phpTypeIn),
array(&$callResult, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), $phpTypeOut));
CallProc($conn, $procName, $callArgs, $callValues);
DropProc($conn, $procName);
$dataOut = trim($callResult);
if (strncmp($dataOut, $dataIn, strlen($dataIn)) != 0)
{
TraceData($dataTypeIn."=>".$dataTypeOut, "\n In: [".$dataIn."]\nOut: [".$dataOut."]");
die("Unexpected result for ".$dataTypeIn."=>".$dataTypeOut);
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
StoredProcRoundtrip(12, 19);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Stored Proc Roundtrip" completed successfully.

View file

@ -0,0 +1,74 @@
--TEST--
Stored Proc Null Data Test
--DESCRIPTION--
Verifies the ability to return a null string from a stored procedure.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function StoredProc()
{
include 'MsSetup.inc';
$testName = "Stored Proc - Null Data";
$data1 = "Microsoft SQL Server ";
$data2 = "Driver for PHP";
StartTest($testName);
Setup();
$conn1 = Connect();
ExecProc($conn1, $procName, "VARCHAR(32)", SQLSRV_SQLTYPE_VARCHAR(32), "ABC");
ExecProc($conn1, $procName, "FLOAT", SQLSRV_SQLTYPE_FLOAT, 3.2);
ExecProc($conn1, $procName, "INT", SQLSRV_SQLTYPE_INT, 5);
sqlsrv_close($conn1);
EndTest($testName);
}
function ExecProc($conn, $procName, $sqlType, $sqlTypeEx, $initData)
{
$data = $initData;
$procArgs = "@p1 $sqlType OUTPUT";
$procCode = "SET @p1 = NULL";
$callArgs = array(array(&$data, SQLSRV_PARAM_OUT, null, $sqlTypeEx));
CreateProc($conn, $procName, $procArgs, $procCode);
CallProc($conn, $procName, "?", $callArgs);
DropProc($conn, $procName);
if ($data != null)
{
die("Data corruption: [$data] instead of null.");
}
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
StoredProc();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test "Stored Proc - Null Data" completed successfully.

View file

@ -0,0 +1,76 @@
--TEST--
Data Roundtrip via Stored Proc
--DESCRIPTION--
Verifies that data is not corrupted through a roundtrip via a store procedure.
Checks all character data types.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function BugRepro()
{
include 'MsSetup.inc';
$testName = "Regression VSTS 611146";
StartTest($testName);
Setup();
$conn1 = Connect();
// empty parameter array
$s = sqlsrv_query( $conn1, "select ?", array( array() ));
if( $s !== false )
{
die( "Should have failed." );
}
else
{
$arr = sqlsrv_errors();
print_r( $arr[0][2] );
print_r( "\n" );
}
// unknown direction
$s = sqlsrv_query( $conn1, "select ?", array( array( 1, 1000 ) ));
if( $s !== false )
{
die( "Should have failed." );
}
else
{
$arr = sqlsrv_errors();
print_r( $arr[0][2] );
print_r( "\n" );
}
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
BugRepro();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Parameter array 1 must have at least one value or variable.
An invalid direction for parameter 1 was specified. SQLSRV_PARAM_IN, SQLSRV_PARAM_OUT, and SQLSRV_PARAM_INOUT are valid values.
Test "Regression VSTS 611146" completed successfully.

View file

@ -0,0 +1,72 @@
--TEST--
Data Roundtrip via Stored Proc
--DESCRIPTION--
Verifies that data is not corrupted through a roundtrip via a store procedure.
Checks all character data types.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function BugRepro()
{
include 'MsSetup.inc';
$testName = "Regression VSTS 846501";
StartTest($testName);
Setup();
$conn1 = Connect();
// empty parameter array
$s = sqlsrv_query( $conn1, "DROP TABLE test_bq" );
$s = sqlsrv_query( $conn1, "CREATE TABLE test_bq (id INT IDENTITY NOT NULL, test_varchar_max varchar(max))" );
if( $s === false ) {
die( print_r( sqlsrv_errors(), true ));
}
$s = sqlsrv_query( $conn1, "CREATE CLUSTERED INDEX [idx_test_int] ON test_bq (id)" );
if( $s === false ) {
die( print_r( sqlsrv_errors(), true ));
}
$s = sqlsrv_query( $conn1, "INSERT INTO test_bq (test_varchar_max) VALUES ('ABCD')" );
if( $s === false ) {
die( print_r( sqlsrv_errors(), true ));
}
$tsql = "select test_varchar_max from test_bq";
$result = sqlsrv_query( $conn1, $tsql, array(), array( "Scrollable" => SQLSRV_CURSOR_CLIENT_BUFFERED ));
while($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_BOTH))
{
print $row['test_varchar_max']."\n";
}
sqlsrv_query( $conn1, "DROP TABLE test_bq" );
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
BugRepro();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
ABCD
Test "Regression VSTS 846501" completed successfully.

View file

@ -0,0 +1,108 @@
--TEST--
Complex Stored Proc Test
--DESCRIPTION--
Test output string parameters with rows affected return results before output parameter.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function StoredProcCheck()
{
include 'MsSetup.inc';
$testName = "ResultSet with Stored Proc";
StartTest($testName);
Setup();
$conn1 = Connect();
$table1 = $tableName."_1";
$table2 = $tableName."_2";
$table3 = $tableName."_3";
$procArgs = "@p1 int, @p2 nchar(32), @p3 nvarchar(64), @p4 nvarchar(max) OUTPUT";
$introText="Initial Value";
$callArgs = array(array(1, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_INT, SQLSRV_SQLTYPE_INT),
array('Dummy No', SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_NCHAR(32)),
array('Dummy ID', SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_NVARCHAR(50)),
array( &$introText, SQLSRV_PARAM_OUT, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_NVARCHAR(256)));
$procCode =
"IF (@p3 IS NULL)
BEGIN
INSERT INTO [$table1] (DataID, ExecTime, DataNo) values (@p1, GETDATE(), @p2)
END
ELSE
BEGIN
INSERT INTO [$table1] (DataID, ExecTime, DataNo, DataRef) values (@p1, GETDATE(), @p2, @p3)
END
INSERT INTO [$table2] (DataID, DataNo) values (@p1, @p2)
SELECT @p4=(SELECT Intro from [$table3] WHERE DataID=@p1) ";
CreateTableEx($conn1, $table1, "DataID int, ExecTime datetime, DataNo nchar(32), DataRef nvarchar(64)");
CreateTableEx($conn1, $table2, "DataID int, DataNo nchar(32)");
CreateTableEx($conn1, $table3, "DataID int, Intro nvarchar(max)");
CreateProc($conn1, $procName, $procArgs, $procCode);
$stmt1 = sqlsrv_query($conn1, "INSERT INTO [$table3] (DataID, Intro) VALUES (1, 'Test Value 1')");
InsertCheck($stmt1);
$stmt2 = sqlsrv_query($conn1, "INSERT INTO [$table3] (DataID, Intro) VALUES (2, 'Test Value 2')");
InsertCheck($stmt2);
$stmt3 = sqlsrv_query($conn1, "INSERT INTO [$table3] (DataID, Intro) VALUES (3, 'Test Value 3')");
InsertCheck($stmt3);
$stmt4 = CallProcEx($conn1, $procName, "", "?, ?, ?, ?", $callArgs);
$result = sqlsrv_next_result($stmt4);
while ($result != null)
{
if( $result === false )
{
FatalError("Failed to execute sqlsrv_next_result");
}
$result = sqlsrv_next_result($stmt4);
}
sqlsrv_free_stmt($stmt4);
DropProc($conn1, $procName);
echo "$introText\n";
DropTable($conn1, $table1);
DropTable($conn1, $table2);
DropTable($conn1, $table3);
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
StoredProcCheck();
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
Test Value 1
Test "ResultSet with Stored Proc" completed successfully.

View file

@ -0,0 +1,80 @@
--TEST--
Complex Insert Query Test
--DESCRIPTION--
Test the driver behavior with a complex insert query.
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function ComplexInsert($count)
{
include 'MsSetup.inc';
$testName = "Complex Insert Query";
StartTest($testName);
Setup();
$conn1 = Connect();
DropTable($conn1, $tableName);
$data = "a1='1', a2='2', a3='3', a4='4', a5='5', a6='6'";
$querySelect = "SELECT COUNT(*) FROM [$tableName]";
$queryInsert =
" SELECT $data INTO [$tableName]
DECLARE @i int
SET @i=1
WHILE (@i < $count)
BEGIN
INSERT [$tableName]
SELECT $data
SET @i = @i + 1
END
";
$stmt1 = ExecuteQuery($conn1, $queryInsert);
while (sqlsrv_next_result($stmt1) != NULL) {};
sqlsrv_free_stmt($stmt1);
$stmt2 = ExecuteQuery($conn1, $querySelect);
$row = sqlsrv_fetch_array($stmt2);
sqlsrv_free_stmt($stmt2);
printf("$count rows attempted; actual rows created = ".$row[0]."\n");
sqlsrv_close($conn1);
EndTest($testName);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
try
{
ComplexInsert(160);
}
catch (Exception $e)
{
echo $e->getMessage();
}
}
Repro();
?>
--EXPECT--
160 rows attempted; actual rows created = 160
Test "Complex Insert Query" completed successfully.

View file

@ -0,0 +1,89 @@
--TEST--
PHP - Large Column Name Test
--Description--
Verifies that long column names are supported (up to 128 chars).
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function LargeColumnNameTest($columnName, $expectfail)
{
include 'MsSetup.inc';
Setup();
$conn = Connect();
$tableName = "LargeColumnNameTest";
DropTable($conn, $tableName);
sqlsrv_query($conn, "CREATE TABLE [$tableName] ([$columnName] int)");
sqlsrv_query($conn, "INSERT INTO [$tableName] ([$columnName]) VALUES (5)");
$stmt = sqlsrv_query($conn, "SELECT * from [$tableName]");
if ( null == $stmt )
{
echo "$";
echo "stmt = null";
echo "\n";
}
else
{
if ( null == sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) )
{
if (!$expectfail)
FatalError("Possible regression: Unable to retrieve inserted value.");
}
sqlsrv_free_stmt($stmt);
}
DropTable($conn, $tableName);
sqlsrv_close($conn);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
$testName = "PHP - Large Column Name Test";
StartTest($testName);
$columnName = "a";
try
{
for ($a = 1; $a <= 129; $a++)
{
LargeColumnNameTest($columnName, $a > 128);
$columnName .= "A";
}
}
catch (Exception $e)
{
echo $e->getMessage();
}
EndTest($testName);
}
Repro();
?>
--EXPECT--
$stmt = null
Test "PHP - Large Column Name Test" completed successfully.

View file

@ -0,0 +1,86 @@
--TEST--
PHP - Large Unicode Column Name Test
--DESCRIPTION--
Verifies that long column names are supported (up to 128 chars).
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function LargeColumnNameTest($columnName, $expectfail)
{
include 'MsSetup.inc';
Setup();
$conn = ConnectUTF8();
$tableName = "LargeColumnNameTest";
DropTable($conn, $tableName);
sqlsrv_query($conn, "CREATE TABLE [$tableName] ([$columnName] int)");
sqlsrv_query($conn, "INSERT INTO [$tableName] ([$columnName]) VALUES (5)");
$stmt = sqlsrv_query($conn, "SELECT * from [$tableName]");
if ( null == $stmt )
{
echo "$";
echo "stmt = null";
echo "\n";
}
else
{
if ( null == sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) )
{
if (!$expectfail)
FatalError("Possible regression: Unable to retrieve inserted value.");
}
sqlsrv_free_stmt($stmt);
}
sqlsrv_close($conn);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
$testName = "PHP - Large Unicode Column Name Test";
StartTest($testName);
$columnName = "银";
try
{
for ($a = 1; $a <= 129; $a++)
{
LargeColumnNameTest($columnName, $a > 128);
$columnName .= "银";
}
}
catch (Exception $e)
{
echo $e->getMessage();
}
EndTest($testName);
}
Repro();
?>
--EXPECT--
$stmt = null
Test "PHP - Large Unicode Column Name Test" completed successfully.

View file

@ -0,0 +1,86 @@
--TEST--
PHP - Large Unicode Column Name Test
--DESCRIPTION--
Verifies that long column names are supported (up to 128 chars).
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function LargeColumnNameTest($columnName, $expectfail)
{
include 'MsSetup.inc';
Setup();
$conn = ConnectUTF8();
$tableName = "LargeColumnNameTest";
DropTable($conn, $tableName);
sqlsrv_query($conn, "CREATE TABLE [$tableName] ([$columnName] int)");
sqlsrv_query($conn, "INSERT INTO [$tableName] ([$columnName]) VALUES (5)");
$stmt = sqlsrv_query($conn, "SELECT * from [$tableName]");
if ( null == $stmt )
{
echo "$";
echo "stmt = null";
echo "\n";
}
else
{
if ( null == sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC) )
{
if (!$expectfail)
FatalError("Possible regression: Unable to retrieve inserted value.");
}
sqlsrv_free_stmt($stmt);
}
sqlsrv_close($conn);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
$testName = "PHP - Large Unicode Column Name Test";
StartTest($testName);
$columnName = "银";
try
{
for ($a = 1; $a <= 129; $a++)
{
LargeColumnNameTest($columnName, $a > 128);
$columnName .= "银";
}
}
catch (Exception $e)
{
echo $e->getMessage();
}
EndTest($testName);
}
Repro();
?>
--EXPECT--
$stmt = null
Test "PHP - Large Unicode Column Name Test" completed successfully.

View file

@ -0,0 +1,94 @@
--TEST--
PHP - Max Output Params Test
--DESCRIPTION--
Fetch data as VARCHAR(MAX)
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function MaxOutputParamsTest($buffer, $phptype, $sqltype, $expected)
{
include 'MsSetup.inc';
Setup();
$conn = Connect();
DropProc($conn, "EXEC_TEST");
CreateProc(
$conn,
"EXEC_TEST",
"@OUT varchar(80) output",
"SET NOCOUNT ON; select @OUT = '$expected'; return (0)
");
$outstr = $buffer;
$sql = "execute EXEC_TEST ?";
$stmt = sqlsrv_prepare($conn, $sql, array(array( &$outstr, SQLSRV_PARAM_OUT, $phptype, $sqltype)));
sqlsrv_execute($stmt);
echo "Expected: $expected Received: $outstr\n";
if ($outstr !== $expected)
{
print_r(sqlsrv_errors(SQLSRV_ERR_ALL));
return(-1);
}
sqlsrv_free_stmt($stmt);
sqlsrv_close($conn);
return(0);
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
$failed = null;
$testName = "PHP - Max Output Params Test";
StartTest($testName);
try
{
$failed |= MaxOutputParamsTest("ab", SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_VARCHAR('MAX'), "abc");
$failed |= MaxOutputParamsTest(null, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_VARCHAR('10'), "abc");
$failed |= MaxOutputParamsTest(null, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), SQLSRV_SQLTYPE_VARCHAR('MAX'), "abc");
$failed |= MaxOutputParamsTest(null, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY), SQLSRV_SQLTYPE_VARCHAR('MAX'), "abc");
$failed |= MaxOutputParamsTest("abc", SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR), null, "abc");
}
catch (Exception $e)
{
echo $e->getMessage();
}
if ($failed)
FatalError("Possible Regression: Value returned as VARCHAR(MAX) truncated");
EndTest($testName);
}
Repro();
?>
--EXPECT--
Expected: abc Received: abc
Expected: abc Received: abc
Expected: abc Received: abc
Expected: abc Received: abc
Expected: abc Received: abc
Test "PHP - Max Output Params Test" completed successfully.

View file

@ -0,0 +1,100 @@
--TEST--
PHP - Insert Nulls
--DESCRIPTION--
Test inserting nulls into nullable columns
--ENV--
PHPT_EXEC=true
--SKIPIF--
<?php require('skipif.inc'); ?>
--FILE--
<?php
include 'MsCommon.inc';
function InsertNullsTest($phptype, $sqltype)
{
include 'MsSetup.inc';
$outvar = null;
$failed = false;
Setup();
$conn = Connect();
DropTable($conn, $tableName);
CreateTable($conn, $tableName);
$stmt = sqlsrv_query($conn, <<<SQL
SELECT [TABLE_NAME],[COLUMN_NAME],[IS_NULLABLE] FROM [INFORMATION_SCHEMA].[COLUMNS] WHERE [TABLE_NAME] = '$tableName'
SQL
);
if ($stmt === false)
{
FatalError("Could not query for column information on table $tableName");
}
while ($row = sqlsrv_fetch($stmt))
{
$tableName = sqlsrv_get_field($stmt, 0);
$columnName = sqlsrv_get_field($stmt, 1);
$nullable = sqlsrv_get_field($stmt, 2);
Trace($columnName . ": " . $nullable . "\n");
if (($nullable == 'YES') && (strpos($columnName, "binary") !== false))
{
$stmt2 = sqlsrv_prepare($conn, "INSERT INTO [$tableName] ([" . $columnName . "]) VALUES (?)",
array(array( null, SQLSRV_PARAM_IN, $phptype, $sqltype)) );
if (!sqlsrv_execute($stmt2))
{
print_r(sqlsrv_errors(SQLSRV_ERR_ALL));
$failed = true;
}
}
}
DropTable($conn, $tableName);
return $failed;
}
//--------------------------------------------------------------------
// Repro
//
//--------------------------------------------------------------------
function Repro()
{
$failed = null;
$testName = "PHP - Insert Nulls";
StartTest($testName);
try
{
$failed |= InsertNullsTest(SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_BINARY), null);
$failed |= InsertNullsTest(null, SQLSRV_SQLTYPE_VARBINARY('10'));
}
catch (Exception $e)
{
echo $e->getMessage();
}
if ($failed)
FatalError("Possible Regression: Could not insert NULL");
EndTest($testName);
}
Repro();
?>
--EXPECT--
Test "PHP - Insert Nulls" completed successfully.