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

This bug has been fixed in CVS.

In case this was a PHP problem, snapshots of the sources are packaged
every three hours; this change will be in the next snapshot. You can
grab the snapshot at http://snaps.php.net/.
 
In case this was a documentation problem, the fix will show up soon at
http://www.php.net/manual/.

In case this was a PHP.net website problem, the change will show
up on the PHP.net site and on the mirror sites in short time.
 
Thank you for the report, and for helping us make PHP better.

Committed numerous changes to ext/sybase_ct, see CVS log for
ext/sybase_ct/php_sybase_ct.c and ext/sybase_ct/php_sybase_ct.h


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

[2002-06-10 18:43:18] [EMAIL PROTECTED]

Sorry, here's an example script for sybase_set_message_handler():

<?php
  function sybase_error($msgnumber, $severity, $state, $line, $text) {
    if (5701 == $msgnumber) return;             // Changed database
context to ...
    if (257 == $msgnumber) return FALSE;        // Implicit
conversion...
    printf(
      "Caught Sybase Server Message #%d [Severity %d, state %d] at line
%d\n'%s'\n\n",
      $msgnumber,
      $severity,
      $state,
      $line,
      chop($text)
    );
  }

  sybase_set_message_handler('sybase_error');
  $dbh= sybase_connect([...]);

  // Erroneous call
  sybase_query('select @does_not_exist');

  // Another erroneous call, assume foo_id is numeric(10)
  // This will result in an "...implicit conversion..."
  // which is not handled by the above function
  sybase_query('select * from foo where foo_id= "1"');
?>

The output is:
--------------------------------------------------------
Caught Sybase Server Message #137 [Severity 15, state 2] at line 1
'Must declare variable '@does_not_exist'.'
<br />
<b>Warning</b>:  Sybase:  Server message #257: Implicit conversion from
datatype 'VARCHAR' to 'NUMERIC' is not allowed.  Use the CONVERT
function to run this query.
 (severity 16, procedure N/A) in
<b>/usr/home/thekid/devel/php/sybase_test.php</b> on line <b>23</b><br
/>
--------------------------------------------------------

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

[2002-06-10 15:50:15] [EMAIL PROTECTED]

With this last patch, you will be able to handle all of sybase's error
messages via a callback function. This comes in quite handy when having
to check for deadlocks (the 1205:-)).

$deadlock= strstr($php_errormsg, 'deadlock'); is, of course, possible
right now, but in my eyes not a very generalistic way of going about
it...

--- php4-200205012100/ext/sybase_ct/php_sybase_ct.h     Thu Feb 28 09:38:19
2002
+++ __build__/ext/sybase_ct/php_sybase_ct.h     Mon Jun 10 21:32:25 2002
@@ -45,6 +45,7 @@
 PHP_FUNCTION(sybase_num_fields);
 PHP_FUNCTION(sybase_fetch_row);
 PHP_FUNCTION(sybase_fetch_array);
+PHP_FUNCTION(sybase_fetch_assoc);
 PHP_FUNCTION(sybase_fetch_object);
 PHP_FUNCTION(sybase_data_seek);
 PHP_FUNCTION(sybase_result);
@@ -53,7 +54,7 @@
 PHP_FUNCTION(sybase_min_client_severity);
 PHP_FUNCTION(sybase_min_server_severity);
 PHP_FUNCTION(sybase_fetch_field);
-
+PHP_FUNCTION(sybase_set_message_handler);
 
 #include <ctpublic.h>
 
@@ -66,6 +67,7 @@
        char *hostname;
        char *server_message;
        long min_server_severity, min_client_severity;
+        zval *callback_name;
        CS_CONTEXT *context;
 ZEND_END_MODULE_GLOBALS(sybase)
 
@@ -93,7 +95,6 @@
        int cur_row,cur_field;
        int num_rows,num_fields;
 } sybase_result;
-
 
 #ifdef ZTS
 # define SybCtG(v) TSRMG(sybase_globals_id, zend_sybase_globals *, v)

--- php4-200205012100/ext/sybase_ct/php_sybase_ct.c     Tue Mar 12 21:34:06
2002
+++ __build__/ext/sybase_ct/php_sybase_ct.c     Wed May  8 04:12:38 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)
@@ -56,23 +57,26 @@
        PHP_FE(sybase_affected_rows,            NULL)
        PHP_FE(sybase_min_client_severity,      NULL)
        PHP_FE(sybase_min_server_severity,      NULL)
