Merge pull request #592 from yitam/nextResult
Fix to GitHub issues 574 and 580
This commit is contained in:
commit
04f50341bc
|
@ -45,7 +45,7 @@ namespace {
|
|||
|
||||
// *** internal constants ***
|
||||
|
||||
const int INITIAL_FIELD_STRING_LEN = 256; // base allocation size when retrieving a string field
|
||||
const int INITIAL_LOB_FIELD_LEN = 2048; // base allocation size when retrieving a LOB field
|
||||
|
||||
// *** internal functions ***
|
||||
|
||||
|
@ -1520,9 +1520,9 @@ SQLPOINTER read_lob_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_in
|
|||
}
|
||||
|
||||
SQLLEN already_read = 0;
|
||||
SQLLEN to_read = INITIAL_FIELD_STRING_LEN;
|
||||
SQLLEN to_read = INITIAL_LOB_FIELD_LEN;
|
||||
sqlsrv_malloc_auto_ptr<char> buffer;
|
||||
buffer = static_cast<char*>( sqlsrv_malloc( INITIAL_FIELD_STRING_LEN + extra + sizeof( SQLULEN )));
|
||||
buffer = static_cast<char*>( sqlsrv_malloc( INITIAL_LOB_FIELD_LEN + extra + sizeof( SQLULEN )));
|
||||
SQLRETURN r = SQL_SUCCESS;
|
||||
SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ];
|
||||
SQLLEN last_field_len = 0;
|
||||
|
|
|
@ -1357,30 +1357,31 @@ struct sqlsrv_stmt : public sqlsrv_context {
|
|||
bool past_fetch_end; // Core_sqlsrv_fetch sets this field when the statement goes beyond the last row
|
||||
sqlsrv_result_set* current_results; // Current result set
|
||||
SQLULEN cursor_type; // Type of cursor for the current result set
|
||||
int fwd_row_index; // fwd_row_index is the current row index, SQL_CURSOR_FORWARD_ONLY
|
||||
int fwd_row_index; // fwd_row_index is the current row index, SQL_CURSOR_FORWARD_ONLY
|
||||
int curr_result_set; // the current active result set, 0 by default but will be incremented by core_sqlsrv_next_result
|
||||
bool has_rows; // Has_rows is set if there are actual rows in the row set
|
||||
bool fetch_called; // Used by core_sqlsrv_get_field to return an informative error if fetch not yet called
|
||||
int last_field_index; // last field retrieved by core_sqlsrv_get_field
|
||||
bool past_next_result_end; // core_sqlsrv_next_result sets this to true when the statement goes beyond the
|
||||
// last results
|
||||
unsigned long query_timeout; // maximum allowed statement execution time
|
||||
zend_long buffered_query_limit; // maximum allowed memory for a buffered query (measured in KB)
|
||||
zend_long buffered_query_limit; // maximum allowed memory for a buffered query (measured in KB)
|
||||
|
||||
// holds output pointers for SQLBindParameter
|
||||
// We use a deque because it 1) provides the at/[] access in constant time, and 2) grows dynamically without moving
|
||||
// memory, which is important because we pass the pointer to an element of the deque to SQLBindParameter to hold
|
||||
std::deque<SQLLEN> param_ind_ptrs; // output pointers for lengths for calls to SQLBindParameter
|
||||
zval param_input_strings; // hold all UTF-16 input strings that aren't managed by PHP
|
||||
zval output_params; // hold all the output parameters
|
||||
zval param_streams; // track which streams to send data to the server
|
||||
zval param_datetime_buffers; // datetime strings to be converted back to DateTime objects
|
||||
zval param_input_strings; // hold all UTF-16 input strings that aren't managed by PHP
|
||||
zval output_params; // hold all the output parameters
|
||||
zval param_streams; // track which streams to send data to the server
|
||||
zval param_datetime_buffers; // datetime strings to be converted back to DateTime objects
|
||||
bool send_streams_at_exec; // send all stream data right after execution before returning
|
||||
sqlsrv_stream current_stream; // current stream sending data to the server as an input parameter
|
||||
unsigned int current_stream_read; // # of bytes read so far. (if we read an empty PHP stream, we send an empty string
|
||||
// to the server)
|
||||
zval field_cache; // cache for a single row of fields, to allow multiple and out of order retrievals
|
||||
zval col_cache; // Used by get_field_as_string not to call SQLColAttribute() after every fetch.
|
||||
zval active_stream; // the currently active stream reading data from the database
|
||||
zval field_cache; // cache for a single row of fields, to allow multiple and out of order retrievals
|
||||
zval col_cache; // Used by get_field_as_string not to call SQLColAttribute() after every fetch.
|
||||
zval active_stream; // the currently active stream reading data from the database
|
||||
|
||||
sqlsrv_stmt( _In_ sqlsrv_conn* c, _In_ SQLHANDLE handle, _In_ error_callback e, _In_opt_ void* drv TSRMLS_DC );
|
||||
virtual ~sqlsrv_stmt( void );
|
||||
|
|
|
@ -60,7 +60,8 @@ struct col_cache {
|
|||
}
|
||||
};
|
||||
|
||||
const int INITIAL_FIELD_STRING_LEN = 256; // base allocation size when retrieving a string field
|
||||
const int INITIAL_FIELD_STRING_LEN = 2048; // base allocation size when retrieving a string field
|
||||
const int INITIAL_AE_FIELD_STRING_LEN = 8000; // base allocation size when retrieving a string field when AE is enabled
|
||||
|
||||
// UTF-8 tags for byte length of characters, used by streams to make sure we don't clip a character in between reads
|
||||
const unsigned int UTF8_MIDBYTE_MASK = 0xc0;
|
||||
|
@ -135,6 +136,7 @@ sqlsrv_stmt::sqlsrv_stmt( _In_ sqlsrv_conn* c, _In_ SQLHANDLE handle, _In_ error
|
|||
current_results( NULL ),
|
||||
cursor_type( SQL_CURSOR_FORWARD_ONLY ),
|
||||
fwd_row_index( -1 ),
|
||||
curr_result_set( 0 ),
|
||||
has_rows( false ),
|
||||
fetch_called( false ),
|
||||
last_field_index( -1 ),
|
||||
|
@ -1138,9 +1140,13 @@ void core_sqlsrv_next_result( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC, _In_ bool fin
|
|||
|
||||
// mark we are past the end of all results
|
||||
stmt->past_next_result_end = true;
|
||||
|
||||
// reset the current active result set
|
||||
stmt->curr_result_set = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
stmt->curr_result_set++;
|
||||
stmt->new_result_set( TSRMLS_C );
|
||||
}
|
||||
catch( core::CoreException& e ) {
|
||||
|
@ -2236,6 +2242,7 @@ void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_ind
|
|||
SQLLEN field_len_temp = 0;
|
||||
SQLLEN sql_display_size = 0;
|
||||
char* field_value_temp = NULL;
|
||||
unsigned int intial_field_len = INITIAL_FIELD_STRING_LEN;
|
||||
|
||||
try {
|
||||
|
||||
|
@ -2262,6 +2269,11 @@ void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_ind
|
|||
break;
|
||||
}
|
||||
|
||||
if( stmt->conn->ce_option.enabled ) {
|
||||
// when AE is enabled, increase the intial field len
|
||||
intial_field_len = INITIAL_AE_FIELD_STRING_LEN;
|
||||
}
|
||||
|
||||
col_cache* cached = NULL;
|
||||
if ( NULL != ( cached = static_cast< col_cache* >( zend_hash_index_find_ptr( Z_ARRVAL( stmt->col_cache ), static_cast< zend_ulong >( field_index ))))) {
|
||||
sql_field_type = cached->sql_type;
|
||||
|
@ -2282,7 +2294,7 @@ void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_ind
|
|||
if( sql_display_size == 0 || sql_display_size == INT_MAX ||
|
||||
sql_display_size == INT_MAX >> 1 || sql_display_size == UINT_MAX - 1 ) {
|
||||
|
||||
field_len_temp = INITIAL_FIELD_STRING_LEN;
|
||||
field_len_temp = intial_field_len;
|
||||
|
||||
SQLLEN initiallen = field_len_temp + extra;
|
||||
|
||||
|
@ -2323,7 +2335,7 @@ void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_ind
|
|||
if( field_len_temp == SQL_NO_TOTAL ) {
|
||||
|
||||
// reset the field_len_temp
|
||||
field_len_temp = INITIAL_FIELD_STRING_LEN;
|
||||
field_len_temp = intial_field_len;
|
||||
|
||||
do {
|
||||
SQLLEN initial_field_len = field_len_temp;
|
||||
|
@ -2378,14 +2390,14 @@ void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_ind
|
|||
&dummy_field_len, false /*handle_warning*/ TSRMLS_CC );
|
||||
}
|
||||
else {
|
||||
// We have already recieved INITIAL_FIELD_STRING_LEN size data.
|
||||
field_len_temp -= INITIAL_FIELD_STRING_LEN;
|
||||
// We have already recieved intial_field_len size data.
|
||||
field_len_temp -= intial_field_len;
|
||||
|
||||
// Get the rest of the data.
|
||||
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp + INITIAL_FIELD_STRING_LEN,
|
||||
r = stmt->current_results->get_data( field_index + 1, c_type, field_value_temp + intial_field_len,
|
||||
field_len_temp + extra, &dummy_field_len,
|
||||
true /*handle_warning*/ TSRMLS_CC );
|
||||
field_len_temp += INITIAL_FIELD_STRING_LEN;
|
||||
field_len_temp += intial_field_len;
|
||||
}
|
||||
|
||||
if( dummy_field_len == SQL_NULL_DATA ) {
|
||||
|
@ -2655,6 +2667,12 @@ bool reset_ae_stream_cursor( _Inout_ sqlsrv_stmt* stmt ) {
|
|||
// close and reopen the cursor
|
||||
core::SQLCloseCursor(stmt->current_results->odbc);
|
||||
core::SQLExecute(stmt);
|
||||
|
||||
// advance to the previous active result set
|
||||
for (int j = 0; j < stmt->curr_result_set; j++) {
|
||||
core::SQLMoreResults(stmt);
|
||||
}
|
||||
|
||||
// FETCH_NEXT until the cursor reaches the row that it was at
|
||||
for (int i = 0; i <= stmt->fwd_row_index; i++) {
|
||||
core::SQLFetchScroll(stmt->current_results->odbc, SQL_FETCH_NEXT, 0);
|
||||
|
|
170
test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt
Normal file
170
test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt
Normal file
|
@ -0,0 +1,170 @@
|
|||
--TEST--
|
||||
GitHub issue 574 - Fetch Next Result Test
|
||||
--DESCRIPTION--
|
||||
Verifies the functionality of PDOStatement nextRowset
|
||||
--ENV--
|
||||
PHPT_EXEC=true
|
||||
--SKIPIF--
|
||||
<?php require('skipif_mid-refactor.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once("MsCommon_mid-refactor.inc");
|
||||
|
||||
try {
|
||||
$conn = connect();
|
||||
$tableName = 'test574';
|
||||
$tableName1 = 'test574_1';
|
||||
|
||||
// create two tables with max fields
|
||||
$columns = array(new ColumnMeta('varchar(max)', 'col1'));
|
||||
createTable($conn, $tableName, $columns);
|
||||
|
||||
$columns = array(new ColumnMeta('varchar(max)', 'col1'));
|
||||
createTable($conn, $tableName1, $columns);
|
||||
|
||||
// insert one row to each table
|
||||
$phrase = str_repeat('This is a test ', 25000);
|
||||
$stmt = insertRow($conn, $tableName, array('col1' => $phrase));
|
||||
unset($stmt);
|
||||
|
||||
$phrase1 = str_repeat('This is indeed very long ', 30000);
|
||||
$stmt = insertRow($conn, $tableName1, array('col1' => $phrase1));
|
||||
unset($stmt);
|
||||
|
||||
// run queries in a batch
|
||||
$stmt = $conn->prepare("SELECT * FROM [$tableName]; SELECT artist FROM [cd_info]; SELECT * FROM [$tableName1]");
|
||||
$stmt->execute();
|
||||
|
||||
// fetch from $tableName
|
||||
$row = $stmt->fetch(PDO::FETCH_NUM);
|
||||
if ($row) {
|
||||
if ($row[0] === $phrase) {
|
||||
echo(substr($row[0], 0, 15)) . PHP_EOL;
|
||||
} else {
|
||||
echo "Incorrect value substr($row[0], 0, 1000)...!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// fetch from cd_info
|
||||
echo "1. next result? ";
|
||||
$next = $stmt->nextRowset();
|
||||
var_dump($next);
|
||||
|
||||
$row = $stmt->fetch(PDO::FETCH_NUM);
|
||||
if ($row) {
|
||||
echo $row[0] . PHP_EOL;
|
||||
}
|
||||
|
||||
// fetch from $tableName1
|
||||
echo "2. next result? ";
|
||||
$next = $stmt->nextRowset();
|
||||
var_dump($next);
|
||||
|
||||
$row = $stmt->fetch(PDO::FETCH_NUM);
|
||||
if ($row) {
|
||||
if ($row[0] === $phrase1) {
|
||||
echo(substr($row[0], 0, 25)) . PHP_EOL;
|
||||
} else {
|
||||
echo "Incorrect value substr($row[0], 0, 1000)...!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// should be no more next results, first returns false second throws an exception
|
||||
echo "3. next result? ";
|
||||
$next = $stmt->nextRowset();
|
||||
var_dump($next);
|
||||
|
||||
$row = $stmt->fetch(PDO::FETCH_NUM);
|
||||
if ($row) {
|
||||
fatalError("This is unexpected!\n");
|
||||
}
|
||||
|
||||
echo "4. next result? " . PHP_EOL;
|
||||
try {
|
||||
$next = $stmt->nextRowset();
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
// run queries in a batch again, different order this time
|
||||
$stmt = $conn->prepare("SELECT * FROM [$tableName1]; SELECT * FROM [$tableName]; SELECT artist FROM [cd_info]");
|
||||
$stmt->execute();
|
||||
|
||||
// skip the first two queries
|
||||
$stmt->nextRowset();
|
||||
$stmt->nextRowset();
|
||||
|
||||
// fetch from cd_info
|
||||
$row = $stmt->fetch(PDO::FETCH_NUM);
|
||||
if ($row) {
|
||||
echo $row[0] . PHP_EOL;
|
||||
}
|
||||
|
||||
// re-execute the statement, should return to the first query in the batch
|
||||
$stmt->execute();
|
||||
|
||||
// fetch from $tableName1
|
||||
$row = $stmt->fetch(PDO::FETCH_NUM);
|
||||
if ($row) {
|
||||
if ($row[0] === $phrase1) {
|
||||
echo(substr($row[0], 0, 25)) . PHP_EOL;
|
||||
} else {
|
||||
echo "Incorrect value substr($row[0], 0, 1000)...!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
unset($stmt);
|
||||
|
||||
// execute a simple query, no more batch
|
||||
$stmt = $conn->query("SELECT * FROM [$tableName]");
|
||||
|
||||
// fetch from $tableName
|
||||
$row = $stmt->fetch(PDO::FETCH_NUM);
|
||||
if ($row) {
|
||||
if ($row[0] === $phrase) {
|
||||
echo(substr($row[0], 0, 15)) . PHP_EOL;
|
||||
} else {
|
||||
echo "Incorrect value substr($row[0], 0, 1000)...!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// should be no more next results, first returns false second throws an exception
|
||||
echo "5. next result? ";
|
||||
$next = $stmt->nextRowset();
|
||||
var_dump($next);
|
||||
|
||||
echo "6. next result? " . PHP_EOL;
|
||||
try {
|
||||
$next = $stmt->nextRowset();
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage() . PHP_EOL;
|
||||
}
|
||||
|
||||
dropTable($conn, $tableName);
|
||||
dropTable($conn, $tableName1);
|
||||
|
||||
unset($stmt);
|
||||
unset($conn);
|
||||
|
||||
echo "Done\n";
|
||||
} catch (PDOException $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
?>
|
||||
|
||||
--EXPECT--
|
||||
This is a test
|
||||
1. next result? bool(true)
|
||||
Led Zeppelin
|
||||
2. next result? bool(true)
|
||||
This is indeed very long
|
||||
3. next result? bool(false)
|
||||
4. next result?
|
||||
SQLSTATE[IMSSP]: There are no more results returned by the query.
|
||||
Led Zeppelin
|
||||
This is indeed very long
|
||||
This is a test
|
||||
5. next result? bool(false)
|
||||
6. next result?
|
||||
SQLSTATE[IMSSP]: There are no more results returned by the query.
|
||||
Done
|
202
test/functional/sqlsrv/sqlsrv_574_next_result.phpt
Normal file
202
test/functional/sqlsrv/sqlsrv_574_next_result.phpt
Normal file
|
@ -0,0 +1,202 @@
|
|||
--TEST--
|
||||
GitHub issue 574 - Fetch Next Result Test
|
||||
--DESCRIPTION--
|
||||
Verifies the functionality of sqlsrv_next_result
|
||||
--ENV--
|
||||
PHPT_EXEC=true
|
||||
--SKIPIF--
|
||||
<?php require('skipif_versions_old.inc'); ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once('MsCommon.inc');
|
||||
|
||||
$conn = AE\connect();
|
||||
$tableName = 'test574';
|
||||
$tableName1 = 'test574_1';
|
||||
|
||||
// create two tables with max fields
|
||||
$columns = array(new AE\ColumnMeta('varchar(max)', 'col1'));
|
||||
$stmt = AE\createTable($conn, $tableName, $columns);
|
||||
if (!$stmt) {
|
||||
fatalError("Failed to create table for the test\n");
|
||||
}
|
||||
|
||||
$columns = array(new AE\ColumnMeta('varchar(max)', 'col1'));
|
||||
$stmt = AE\createTable($conn, $tableName1, $columns);
|
||||
if (!$stmt) {
|
||||
fatalError("Failed to create table for the test\n");
|
||||
}
|
||||
|
||||
// insert one row to each table
|
||||
$sql = "insert into $tableName (col1) VALUES (?)";
|
||||
$phrase = str_repeat('This is a test ', 25000);
|
||||
|
||||
$stmt = sqlsrv_prepare($conn, $sql, array($phrase));
|
||||
if ($stmt) {
|
||||
$r = sqlsrv_execute($stmt);
|
||||
if (!$r) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
|
||||
$phrase1 = str_repeat('This is indeed very long ', 30000);
|
||||
$sql = "insert into $tableName1 (col1) VALUES (?)";
|
||||
$stmt = sqlsrv_prepare($conn, $sql, array($phrase1));
|
||||
if ($stmt) {
|
||||
$r = sqlsrv_execute($stmt);
|
||||
if (!$r) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
|
||||
// run queries in a batch
|
||||
$stmt = sqlsrv_prepare($conn, "SELECT * FROM [$tableName]; SELECT artist FROM [cd_info]; SELECT * FROM [$tableName1]");
|
||||
if ($stmt) {
|
||||
$r = sqlsrv_execute($stmt);
|
||||
if (!$r) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
|
||||
// fetch from $tableName
|
||||
$row = sqlsrv_fetch($stmt);
|
||||
if ($row) {
|
||||
$fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
|
||||
if ($fld === $phrase) {
|
||||
echo(substr($fld, 0, 15)) . PHP_EOL;
|
||||
} else {
|
||||
echo "Incorrect value substr($fld, 0, 1000)...!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// fetch from cd_info
|
||||
echo "1. next result? ";
|
||||
$next = sqlsrv_next_result($stmt);
|
||||
var_dump($next);
|
||||
|
||||
$row = sqlsrv_fetch($stmt);
|
||||
if ($row) {
|
||||
$fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
|
||||
echo $fld . PHP_EOL;
|
||||
}
|
||||
|
||||
// fetch from $tableName1
|
||||
echo "2. next result? ";
|
||||
$next = sqlsrv_next_result($stmt);
|
||||
var_dump($next);
|
||||
|
||||
$row = sqlsrv_fetch($stmt);
|
||||
if ($row) {
|
||||
$fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
|
||||
if ($fld === $phrase1) {
|
||||
echo(substr($fld, 0, 25)) . PHP_EOL;
|
||||
} else {
|
||||
echo "Incorrect value substr($fld, 0, 1000)...!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// should be no more next results, first returns NULL second returns false
|
||||
echo "3. next result? ";
|
||||
$next = sqlsrv_next_result($stmt);
|
||||
var_dump($next);
|
||||
|
||||
$row = sqlsrv_fetch($stmt);
|
||||
if ($row) {
|
||||
fatalError("This is unexpected!\n");
|
||||
}
|
||||
|
||||
echo "4. next result? ";
|
||||
$next = sqlsrv_next_result($stmt);
|
||||
var_dump($next);
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
// run queries in a batch again, different order this time
|
||||
$stmt = sqlsrv_prepare($conn, "SELECT * FROM [$tableName1]; SELECT * FROM [$tableName]; SELECT artist FROM [cd_info]");
|
||||
if ($stmt) {
|
||||
$r = sqlsrv_execute($stmt);
|
||||
if (!$r) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
// skip the first two queries
|
||||
sqlsrv_next_result($stmt);
|
||||
sqlsrv_next_result($stmt);
|
||||
|
||||
// fetch from cd_info
|
||||
$row = sqlsrv_fetch($stmt);
|
||||
if ($row) {
|
||||
$fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
|
||||
echo $fld . PHP_EOL;
|
||||
}
|
||||
|
||||
// re-execute the statement, should return to the first query in the batch
|
||||
$r = sqlsrv_execute($stmt);
|
||||
if (!$r) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
|
||||
// fetch from $tableName1
|
||||
$row = sqlsrv_fetch($stmt);
|
||||
if ($row) {
|
||||
$fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
|
||||
if ($fld === $phrase1) {
|
||||
echo(substr($fld, 0, 25)) . PHP_EOL;
|
||||
} else {
|
||||
echo "Incorrect value substr($fld, 0, 1000)...!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
sqlsrv_free_stmt($stmt);
|
||||
|
||||
// execute a simple query, no more batch
|
||||
$stmt = sqlsrv_prepare($conn, "SELECT * FROM [$tableName]");
|
||||
if ($stmt) {
|
||||
$r = sqlsrv_execute($stmt);
|
||||
if (!$r) {
|
||||
print_r(sqlsrv_errors());
|
||||
}
|
||||
}
|
||||
|
||||
// fetch from $tableName
|
||||
$row = sqlsrv_fetch($stmt);
|
||||
if ($row) {
|
||||
$fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR));
|
||||
if ($fld === $phrase) {
|
||||
echo(substr($fld, 0, 15)) . PHP_EOL;
|
||||
} else {
|
||||
echo "Incorrect value substr($fld, 0, 1000)...!" . PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
// should be no more next results, first returns NULL second returns false
|
||||
echo "5. next result? ";
|
||||
$next = sqlsrv_next_result($stmt);
|
||||
var_dump($next);
|
||||
|
||||
echo "6. next result? ";
|
||||
$next = sqlsrv_next_result($stmt);
|
||||
var_dump($next);
|
||||
|
||||
dropTable($conn, $tableName);
|
||||
dropTable($conn, $tableName1);
|
||||
|
||||
sqlsrv_free_stmt($stmt);
|
||||
sqlsrv_close($conn);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
|
||||
--EXPECT--
|
||||
This is a test
|
||||
1. next result? bool(true)
|
||||
Led Zeppelin
|
||||
2. next result? bool(true)
|
||||
This is indeed very long
|
||||
3. next result? NULL
|
||||
4. next result? bool(false)
|
||||
Led Zeppelin
|
||||
This is indeed very long
|
||||
This is a test
|
||||
5. next result? NULL
|
||||
6. next result? bool(false)
|
||||
Done
|
Loading…
Reference in a new issue