ID:               16960
 Updated by:       [EMAIL PROTECTED]
 Reported By:      [EMAIL PROTECTED]
 Status:           Open
 Bug Type:         Feature/Change Request
 Operating System: All
 PHP Version:      4.0CVS-2002-05-02
 New Comment:

OK, more to come. The following patch solves the issues of corrupt
objects, a missing function sybase_fetch_assoc() function and the loss
of fields with similar names while including my previous patch.

* Corrupt objects
  sybase_fetch_object() returns object with numeric member
  variables, which cannot be accessed, e.g.
  object() {
    0     => 'bar',
    'foo' => 'bar'
  }
  $obj->0 will fail.

* Identical fieldnames
  Joining over 2 or more tables and selecting fields with
  the same fieldname, you will lose information using the
  string keys:
  select a.lastchange, b.lastchange [...]
  
  array() {
    0            => 'May 02 2002 05:49PM',
    'lastchange' => 'May 02 2002 05:49PM',
    1            => 'Apr 03 2002 12:22PM'
  }

  Patch returns this using sybase_fetch_assoc():
  array() {
    'lastchange' => 'May 02 2002 05:49PM',
    'lastchange1'=> 'Apr 03 2002 12:22PM'
  )

No BC issues on this, AFAIS.

[patch-ext_sybase_ct_php_sybase_ct.c]
--- php4-200205012100/ext/sybase_ct/php_sybase_ct.c     Tue Mar 12 21:34:06
2002
+++ __build__/ext/sybase_ct/php_sybase_ct.c     Thu May  2 17:39:46 2002
@@ -48,6 +48,7 @@
        PHP_FE(sybase_num_fields,                       NULL)
        PHP_FE(sybase_fetch_row,                        NULL)
        PHP_FE(sybase_fetch_array,                      NULL)
+        PHP_FE(sybase_fetch_assoc,                     NULL)
        PHP_FE(sybase_fetch_object,                     NULL)
        PHP_FE(sybase_data_seek,                        NULL)
        PHP_FE(sybase_fetch_field,                      NULL)
@@ -57,22 +58,23 @@
        PHP_FE(sybase_min_client_severity,      NULL)
        PHP_FE(sybase_min_server_severity,      NULL)
 
-       PHP_FALIAS(mssql_connect,                       sybase_connect,                
 NULL)
-       PHP_FALIAS(mssql_pconnect,                      sybase_pconnect,               
 NULL)
-       PHP_FALIAS(mssql_close,                         sybase_close,                  
 NULL)
-       PHP_FALIAS(mssql_select_db,                     sybase_select_db,              
 NULL)
-       PHP_FALIAS(mssql_query,                         sybase_query,                  
 NULL)
+       PHP_FALIAS(mssql_connect,               sybase_connect,                 NULL)
+       PHP_FALIAS(mssql_pconnect,              sybase_pconnect,                NULL)
+       PHP_FALIAS(mssql_close,                 sybase_close,                   NULL)
+       PHP_FALIAS(mssql_select_db,             sybase_select_db,               NULL)
+       PHP_FALIAS(mssql_query,                 sybase_query,                   NULL)
        PHP_FALIAS(mssql_free_result,           sybase_free_result,             NULL)
        PHP_FALIAS(mssql_get_last_message,      sybase_get_last_message,NULL)
-       PHP_FALIAS(mssql_num_rows,                      sybase_num_rows,               
 NULL)
+       PHP_FALIAS(mssql_num_rows,              sybase_num_rows,                NULL)
        PHP_FALIAS(mssql_num_fields,            sybase_num_fields,              NULL)
-       PHP_FALIAS(mssql_fetch_row,                     sybase_fetch_row,              
 NULL)
+       PHP_FALIAS(mssql_fetch_row,             sybase_fetch_row,               NULL)
        PHP_FALIAS(mssql_fetch_array,           sybase_fetch_array,             NULL)
+        PHP_FALIAS(mssql_fetch_assoc,          sybase_fetch_assoc,             NULL)
        PHP_FALIAS(mssql_fetch_object,          sybase_fetch_object,    NULL)
-       PHP_FALIAS(mssql_data_seek,                     sybase_data_seek,              
 NULL)
