ID: 13475
User updated by: [EMAIL PROTECTED]
Reported By: [EMAIL PROTECTED]
Status: Open
Bug Type: Feature/Change Request
Operating System: Redhat 6.2 Linux
PHP Version: 4.0.6
New Comment:

A bug  has been found in the patch provided in this bug report that causes 
segmentation faults when sybase_output_params() is called many times. Please download 
the corrected patch in its entirety at

http://www.marden.org/php-sybase-ct/

Nick

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

[2001-09-28 16:46:39] [EMAIL PROTECTED]

Ignore the comment about Yaga_DB. I forgot to strip it from my internal (company-wide) 
documentation that I posted as part of this patch. The example of getting the result 
handle through ->_queryID is valid, though.

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

[2001-09-28 06:04:25] [EMAIL PROTECTED]

The following patch to PHP 4.0.6 defines two new functions sybase_return_status() and 
sybase_output_params() that allow the user to retrieve 'return' values from stored 
procedures, and the values of output parameters. Documentation is also included before 
the patch.

This can all be downloaded at

http://www.marden.org/php-sybase-ct/

if you can't parse what's here.

Also, this has not been extensively tested, but it seems to work. You get way you pay 
for. This code way wipe out your DB and cause an Ebola virus outbreak for all I know.

Nick

sybase_ct_funcs.txt:
====================
This file describes the PHP functions sybase_return_status and
sybase_output_params that are implemented in the patch file
patch.php-sybase-ct.return-status-and-output-params, found in 
this directory. The patch file should be applied to the 
ext/sybase_ct directory of a PHP 4.0.6 distribution, and enabled
with --with-sybase-ct=$SYBASE

(o) sybase_return_status (int result) - returns the value of the
    last 'return' statement that occured in the call to sybase_query()
    that returned <result>.  In theory there could be more than one
    return statement, if for example your SQL statement called two
    stored procedures that both call return. You wouldn't be silly
    enough to do that, would you?

    Anyway, the return value of sybase_return_status is an integer.
    It is set to 0 if no return value was set during the last call
    OR if that return value was 0.  The reason for this is that if
    I made the function return false instead (in the case that no
    return value was set), you would not be able to easily test for
    the difference between no return value and a return value of 0
    because PHP is loosely typed. If you have a stored procedure
    that returns 0 to indicate an error value, you should be beaten
    anyway.

(o) sybase_output_params (int result) - returns a hash of output
    parameter names and values that were processed during the call
    to sybase_query() that produced <result>. So this looks like

    @output_param1 => 'an output value',
    @output_param2 => 17,
    etc.

    Just use list() and each() to iterate through the hash like
    you would with any hash in PHP. 

    The return value will be false if there were no output 
    parameters returned from the SQL statement. Thus your
    flow control can look like this

        if( $output_params = sybase_output_params($result) ) {
            // handle processing ...
        }

    and be meaningful.

    A note: The "result" passed to sybase_return_status() and to
    sybase_output_params() is the return value from sybase_query().
    If you're using Yaga_DB, or ADODB directly (don't do that!)
    then you can get this value and use it as follows:

        <?
            $result = $result_set->_queryID;
            if($result)
            {
                $output_params = sybase_output_params($result);
            }
            else
            {
                php_error("No output parameters!");
            }
        ?>

Patch follows:

patch.php-sybase-ct.return_status-and-output_params:
====================== snip ========================

--- php_sybase_ct.h.dist        Thu Sep 27 13:01:53 2001
+++ php_sybase_ct.h     Thu Sep 27 19:45:56 2001
@@ -53,6 +53,8 @@
 PHP_FUNCTION(sybase_min_client_severity);
 PHP_FUNCTION(sybase_min_server_severity);
 PHP_FUNCTION(sybase_fetch_field);
+PHP_FUNCTION(sybase_return_status);
+PHP_FUNCTION(sybase_output_params);
 
 
 #include <ctpublic.h>
@@ -92,6 +94,9 @@
        sybase_link *sybase_ptr;
        int cur_row,cur_field;
        int num_rows,num_fields;
+        int return_status;
+        int num_output_params;
+        pval *output_params;
 } sybase_result;
 
 
--- php_sybase_ct.c.dist        Thu Sep 27 13:01:48 2001
+++ php_sybase_ct.c     Thu Sep 27 23:46:45 2001
@@ -54,6 +54,8 @@
        PHP_FE(sybase_field_seek,           NULL)
        PHP_FE(sybase_result,                           NULL)
        PHP_FE(sybase_affected_rows,            NULL)
+       PHP_FE(sybase_return_status,            NULL)
+       PHP_FE(sybase_output_params,            NULL)
        PHP_FE(sybase_min_client_severity,      NULL)
        PHP_FE(sybase_min_server_severity,      NULL)
 
@@ -109,7 +111,6 @@
        return 0;
 }
 
-
 static void _free_sybase_result(sybase_result *result)
 {
        int i, j;
@@ -131,6 +132,10 @@
                }
                efree(result->fields);
        }
+        
+        if (result->output_params) {
+            pval_destructor(result->output_params);
+        }
 
        efree(result);
 }