+        PHP_FE(sybase_set_message_handler,      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_set_message_handler,  
sybase_set_message_handler,     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)
@@ -199,12 +203,36 @@
 }
 
 
+/* {{{ proto void sybase_set_message_handler(mixed error_func)
+   Set the error handler, to be called when a server message is raise
*/
+PHP_FUNCTION(sybase_set_message_handler)
+{
+       char *c;
+       int c_len;
+
+       if(
+         (ZEND_NUM_ARGS() != 1) || 
+          (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &c,
&c_len)!= SUCCESS))
+       {
+           WRONG_PARAM_COUNT;
+       }
+
+       /*
+        * Is it a good idea to put this in sybase_globals?
+        */
+        MAKE_STD_ZVAL(SybCtG(callback_name));
+       ZVAL_STRINGL(SybCtG(callback_name), c, c_len, 1);
+
+       RETURN_TRUE;    
+}
+/* }}} */
+
 static CS_RETCODE CS_PUBLIC _client_message_handler(CS_CONTEXT
*context, CS_CONNECTION *connection, CS_CLIENTMSG *errmsg)
 {
        TSRMLS_FETCH();
 
        if (CS_SEVERITY(errmsg->msgnumber) >= SybCtG(min_client_severity)) {
-               php_error(E_WARNING, "Sybase:  Client message:  %s (severity %d)",
errmsg->msgstring, CS_SEVERITY(errmsg->msgnumber));
+               php_error(E_WARNING, "Sybase:  Client message:  %s
(severity %d)", errmsg->msgstring, CS_SEVERITY(errmsg->msgnumber));
        }
        STR_FREE(SybCtG(server_message));
        SybCtG(server_message) = estrdup(errmsg->msgstring);
@@ -227,13 +255,61 @@
 
 static CS_RETCODE CS_PUBLIC _server_message_handler(CS_CONTEXT
*context, CS_CONNECTION *connection, CS_SERVERMSG *srvmsg)
 {
+        zval *retval = NULL;
+        zval severity, msgnumber, state, line, text;
+        zval *ptrs[5]= {&msgnumber, &severity, &state, &line, &text};
+        zval **args[5]= {&ptrs[0], &ptrs[1], &ptrs[2], &ptrs[3],
&ptrs[4]};
+       int  handled;
+       
        TSRMLS_FETCH();
 
        if (srvmsg->severity >= SybCtG(min_server_severity)) {
-               php_error(E_WARNING, "Sybase:  Server message:  %s (severity %d,
procedure %s)",
-                                       srvmsg->text, srvmsg->severity, 
((srvmsg->proclen>0) ?
srvmsg->proc : "N/A"));
+               handled= 0;     
+                if (SybCtG(callback_name) != NULL) {
+                       INIT_ZVAL(msgnumber);
+                       INIT_ZVAL(severity);
+                       INIT_ZVAL(state);
+                       INIT_ZVAL(line);
+                       INIT_ZVAL(text);
+         
+                       ZVAL_LONG(&msgnumber, srvmsg->msgnumber);
+                       ZVAL_LONG(&severity, srvmsg->severity);
+                       ZVAL_LONG(&state, srvmsg->state);
+                       ZVAL_LONG(&line, srvmsg->line);
+                       ZVAL_STRING(&text, srvmsg->text, 0);
+          
+                       if (call_user_function_ex(CG(function_table), NULL,
SybCtG(callback_name), &retval, 5, args, 0, NULL TSRMLS_CC)== FAILURE)
{
+                               php_error(E_WARNING, "Sybase:  Cannot call the
messagehandler %s", Z_STRVAL_P(SybCtG(callback_name)));
+                       }
+               
+                       /* 
+                        * Returning FALSE, the user function indicates it can't cope
+                        * with this error. Any other return value will be ignored.
+                        *
+                        */
+                       if (retval) {
+                               handled= (
+                                               (Z_TYPE_P(retval) != IS_BOOL) || 
+                                               (Z_BVAL_P(retval) != 0)
+                                        );              
+                               zval_ptr_dtor(&retval);
+                       }
+                       
+               }
+               if (!handled) {
+                       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));
+        
        SybCtG(server_message) = estrdup(srvmsg->text);
 
        /* If this is a deadlock message, set the connection's deadlock flag
@@ -267,7 +343,7 @@
 
 static void php_sybase_init_globals(zend_sybase_globals
*sybase_globals)
 {
-       long timeout;
+       long timeout, packet_size;
 
        if (cs_ctx_alloc(CTLIB_VERSION, &sybase_globals->context)!=CS_SUCCEED
|| ct_init(sybase_globals->context, CTLIB_VERSION)!=CS_SUCCEED) {
                return;
@@ -316,7 +392,19 @@
                        php_error(E_WARNING, "Sybase:  Unable to set timeout");
                }
        }
+
+       /*
+        * Packet size
+        */
+        if (cfg_get_long("sybct.packet_size", &packet_size)==SUCCESS)
{
+                CS_INT cs_packet_size = packet_size;
+                if (ct_config(sybase_globals->context, CS_SET,
CS_PACKETSIZE, &cs_packet_size, CS_UNUSED, NULL)!=CS_SUCCEED) {
+                        php_error(E_WARNING, "Sybase:  Unable to set
timeout");
+                }
+        }
+                                                                                      
+                                 
        sybase_globals->num_persistent=0;
+        sybase_globals->callback_name = NULL;
 }
 
 
@@ -366,6 +454,7 @@
 PHP_RSHUTDOWN_FUNCTION(sybase)
 {
        efree(SybCtG(appname));
+       if (NULL != SybCtG(callback_name))
zval_ptr_dtor(&SybCtG(callback_name));
        STR_FREE(SybCtG(server_message));
        return SUCCESS;
 }
@@ -893,8 +982,8 @@
 
 static sybase_result * php_sybase_fetch_result_set (sybase_link
*sybase_ptr)
 {
+       sybase_result *result;  
        int num_fields;
-       sybase_result *result;
        char **tmp_buffer;
        CS_INT *lengths;
        CS_SMALLINT *indicators;
@@ -920,7 +1009,6 @@
        result->sybase_ptr = sybase_ptr;
        result->cur_field=result->cur_row=result->num_rows=0;
        result->num_fields = num_fields;
-
        tmp_buffer = (char **) emalloc(sizeof(char *)*num_fields);
        lengths = (CS_INT *) emalloc(sizeof(CS_INT)*num_fields);
        indicators = (CS_SMALLINT *) emalloc(sizeof(CS_INT)*num_fields);
@@ -953,33 +1041,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] = 2;                                
                                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] = (datafmt[i].scale == 0) ? 1 : 2;   // 
+numeric(10) vs
numeric(10, 1)                              
                                break;
-                       default:
+                       default:                                
                                datafmt[i].maxlength++;
                                numerics[i] = 0;
                                break;
@@ -1004,11 +1092,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 +1118,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 {
@@ -1133,7 +1230,6 @@
                 */
                if (ct_results(sybase_ptr->cmd, &restype)!=CS_SUCCEED) {
                        ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
-                       sybase_ptr->dead = 1;
                        RETURN_FALSE;
                }
 
@@ -1192,9 +1288,9 @@
                                case CS_CURSOR_RESULT:
                                case CS_PARAM_RESULT:
                                case CS_ROW_RESULT:
-                                       /* Unexpected results, cancel them. */
                                case CS_STATUS_RESULT:
-                                       ct_cancel(NULL, sybase_ptr->cmd, 
CS_CANCEL_CURRENT);
+                                       /* Discard... */ 
+                                       // ct_cancel(NULL, sybase_ptr->cmd,
CS_CANCEL_CURRENT);
                                        break;
 
                                default:
@@ -1371,8 +1467,9 @@
 {
        pval *sybase_result_index;
        sybase_result *result;
-       int i;
+       int i, j;
        pval *tmp;
+        char name[32];
 
        if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1,
&sybase_result_index)==FAILURE) {
                WRONG_PARAM_COUNT;
@@ -1388,6 +1485,7 @@
                RETURN_FALSE;
        }
 
+        j= 1;
        for (i=0; i<result->num_fields; i++) {
                ALLOC_ZVAL(tmp);
                *tmp = result->data[result->cur_row][i];
@@ -1399,20 +1497,76 @@
                }
                zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *) &tmp,
sizeof(pval *), NULL);
                tmp->refcount++;
-               zend_hash_update(Z_ARRVAL_P(return_value), result->fields[i].name,
strlen(result->fields[i].name)+1, (void *) &tmp, sizeof(pval *),
NULL);
+                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++;
 }
 
+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);
 }
 /* }}} */

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

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/16960

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

Reply via email to