Skip to Content.
Sympa Menu

freetds - RE: mssql_query not updating mssql_get_last_message on php4.1.2 and freetds 0.53

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "Mark Gruetzner" <mgruetzner AT rw3.com>
  • To: "TDS Development Group" <freetds AT franklin.oit.unc.edu>
  • Subject: RE: mssql_query not updating mssql_get_last_message on php4.1.2 and freetds 0.53
  • Date: Thu, 30 May 2002 10:05:52 -0500


Hi Tom,

I have another, related patch for php 4.1.2 (and I haven't seen it fixed in
the latest stable build of php either). The patch below is the entire
"sybase_query" function in the php_sybase_db.c file. Search for //fixfix
to see what I added. This patch allows the actual error message to be sent
to php to update the return value for mssql_get_last_message every time
raiserror is called with a user-defined message, such as raiserror ('My
error message',9,1):

/* {{{ proto int sybase_query(string query [, int link_id])
Send Sybase query */
PHP_FUNCTION(sybase_query)
{
pval *query,*sybase_link_index;
int id,type,retvalue;
sybase_link *sybase_ptr;
sybase_result *result;
int num_fields;
int blocks_initialized=1;
int i,j;
int *column_types;
RETCODE dbresults_retval; //fixfix

switch(ZEND_NUM_ARGS()) {
case 1:
if (getParameters(ht, 1, &query)==FAILURE) {
RETURN_FALSE;
}
id = php_sybase_module.default_link;
break;
case 2:
if (getParameters(ht, 2, &query,
&sybase_link_index)==FAILURE) {
RETURN_FALSE;
}
convert_to_long(sybase_link_index);
id = sybase_link_index->value.lval;
break;
default:
WRONG_PARAM_COUNT;
break;
}

sybase_ptr = (sybase_link *) zend_list_find(id,&type);
if (type!=php_sybase_module.le_link &&
type!=php_sybase_module.le_plink) {
php_error(E_WARNING,"%d is not a Sybase link index",id);
RETURN_FALSE;
}

convert_to_string(query);
if (dbcmd(sybase_ptr->link,query->value.str.val)==FAIL) {
/*php_error(E_WARNING,"Sybase: Unable to set query");*/
RETURN_FALSE;
}
//fixfix--save the result of dbresults for later
if (dbsqlexec(sybase_ptr->link)==FAIL) {
/*php_error(E_WARNING,"Sybase: Query failed");*/
RETURN_FALSE;
}
dbresults_retval = dbresults(sybase_ptr->link);
if (dbresults_retval==FAIL) {
/*php_error(E_WARNING,"Sybase: Query failed");*/
RETURN_FALSE;
}

/* The following is more or less the equivalent of
mysql_store_result().
* fetch all rows from the server into the row buffer, thus:
* 1) Being able to fire up another query without explicitly reading
all
rows
* 2) Having numrows accessible
*/

retvalue=dbnextrow(sybase_ptr->link);

if (retvalue==FAIL) {
RETURN_FALSE;
}

num_fields = dbnumcols(sybase_ptr->link);
if (num_fields<=0) {
RETURN_TRUE;
}

column_types = (int *) emalloc(sizeof(int) * num_fields);
for (i=0; i<num_fields; i++) {
column_types[i] = coltype(i+1);
}

result = (sybase_result *) emalloc(sizeof(sybase_result));
result->data = (pval ***) emalloc(sizeof(pval **)*SYBASE_ROWS_BLOCK);
result->sybase_ptr = sybase_ptr;
result->cur_field=result->cur_row=result->num_rows=0;
result->num_fields = num_fields;

i=0;
while (retvalue!=FAIL && retvalue!=NO_MORE_ROWS) {
result->num_rows++;
if (result->num_rows > blocks_initialized*SYBASE_ROWS_BLOCK) {
result->data = (pval ***)
erealloc(result->data,sizeof(pval
**)*SYBASE_ROWS_BLOCK*(++blocks_initialized));
}
result->data[i] = (pval **) emalloc(sizeof(pval
*)*num_fields);
for (j=1; j<=num_fields; j++) {
php_sybase_get_column_content(sybase_ptr, j,
&result->data[i][j-1],
column_types[j-1]);
if (!php_sybase_module.compatability_mode) {
zval *cur_value = result->data[i][j-1];

convert_to_string(cur_value);
if (PG(magic_quotes_runtime)) {
cur_value->value.str.val =
php_addslashes(cur_value->value.str.val,
cur_value->value.str.len, &cur_value->value.str.len,0 TSRMLS_CC);
}
}
}
retvalue=dbnextrow(sybase_ptr->link);
dbclrbuf(sybase_ptr->link,DBLASTROW(sybase_ptr->link)-1);
i++;
}
result->num_rows = DBCOUNT(sybase_ptr->link);

result->fields = (sybase_field *)
emalloc(sizeof(sybase_field)*num_fields);
j=0;
for (i=0; i<num_fields; i++) {
char *fname = dbcolname(sybase_ptr->link,i+1);
char computed_buf[16];

if (*fname) {
result->fields[i].name = estrdup(fname);
} else {
if (j>0) {
snprintf(computed_buf,16,"computed%d",j);
} else {
strcpy(computed_buf,"computed");
}
result->fields[i].name = estrdup(computed_buf);
j++;
}
result->fields[i].max_length = dbcollen(sybase_ptr->link,i+1);
result->fields[i].column_source =
estrdup(dbcolsource(sybase_ptr->link,i+1));
if (!result->fields[i].column_source) {
result->fields[i].column_source = empty_string;
}
result->fields[i].type = column_types[i];
/* set numeric flag */
switch (column_types[i]) {
case SYBINT2:
case SYBINT4:
case SYBFLT8:
case SYBREAL:
result->fields[i].numeric = 1;
break;
case SYBCHAR:
case SYBTEXT:
default:
result->fields[i].numeric = 0;
break;
}
}
efree(column_types);
return_value->value.lval =
zend_list_insert(result,php_sybase_module.le_result);
return_value->type = IS_LONG;

//fixfix
// If you do a query that calls a stored procedure which returns
// data AND calls raiserror to generated a user-defined error message,
// then after retrieving the first set of results above, the call
// to dbresults will have returned SUCCESS, instead of NO_MORE_RESULTS
// which indicates that the message generated by raiserror is still
// waiting to be read. If this is the case, then call dbresults
// again to force the reading of the message. This will ensure the
// get_last_message call will return the message properly if called
// after mssql_query, like it should.
//
// One thing to note, we are assuming that no more data should follow
// in this case--only the message will be read. To make sure, I have
// added a call to dbnextrow. The assumption is that it will return
// NO_MORE_ROWS in this case. If the assumption is false, generate
// a PHP error so we can debug this case.
if (dbresults_retval != NO_MORE_RESULTS) {

// Call dbresults again to read message
dbresults_retval = dbresults(sybase_ptr->link);

// Check assumption that dbnextrow returns NO_MORE_ROWS
retvalue=dbnextrow(sybase_ptr->link);
if (retvalue != NO_MORE_ROWS) {
php_error(E_WARNING,"Sybase mssql_query assumption
violated. Expected
dbnextrow to return NO_MORE_ROWS\n");
}
}
}

-----Original Message-----
From: bounce-freetds-143882 AT franklin.oit.unc.edu
[mailto:bounce-freetds-143882 AT franklin.oit.unc.edu]On Behalf Of Tom
Sillence
Sent: Wednesday, May 29, 2002 7:55 PM
To: TDS Development Group
Subject: [freetds] RE: mssql_query not updating mssql_get_last_message
on php4.1.2 and freetds 0.53


Thanks for a friendly welcome to the list.

The bug I identified is indeed fixed in the latest CVS version. I should
have checked but I am forced by my sysadmins to use the stable 0.53.
However, for those who are interested, the patch at the bottom of this email
(it is extremely short and simple) can be applied to php. It makes php keep
track of the last error message from the database. In the future, I would
like to see php track the last several errors, but this patch at least gives
equivalent functionality to that of the windows drivers. It is taken
relative to php4.2.1 but the code in question hasn't changed at least since
4.1. The patch should be applied to php_sybase_db.c in ./ext/sybase/
The values returned from this function and its message handling counterpart
are not used by freeTDS's dblib. I am not sure, therefore, what the
INT_CANCEL return value signified. For all I know it may be more appropriate
than returning 0 (I have made this change to keep parity with
php_sybase_message_handler), but it won't have any effect in the current
implementation anyway.

I hope I can be of more relevant help to freeTDS in the future.

[context patch follows]

*** php_sybase_db.c Wed Mar 6 15:59:42 2002
--- ../../../php-4.2.1-patched/ext/sybase/php_sybase_db.c Wed May 29
18:42:59 2002
***************
*** 146,152 ****
if (severity >= php_sybase_module.min_error_severity) {
php_error(E_WARNING,"Sybase error: %s (severity
%d)",dberrstr,severity);
}
! return INT_CANCEL;
}

/* message handler */
--- 146,158 ----
if (severity >= php_sybase_module.min_error_severity) {
php_error(E_WARNING,"Sybase error: %s (severity
%d)",dberrstr,severity);
}
!
!
! STR_FREE(php_sybase_module.server_message);
! php_sybase_module.server_message = estrdup(dberrstr);
! return 0;
!
! // return INT_CANCEL;
}

/* message handler */




---
You are currently subscribed to freetds as: [mgruetzner AT rw3.com]
To unsubscribe, forward this message to
$subst('Email.Unsub')





Archive powered by MHonArc 2.6.24.

Top of Page