Bug #13475 Updated: Patch For Sybase stored procedure return values and and output params
| From: | nick at marden dot org | Date: | Thu, 04 Oct 2001 22:12:48 +0000 |
| Subject: | Bug #13475 Updated: Patch For Sybase stored procedure return values and and output params | ||
| References: | 1 | Groups: | php.dev |
| Request: | Send a blank email to php-dev+get-67292@lists.php.net to get a copy of this message | ||
ID: 13475
User updated by: nick@marden.org
Reported By: nick@marden.org
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] nick@marden.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-09-28 06:04:25] nick@marden.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
------------------------------------------------------------------------
Edit this bug report at http://bugs.php.net/?id=13475&edit=1