@@ -867,6 +872,9 @@
        result->sybase_ptr = sybase_ptr;
        result->cur_field=result->cur_row=result->num_rows=0;
        result->num_fields = num_fields;
+        result->return_status = 0;
+        result->num_output_params = 0;
+        result->output_params = NULL;
 
        tmp_buffer = (char **) emalloc(sizeof(char *)*num_fields);
        lengths = (CS_INT *) emalloc(sizeof(CS_INT)*num_fields);
@@ -1000,6 +1008,28 @@
        return result;
 }
 
+/* Adds the data[0] row in source to the output_params hash in dest */
+static void _copy_output_params(sybase_result *source, sybase_result *dest)
+{
+        zval* new_param;
+       int i;
+        if(!dest->output_params)
+        {
+                ALLOC_ZVAL(dest->output_params)
+                array_init(dest->output_params);
+                INIT_PZVAL(dest->output_params)
+                /* zend_hash_init(dest->output_params->value.ht, 0, NULL, 
+ZVAL_PTR_DTOR, 1); */
+        }
+        for(i=0; i<source->num_fields; i++) {
+               /* Add source->fields[i] as the name and source->data[0][i] as the 
+value */
+                ALLOC_ZVAL(new_param)
+                *new_param = source->data[0][i];
+                zval_copy_ctor(new_param);
+                zend_hash_add(dest->output_params->value.ht,
+                             source->fields[i].name, 
+strlen(source->fields[i].name)+1,
+                              &new_param, sizeof(zval *), NULL);
+        }
+}
 
 /* {{{ proto int sybase_query(string query [, int link_id])
    Send Sybase query */
@@ -1011,6 +1041,8 @@
        sybase_result *result;
        CS_INT restype;
        CS_RETCODE retcode;
+        sybase_result *temp;
+        int i;
        enum {
                Q_RESULT,                               /* Success with results. */
                Q_SUCCESS,                              /* Success but no results. */
@@ -1114,7 +1146,11 @@
                                        ct_cancel(NULL, sybase_ptr->cmd, 
CS_CANCEL_ALL);
                                        sybase_ptr->dead = 1;
                                        RETURN_FALSE;
-                               }
+                               } else if ( restype == CS_PARAM_RESULT && 
+(result->num_fields>0)) {
+                                        _copy_output_params(result, result);
+                                } else if ( restype == CS_STATUS_RESULT && 
+result->data[0] ) {
+                                        result->return_status = 
+atoi(result->data[0][0].value.str.val);
+                                }
                                status = Q_RESULT;
                                break;
                }
@@ -1136,19 +1172,34 @@
                                        status = Q_FAILURE;
                                        break;
                        
+                               case CS_PARAM_RESULT:
+                               case CS_STATUS_RESULT:
+                                        /* For these two cases, fetch the results 
+into a temporary
+                                           sybase_result and then pick through it to 
+populate the
+                                           output_params or return_status of the real 
+sybase_result */
+                                       temp = 
+php_sybase_fetch_result_set(sybase_ptr);
+                                       if (temp == NULL) {
+                                               ct_cancel(NULL, sybase_ptr->cmd, 
+CS_CANCEL_ALL);
+                                               sybase_ptr->dead = 1;
+                                               RETURN_FALSE;
+                                       } else if ( restype == CS_PARAM_RESULT && 
+(temp->num_fields>0) ) {
+                                                _copy_output_params(temp, result);
+                                        } else if ( restype == CS_STATUS_RESULT && 
+temp->data[0] ) {
+                                                result->return_status = 
+atoi(temp->data[0][0].value.str.val);
+                                        }
+                                        _free_sybase_result(temp);
+                                        break;
                                case CS_COMPUTE_RESULT:
                                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);
                                        break;
                        
                                default:
                                        status = Q_FAILURE;
                                        break;
-                       }
+                        }
                        if (status == Q_FAILURE) {
                                ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
                        }
@@ -1670,9 +1721,55 @@
 }
 /* }}} */
 
+/* {{{ proto pval* sybase_return_status (int result)
+   Sets minimum server severity */
+PHP_FUNCTION(sybase_return_status)
+{
+       pval *sybase_result_index;
+       int i;
+       sybase_result *result;
+       pval *field_content;
+       SybCtLS_FETCH();
 
-#endif
+       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);
 
+       return_value->value.lval = result->return_status;
+       return_value->type = IS_LONG;
+        return;
+}
+/* }}} */
+
+/* {{{ proto pval* sybase_output_params (int result)
+   Sets minimum server severity */
+PHP_FUNCTION(sybase_output_params)
+{
+       pval *sybase_result_index;
+       int i;
+       sybase_result *result;
+       pval *field_content;
+       SybCtLS_FETCH();
+
+       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->output_params == NULL)
+            RETURN_FALSE;
+
+        /* Copy output_params to return_value */
+       *return_value = *(result->output_params);
+       pval_copy_constructor(return_value);
+        return;
+}
+/* }}} */
+
+#endif
 /*
  * Local variables:
  * tab-width: 4




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



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


-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]

Reply via email to