@@ -124,7 +124,6 @@ void send_param_streams( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC );
124
124
void sqlsrv_output_param_dtor ( _Inout_ zval* data );
125
125
// called when a bound stream parameter is to be destroyed.
126
126
void sqlsrv_stream_dtor ( _Inout_ zval* data );
127
- bool is_streamable_type ( _In_ SQLINTEGER sql_type );
128
127
129
128
}
130
129
@@ -997,22 +996,24 @@ void core_sqlsrv_get_field( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
997
996
efree ( field_value );
998
997
field_value = NULL ;
999
998
*field_len = 0 ;
1000
- }
1001
- }
1002
- }
1003
-
1004
- // If the php type was not specified set the php type to be the default type.
1005
- if ( sqlsrv_php_type.typeinfo .type == SQLSRV_PHPTYPE_INVALID ) {
1006
-
1007
- // Get the SQL type of the field.
1008
- core::SQLColAttributeW ( stmt, field_index + 1 , SQL_DESC_CONCISE_TYPE, NULL , 0 , NULL , &sql_field_type TSRMLS_CC );
999
+ }
1000
+ }
1001
+ }
1009
1002
1010
- // Get the length of the field.
1011
- core::SQLColAttributeW ( stmt, field_index + 1 , SQL_DESC_LENGTH, NULL , 0 , NULL , &sql_field_len TSRMLS_CC );
1003
+ // If the php type was not specified set the php type to be the default type.
1004
+ if (sqlsrv_php_type.typeinfo .type == SQLSRV_PHPTYPE_INVALID) {
1005
+ SQLSRV_ASSERT (stmt->current_meta_data .size () > field_index, " core_sqlsrv_get_field - meta data vector not in sync" );
1006
+ sql_field_type = stmt->current_meta_data [field_index]->field_type ;
1007
+ if (stmt->current_meta_data [field_index]->field_precision > 0 ) {
1008
+ sql_field_len = stmt->current_meta_data [field_index]->field_precision ;
1009
+ }
1010
+ else {
1011
+ sql_field_len = stmt->current_meta_data [field_index]->field_size ;
1012
+ }
1012
1013
1013
- // Get the corresponding php type from the sql type.
1014
- sqlsrv_php_type = stmt->sql_type_to_php_type ( static_cast <SQLINTEGER>( sql_field_type ), static_cast <SQLUINTEGER>( sql_field_len ), prefer_string );
1015
- }
1014
+ // Get the corresponding php type from the sql type.
1015
+ sqlsrv_php_type = stmt->sql_type_to_php_type (static_cast <SQLINTEGER>(sql_field_type), static_cast <SQLUINTEGER>(sql_field_len), prefer_string);
1016
+ }
1016
1017
1017
1018
// Verify that we have an acceptable type to convert.
1018
1019
CHECK_CUSTOM_ERROR ( !is_valid_sqlsrv_phptype ( sqlsrv_php_type ), stmt, SQLSRV_ERROR_INVALID_TYPE ) {
@@ -1441,7 +1442,7 @@ void close_active_stream( _Inout_ sqlsrv_stmt* stmt TSRMLS_DC )
1441
1442
1442
1443
namespace {
1443
1444
1444
- bool is_streamable_type ( _In_ SQLLEN sql_type )
1445
+ bool is_streamable_type ( _In_ SQLSMALLINT sql_type )
1445
1446
{
1446
1447
switch ( sql_type ) {
1447
1448
case SQL_CHAR:
@@ -1460,6 +1461,25 @@ bool is_streamable_type( _In_ SQLLEN sql_type )
1460
1461
return false ;
1461
1462
}
1462
1463
1464
+ bool is_a_numeric_type (_In_ SQLSMALLINT sql_type)
1465
+ {
1466
+ switch (sql_type) {
1467
+ case SQL_BIGINT:
1468
+ case SQL_BIT:
1469
+ case SQL_INTEGER:
1470
+ case SQL_SMALLINT:
1471
+ case SQL_TINYINT:
1472
+ case SQL_FLOAT:
1473
+ case SQL_DOUBLE:
1474
+ case SQL_REAL:
1475
+ case SQL_DECIMAL:
1476
+ case SQL_NUMERIC:
1477
+ return true ;
1478
+ }
1479
+
1480
+ return false ;
1481
+ }
1482
+
1463
1483
void calc_string_size ( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_index, _In_ SQLLEN sql_type, _Inout_ SQLLEN& size TSRMLS_DC )
1464
1484
{
1465
1485
try {
@@ -1693,12 +1713,10 @@ void core_get_field_common( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_i
1693
1713
{
1694
1714
php_stream* stream = NULL ;
1695
1715
sqlsrv_stream* ss = NULL ;
1696
- SQLLEN sql_type;
1716
+ SQLSMALLINT sql_type;
1697
1717
1698
- SQLRETURN r = SQLColAttributeW ( stmt->handle (), field_index + 1 , SQL_DESC_TYPE, NULL , 0 , NULL , &sql_type );
1699
- CHECK_SQL_ERROR_OR_WARNING ( r, stmt ) {
1700
- throw core::CoreException ();
1701
- }
1718
+ SQLSRV_ASSERT (stmt->current_meta_data .size () > field_index, " core_get_field_common - meta data vector not in sync" );
1719
+ sql_type = stmt->current_meta_data [field_index]->field_type ;
1702
1720
1703
1721
CHECK_CUSTOM_ERROR ( !is_streamable_type ( sql_type ), stmt, SQLSRV_ERROR_STREAMABLE_TYPES_ONLY ) {
1704
1722
throw core::CoreException ();
@@ -2208,9 +2226,30 @@ void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_ind
2208
2226
DEBUG_SQLSRV_ASSERT ( sqlsrv_php_type.typeinfo .type == SQLSRV_PHPTYPE_STRING,
2209
2227
" Type should be SQLSRV_PHPTYPE_STRING in get_field_as_string" );
2210
2228
2229
+ col_cache* cached = NULL ;
2230
+ if ( NULL != ( cached = static_cast < col_cache* >( zend_hash_index_find_ptr ( Z_ARRVAL ( stmt->col_cache ), static_cast < zend_ulong >( field_index ))))) {
2231
+ sql_field_type = cached->sql_type ;
2232
+ sql_display_size = cached->display_size ;
2233
+ }
2234
+ else {
2235
+ SQLSRV_ASSERT (stmt->current_meta_data .size () > field_index, " get_field_as_string - meta data vector not in sync" );
2236
+ sql_field_type = stmt->current_meta_data [field_index]->field_type ;
2237
+
2238
+ // Calculate the field size.
2239
+ calc_string_size ( stmt, field_index, sql_field_type, sql_display_size TSRMLS_CC );
2240
+
2241
+ col_cache cache ( sql_field_type, sql_display_size );
2242
+ core::sqlsrv_zend_hash_index_update_mem ( *stmt, Z_ARRVAL ( stmt->col_cache ), field_index, &cache, sizeof ( col_cache ) TSRMLS_CC );
2243
+ }
2244
+
2245
+ // Determine the correct encoding
2211
2246
if ( sqlsrv_php_type.typeinfo .encoding == SQLSRV_ENCODING_DEFAULT ) {
2212
2247
sqlsrv_php_type.typeinfo .encoding = stmt->conn ->encoding ();
2213
2248
}
2249
+ // For numbers, no need to convert
2250
+ if (is_a_numeric_type (sql_field_type)) {
2251
+ sqlsrv_php_type.typeinfo .encoding = SQLSRV_ENCODING_CHAR;
2252
+ }
2214
2253
2215
2254
// Set the C type and account for null characters at the end of the data.
2216
2255
switch ( sqlsrv_php_type.typeinfo .encoding ) {
@@ -2228,22 +2267,6 @@ void get_field_as_string( _Inout_ sqlsrv_stmt* stmt, _In_ SQLUSMALLINT field_ind
2228
2267
break ;
2229
2268
}
2230
2269
2231
- col_cache* cached = NULL ;
2232
- if ( NULL != ( cached = static_cast < col_cache* >( zend_hash_index_find_ptr ( Z_ARRVAL ( stmt->col_cache ), static_cast < zend_ulong >( field_index ))))) {
2233
- sql_field_type = cached->sql_type ;
2234
- sql_display_size = cached->display_size ;
2235
- }
2236
- else {
2237
- // Get the SQL type of the field. unixODBC 2.3.1 requires wide calls to support pooling
2238
- core::SQLColAttributeW ( stmt, field_index + 1 , SQL_DESC_CONCISE_TYPE, NULL , 0 , NULL , &sql_field_type TSRMLS_CC );
2239
-
2240
- // Calculate the field size.
2241
- calc_string_size ( stmt, field_index, sql_field_type, sql_display_size TSRMLS_CC );
2242
-
2243
- col_cache cache ( sql_field_type, sql_display_size );
2244
- core::sqlsrv_zend_hash_index_update_mem ( *stmt, Z_ARRVAL ( stmt->col_cache ), field_index, &cache, sizeof ( col_cache ) TSRMLS_CC );
2245
- }
2246
-
2247
2270
// if this is a large type, then read the first few bytes to get the actual length from SQLGetData
2248
2271
if ( sql_display_size == 0 || sql_display_size == INT_MAX ||
2249
2272
sql_display_size == INT_MAX >> 1 || sql_display_size == UINT_MAX - 1 ) {
0 commit comments