From 52b612ece8295b458c80bea43417daf05b40899b Mon Sep 17 00:00:00 2001 From: Jenny Tam Date: Thu, 9 Nov 2017 15:24:08 -0800 Subject: [PATCH 1/3] Fix to GitHub issue 574 --- source/shared/core_results.cpp | 2 +- source/shared/core_sqlsrv.h | 19 +- source/shared/core_stmt.cpp | 11 ++ .../pdo_sqlsrv/pdo_574_next_rowset.phpt | 154 +++++++++++++++ .../sqlsrv/sqlsrv_574_next_result.phpt | 186 ++++++++++++++++++ 5 files changed, 362 insertions(+), 10 deletions(-) create mode 100644 test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt create mode 100644 test/functional/sqlsrv/sqlsrv_574_next_result.phpt diff --git a/source/shared/core_results.cpp b/source/shared/core_results.cpp index 34e5b708..a1ec6039 100644 --- a/source/shared/core_results.cpp +++ b/source/shared/core_results.cpp @@ -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_FIELD_STRING_LEN = 1024; // base allocation size when retrieving a string field // *** internal functions *** diff --git a/source/shared/core_sqlsrv.h b/source/shared/core_sqlsrv.h index bad4b538..1bc680cd 100644 --- a/source/shared/core_sqlsrv.h +++ b/source/shared/core_sqlsrv.h @@ -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 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 ); diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index bf268d8b..e5812f99 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -135,6 +135,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 +1139,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 ) { @@ -2655,6 +2660,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); diff --git a/test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt b/test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt new file mode 100644 index 00000000..896a77ab --- /dev/null +++ b/test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt @@ -0,0 +1,154 @@ +--TEST-- +GitHub issue 574 - Fetch Next Result Test +--DESCRIPTION-- +Verifies the functionality of PDOStatement nextRowset +--ENV-- +PHPT_EXEC=true +--SKIPIF-- + +--FILE-- + $phrase)); + unset($stmt); + + $phrase = str_repeat('This is indeed very long ', 300); + $stmt = insertRow($conn, $tableName1, array('col1' => $phrase)); + 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) { + echo(substr($row[0], 0, 15)) . 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(substr($row[0], 0, 15)) . PHP_EOL; + } + + // fetch from $tableName1 + echo "2. next result? "; + $next = $stmt->nextRowset(); + var_dump($next); + + $row = $stmt->fetch(PDO::FETCH_NUM); + if ($row) { + echo(substr($row[0], 0, 25)) . 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(substr($row[0], 0, 15)) . 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) { + echo(substr($row[0], 0, 25)) . 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) { + echo(substr($row[0], 0, 15)) . 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 \ No newline at end of file diff --git a/test/functional/sqlsrv/sqlsrv_574_next_result.phpt b/test/functional/sqlsrv/sqlsrv_574_next_result.phpt new file mode 100644 index 00000000..99816369 --- /dev/null +++ b/test/functional/sqlsrv/sqlsrv_574_next_result.phpt @@ -0,0 +1,186 @@ +--TEST-- +GitHub issue 574 - Fetch Next Result Test +--DESCRIPTION-- +Verifies the functionality of sqlsrv_next_result +--ENV-- +PHPT_EXEC=true +--SKIPIF-- + +--FILE-- + + +--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 \ No newline at end of file From d633691b5bbfb109f0e47c19af43f341fdc1e0a3 Mon Sep 17 00:00:00 2001 From: Jenny Tam Date: Fri, 10 Nov 2017 15:04:07 -0800 Subject: [PATCH 2/3] Raised the initial buffer size and modified tests as per review --- source/shared/core_results.cpp | 2 +- .../pdo_sqlsrv/pdo_574_next_rowset.phpt | 34 ++++++++++++++----- .../sqlsrv/sqlsrv_574_next_result.phpt | 34 ++++++++++++++----- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/source/shared/core_results.cpp b/source/shared/core_results.cpp index a1ec6039..70b4a59e 100644 --- a/source/shared/core_results.cpp +++ b/source/shared/core_results.cpp @@ -45,7 +45,7 @@ namespace { // *** internal constants *** -const int INITIAL_FIELD_STRING_LEN = 1024; // base allocation size when retrieving a string field +const int INITIAL_FIELD_STRING_LEN = 8000; // base allocation size when retrieving a string field // *** internal functions *** diff --git a/test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt b/test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt index 896a77ab..d4c0e811 100644 --- a/test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt +++ b/test/functional/pdo_sqlsrv/pdo_574_next_rowset.phpt @@ -24,12 +24,12 @@ try { createTable($conn, $tableName1, $columns); // insert one row to each table - $phrase = str_repeat('This is a test ', 250); + $phrase = str_repeat('This is a test ', 25000); $stmt = insertRow($conn, $tableName, array('col1' => $phrase)); unset($stmt); - $phrase = str_repeat('This is indeed very long ', 300); - $stmt = insertRow($conn, $tableName1, array('col1' => $phrase)); + $phrase1 = str_repeat('This is indeed very long ', 30000); + $stmt = insertRow($conn, $tableName1, array('col1' => $phrase1)); unset($stmt); // run queries in a batch @@ -39,7 +39,11 @@ try { // fetch from $tableName $row = $stmt->fetch(PDO::FETCH_NUM); if ($row) { - echo(substr($row[0], 0, 15)) . PHP_EOL; + 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 @@ -49,7 +53,7 @@ try { $row = $stmt->fetch(PDO::FETCH_NUM); if ($row) { - echo(substr($row[0], 0, 15)) . PHP_EOL; + echo $row[0] . PHP_EOL; } // fetch from $tableName1 @@ -59,7 +63,11 @@ try { $row = $stmt->fetch(PDO::FETCH_NUM); if ($row) { - echo(substr($row[0], 0, 25)) . PHP_EOL; + 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 @@ -90,7 +98,7 @@ try { // fetch from cd_info $row = $stmt->fetch(PDO::FETCH_NUM); if ($row) { - echo(substr($row[0], 0, 15)) . PHP_EOL; + echo $row[0] . PHP_EOL; } // re-execute the statement, should return to the first query in the batch @@ -99,7 +107,11 @@ try { // fetch from $tableName1 $row = $stmt->fetch(PDO::FETCH_NUM); if ($row) { - echo(substr($row[0], 0, 25)) . PHP_EOL; + 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); @@ -109,7 +121,11 @@ try { // fetch from $tableName $row = $stmt->fetch(PDO::FETCH_NUM); if ($row) { - echo(substr($row[0], 0, 15)) . PHP_EOL; + 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 diff --git a/test/functional/sqlsrv/sqlsrv_574_next_result.phpt b/test/functional/sqlsrv/sqlsrv_574_next_result.phpt index 99816369..c21f7178 100644 --- a/test/functional/sqlsrv/sqlsrv_574_next_result.phpt +++ b/test/functional/sqlsrv/sqlsrv_574_next_result.phpt @@ -30,7 +30,7 @@ if (!$stmt) { // insert one row to each table $sql = "insert into $tableName (col1) VALUES (?)"; -$phrase = str_repeat('This is a test ', 250); +$phrase = str_repeat('This is a test ', 25000); $stmt = sqlsrv_prepare($conn, $sql, array($phrase)); if ($stmt) { @@ -40,9 +40,9 @@ if ($stmt) { } } -$phrase = str_repeat('This is indeed very long ', 300); +$phrase1 = str_repeat('This is indeed very long ', 30000); $sql = "insert into $tableName1 (col1) VALUES (?)"; -$stmt = sqlsrv_prepare($conn, $sql, array($phrase)); +$stmt = sqlsrv_prepare($conn, $sql, array($phrase1)); if ($stmt) { $r = sqlsrv_execute($stmt); if (!$r) { @@ -63,7 +63,11 @@ if ($stmt) { $row = sqlsrv_fetch($stmt); if ($row) { $fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)); - echo(substr($fld, 0, 15)) . PHP_EOL; + if ($fld === $phrase) { + echo(substr($fld, 0, 15)) . PHP_EOL; + } else { + echo "Incorrect value substr($fld, 0, 1000)...!" . PHP_EOL; + } } // fetch from cd_info @@ -74,7 +78,7 @@ var_dump($next); $row = sqlsrv_fetch($stmt); if ($row) { $fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)); - echo(substr($fld, 0, 15)) . PHP_EOL; + echo $fld . PHP_EOL; } // fetch from $tableName1 @@ -85,7 +89,11 @@ var_dump($next); $row = sqlsrv_fetch($stmt); if ($row) { $fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)); - echo(substr($fld, 0, 25)) . PHP_EOL; + 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 @@ -119,7 +127,7 @@ sqlsrv_next_result($stmt); $row = sqlsrv_fetch($stmt); if ($row) { $fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)); - echo(substr($fld, 0, 15)) . PHP_EOL; + echo $fld . PHP_EOL; } // re-execute the statement, should return to the first query in the batch @@ -132,7 +140,11 @@ if (!$r) { $row = sqlsrv_fetch($stmt); if ($row) { $fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)); - echo(substr($fld, 0, 25)) . PHP_EOL; + if ($fld === $phrase1) { + echo(substr($fld, 0, 25)) . PHP_EOL; + } else { + echo "Incorrect value substr($fld, 0, 1000)...!" . PHP_EOL; + } } sqlsrv_free_stmt($stmt); @@ -149,7 +161,11 @@ if ($stmt) { $row = sqlsrv_fetch($stmt); if ($row) { $fld = sqlsrv_get_field($stmt, 0, SQLSRV_PHPTYPE_STRING(SQLSRV_ENC_CHAR)); - echo(substr($fld, 0, 15)) . PHP_EOL; + 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 From 1a2459614e633fd7be5b08d4ceca6fc25220d3c8 Mon Sep 17 00:00:00 2001 From: Jenny Tam Date: Wed, 15 Nov 2017 11:00:56 -0800 Subject: [PATCH 3/3] Adjusted the initial length for string and LOB fields --- source/shared/core_results.cpp | 6 +++--- source/shared/core_stmt.cpp | 21 ++++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/source/shared/core_results.cpp b/source/shared/core_results.cpp index 70b4a59e..98ea7afa 100644 --- a/source/shared/core_results.cpp +++ b/source/shared/core_results.cpp @@ -45,7 +45,7 @@ namespace { // *** internal constants *** -const int INITIAL_FIELD_STRING_LEN = 8000; // 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 buffer; - buffer = static_cast( sqlsrv_malloc( INITIAL_FIELD_STRING_LEN + extra + sizeof( SQLULEN ))); + buffer = static_cast( sqlsrv_malloc( INITIAL_LOB_FIELD_LEN + extra + sizeof( SQLULEN ))); SQLRETURN r = SQL_SUCCESS; SQLCHAR state[ SQL_SQLSTATE_BUFSIZE ]; SQLLEN last_field_len = 0; diff --git a/source/shared/core_stmt.cpp b/source/shared/core_stmt.cpp index e5812f99..e47bca4d 100644 --- a/source/shared/core_stmt.cpp +++ b/source/shared/core_stmt.cpp @@ -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; @@ -2241,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 { @@ -2267,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; @@ -2287,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; @@ -2328,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; @@ -2383,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 ) {