+       PHP_FALIAS(mssql_data_seek,             sybase_data_seek,               NULL)
        PHP_FALIAS(mssql_fetch_field,           sybase_fetch_field,             NULL)
        PHP_FALIAS(mssql_field_seek,            sybase_field_seek,              NULL)
-       PHP_FALIAS(mssql_result,                        sybase_result,                 
 NULL)
+       PHP_FALIAS(mssql_result,                sybase_result,                  NULL)
        PHP_FALIAS(mssql_affected_rows,         sybase_affected_rows,   NULL)

        PHP_FALIAS(mssql_min_client_severity,   sybase_min_client_severity,     NULL)

        PHP_FALIAS(mssql_min_server_severity,   sybase_min_server_severity,     NULL)
@@ -230,7 +232,8 @@
        TSRMLS_FETCH();
 
        if (srvmsg->severity >= SybCtG(min_server_severity)) {
-               php_error(E_WARNING, "Sybase:  Server message:  %s (severity %d,
procedure %s)",
+               php_error(E_WARNING, "Sybase:  Server message #%d: %s (severity %d,
procedure %s)",
+                                        srvmsg->msgnumber,
                                        srvmsg->text, srvmsg->severity, 
((srvmsg->proclen>0) ?
srvmsg->proc : "N/A"));
        }
        STR_FREE(SybCtG(server_message));
@@ -953,33 +956,33 @@
                                break;
                        case CS_SMALLINT_TYPE:
                                datafmt[i].maxlength = 7;
-                               numerics[i] = 1;
+                               numerics[i] = 1;                               
                                break;
                        case CS_INT_TYPE:
                                datafmt[i].maxlength = 12;
-                               numerics[i] = 1;
+                               numerics[i] = 1;                                
                                break;
                        case CS_REAL_TYPE:
                        case CS_FLOAT_TYPE:
                                datafmt[i].maxlength = 24;
-                               numerics[i] = 1;
-                               break;
+                               numerics[i] = 2;
+                                break;
                        case CS_MONEY_TYPE:
                        case CS_MONEY4_TYPE:
                                datafmt[i].maxlength = 24;
-                               numerics[i] = 0;
+                               numerics[i] = 0;                                
                                break;
                        case CS_DATETIME_TYPE:
                        case CS_DATETIME4_TYPE:
                                datafmt[i].maxlength = 30;
                                numerics[i] = 0;
-                               break;
+                                break;
                        case CS_NUMERIC_TYPE:
                        case CS_DECIMAL_TYPE:
                                datafmt[i].maxlength = datafmt[i].precision + 3;
-                               numerics[i] = 1;
+                               numerics[i] = 2;                                
                                break;
-                       default:
+                       default:                                
                                datafmt[i].maxlength++;
                                numerics[i] = 0;
                                break;
@@ -1004,11 +1007,20 @@
                result->data[i] = (pval *) emalloc(sizeof(pval)*num_fields);
                for (j=0; j<num_fields; j++) {
                        if (indicators[j] == -1) { /* null value */
-                               ZVAL_FALSE(&result->data[i][j]);
+                               ZVAL_NULL(&result->data[i][j]);
                        } else {
                                Z_STRLEN(result->data[i][j]) = lengths[j]-1;  /* we 
don't need the
NULL in the length */
                                Z_STRVAL(result->data[i][j]) = estrndup(tmp_buffer[j],
lengths[j]);
                                Z_TYPE(result->data[i][j]) = IS_STRING;
+                          
+                               /* Here we go, i want those types!:-) 
+                                * Perhaps there is a nicer way of doing this, instead 
+of making
strings first 
+                                * and then converting them back, but I'm a 
+Zend-API-lamer.
+                                 */
+                               switch (numerics[j]) {
+                                      case 1:
convert_to_long(&result->data[i][j]); break;
+                                      case 2:
convert_to_double(&result->data[i][j]); numerics[j]= 1; break;
+                               }
                        }
                }
        }
