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


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