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