@@ -1021,7 +1033,7 @@
                j=0;
                for (i=0; i<num_fields; i++) {
                        char computed_buf[16];
-
+                  
                        if (datafmt[i].namelen>0) {
                                result->fields[i].name = estrndup(datafmt[i].name,
datafmt[i].namelen);
                        } else {
@@ -1404,15 +1416,65 @@
        result->cur_row++;
 }
 
+static void php_sybase_fetch_assoc(INTERNAL_FUNCTION_PARAMETERS)
+{
+       pval *sybase_result_index;
+       sybase_result *result;
+       int i, j;
+       pval *tmp;
+        char name[32];
+
+       if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1,
&sybase_result_index)==FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       ZEND_FETCH_RESOURCE(result, sybase_result *, &sybase_result_index,
-1, "Sybase result", le_result);
+
+       if (result->cur_row >= result->num_rows) {
+               RETURN_FALSE;
+       }
+
+       if (array_init(return_value)==FAILURE) {
+               RETURN_FALSE;
+       }
+
+        j= 1;
+       for (i=0; i<result->num_fields; i++) {
+               ALLOC_ZVAL(tmp);
+               *tmp = result->data[result->cur_row][i];
+               INIT_PZVAL(tmp);
+               if (PG(magic_quotes_runtime) && Z_TYPE_P(tmp) == IS_STRING) {
+                       Z_STRVAL_P(tmp) = php_addslashes(Z_STRVAL_P(tmp), 
+Z_STRLEN_P(tmp),
&Z_STRLEN_P(tmp), 0 TSRMLS_CC);
+               } else {
+                       pval_copy_constructor(tmp);
+               }
+                if (zend_hash_exists(Z_ARRVAL_P(return_value),
result->fields[i].name, strlen(result->fields[i].name)+1)) {
+                        snprintf(name, 32, "%s%d",
result->fields[i].name, j);
+                        j++;
+                       zend_hash_update(Z_ARRVAL_P(return_value), name, 
+strlen(name)+1,
(void *) &tmp, sizeof(pval *), NULL);
+               } else {
+                        zend_hash_update(Z_ARRVAL_P(return_value),
result->fields[i].name, strlen(result->fields[i].name)+1, (void *)
&tmp, sizeof(pval *), NULL);
+                }
+       }
+       result->cur_row++;
+}
 
 /* {{{ proto object sybase_fetch_object(int result)
    Fetch row as object */
 PHP_FUNCTION(sybase_fetch_object)
 {
-       php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+       php_sybase_fetch_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU);
        if (Z_TYPE_P(return_value)==IS_ARRAY) {
                object_and_properties_init(return_value,
ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
        }
+}
+/* }}} */
+
+/* {{{ proto array sybase_fetch_assoc(int result)
+   Fetch row as array */
+PHP_FUNCTION(sybase_fetch_assoc)
+{
+       php_sybase_fetch_assoc(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 }
 /* }}} */


Previous Comments:
------------------------------------------------------------------------

[2002-05-02 05:37:17] [EMAIL PROTECTED]

First of all: I'm putting this in here since my mail to
[EMAIL PROTECTED] was rejected thanks to an overefficient spam
protection filter (kundenserver.de).
Please see http://relaytest.kundenserver.de/ for details.

Here's my mail:
--------------------------------------------------------
Hello,
as you might know, the sybase extension is very bad when it comes to
data types, since it returns almost everything as a string, except for
NULL values, which become FALSE.
        
Short example:
--- SQL -------------------------------
select
      NULL as "null",
      "string" as string,
      6100 as integer,
      6.1 as float,
      getdate() as date

--- var_dump() of resultset -----------  
array(10) {
  [0]=>
  string(0) ""
  ["null"]=>
  string(0) ""
  [1]=>   
  string(6) "string"
  ["string"]=>
  string(6) "string"
  [2]=>
  string(4) "6100"
  ["integer"]=>
  string(4) "6100"
  [3]=>
  string(3) "6.1"
  ["float"]=>
  string(3) "6.1"
  [4]=>
  string(4) "   :"
  ["date"]=>  
  string(4) "   :"
}
      
Well, when writing applications communicating via SOAP with
type-secure
languages - in my case PHP as server, Java as client - this comes
quite
unhandy, since on ends up going through the resultset and changing
types
for each entry, thus producing unnecessary overhead.
        
Something like this would be much nicer:
--- var_dump() of resultset -----------
array(10) {
  [0]=>
  NULL
  ["null"]=>  
  NULL
  [1]=>
  string(6) "string"
  ["string"]=>
  string(6) "string"
  [2]=>
  int(6100)
  ["integer"]=>
  int(6100)
  [3]=>
  float(6.1)
  ["float"]=>
  float(6.1)
  [4]=>
  string(19) "May 02 2002 11:15AM"
  ["date"]=>
  string(19) "May 02 2002 11:15AM"
}

OK, so I went ahead and patched ext/sybase_ct/php_sybase_ct.c to
accomplish my wishes. I must admit though I'm a total lamer when it
goes
to writing C sourcecode and utilizing the Zend API, so - after
studying
a couple of files, wrote a couple of lines, compiled, watched the
thing
segfault once or twice, I finally managed to get a running PHP binary
and a sybase_ct.so compiled.

Attached is the patch, however ugly it may be, it compiles and
produces
the resultset as intended - maybe you guys want to take a look at it
and correct it to be much nicer and much better:-)

