php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #13475 Patch For Sybase stored procedure return values and and output params
Submitted: 2001-09-28 06:04 UTC Modified: 2005-06-22 03:14 UTC
Votes:8
Avg. Score:3.8 ± 1.3
Reproduced:5 of 6 (83.3%)
Same Version:0 (0.0%)
Same OS:2 (40.0%)
From: nick at marden dot org Assigned:
Status: Suspended Package: Feature/Change Request
PHP Version: 4.0.6 OS: Redhat 6.2 Linux
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [2001-09-28 06:04 UTC] nick at marden dot org
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



Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2001-09-28 16:46 UTC] nick at marden dot org
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-10-04 18:12 UTC] nick at marden dot org
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
 [2004-01-23 20:58 UTC] thekid@php.net
---------------------------------------------------------
Not Found
The requested URL /php-sybase-ct/ was not found on this server.

Apache/1.3.27 Server at www.marden.org Port 
---------------------------------------------------------

I kind of like the idea, though:)
 [2005-06-22 03:14 UTC] nick at marden dot org
I have revived this patch (for PHP 4.3.11) and it now resides 
(again) at http://www.marden.org/php-sybase-ct/
 [2008-06-18 12:33 UTC] maggelo at gmail dot com
links are broken...
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Sun Nov 19 01:31:42 2017 UTC