-- 
Timm Friebe
Systems developer Schlund+Partner AG
Karlsruhe, Germany

[patch-ext_sybase_ct_php_sybase_ct.c]
--- php4-200205012100/ext/sybase_ct/php_sybase_ct.c     Tue Mar 12 21:34:06
2002
+++ __build__/ext/sybase_ct/php_sybase_ct.c     Thu May  2 10:47:53 2002
@@ -953,33 +953,33 @@
                                break;
                        case CS_SMALLINT_TYPE:
                                datafmt[i].maxlength = 7;
-                               numerics[i] = 1;
+                               numerics[i] = 1;                               
                                break;
                        case CS_INT_TYPE:
                                datafmt[i].maxlength = 12;
-                               numerics[i] = 1;
+                               numerics[i] = 1;                                
                                break;
                        case CS_REAL_TYPE:
                        case CS_FLOAT_TYPE:
                                datafmt[i].maxlength = 24;
-                               numerics[i] = 1;
-                               break;
+                               numerics[i] = 2;
+                                break;
                        case CS_MONEY_TYPE:
                        case CS_MONEY4_TYPE:
                                datafmt[i].maxlength = 24;
-                               numerics[i] = 0;
+                               numerics[i] = 0;                                
                                break;
                        case CS_DATETIME_TYPE:
                        case CS_DATETIME4_TYPE:
                                datafmt[i].maxlength = 30;
                                numerics[i] = 0;
-                               break;
+                                break;
                        case CS_NUMERIC_TYPE:
                        case CS_DECIMAL_TYPE:
                                datafmt[i].maxlength = datafmt[i].precision + 3;
-                               numerics[i] = 1;
+                               numerics[i] = 2;                                
                                break;
-                       default:
+                       default:                                
                                datafmt[i].maxlength++;
                                numerics[i] = 0;
                                break;
@@ -1004,11 +1004,19 @@
                result->data[i] = (pval *) emalloc(sizeof(pval)*num_fields);
                for (j=0; j<num_fields; j++) {
                        if (indicators[j] == -1) { /* null value */
-                               ZVAL_FALSE(&result->data[i][j]);
+                               ZVAL_NULL(&result->data[i][j]);
                        } else {
                                Z_STRLEN(result->data[i][j]) = lengths[j]-1;  /* we 
don't need the
NULL in the length */
                                Z_STRVAL(result->data[i][j]) = estrndup(tmp_buffer[j],
lengths[j]);
                                Z_TYPE(result->data[i][j]) = IS_STRING;
+                          
+                               // Here we go, i want those types!:-) 
+                               // Perhaps there is a nicer way of doing this, instead 
+of making
strings first 
+                               // and then converting them back, but I'm a 
+Zend-API-lamer.
+                               switch (numerics[j]) {
+                                      case 1:
convert_to_long(&result->data[i][j]); break;
+                                      case 2:
convert_to_double(&result->data[i][j]); numerics[j]= 1; break;
+                               }
                        }
                }
        }


------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=16960&edit=1

Reply via email to