Index: ext/sybase_ct/php_sybase_ct.c
===================================================================
RCS file: /repository/php-src/ext/sybase_ct/php_sybase_ct.c,v
retrieving revision 1.73.2.16
diff -u -r1.73.2.16 php_sybase_ct.c
--- ext/sybase_ct/php_sybase_ct.c	21 May 2004 21:00:19 -0000	1.73.2.16
+++ ext/sybase_ct/php_sybase_ct.c	12 Jul 2004 20:43:06 -0000
@@ -118,13 +118,12 @@
 	return 0;
 }
 
-
 static void _free_sybase_result(sybase_result *result)
 {
 	int i, j;
 
 	if (result->data) {
-		for (i=0; i<(result->store ? result->num_rows : 0); i++) {
+		for (i = 0; i < (result->store ? result->num_rows : MIN(1, result->num_rows)); i++) {
 			for (j=0; j<result->num_fields; j++) {
 				zval_dtor(&result->data[i][j]);
 			}
@@ -144,10 +143,21 @@
 	efree(result);
 }
 
+/* Forward declaration */
+static int php_sybase_finish_results (sybase_result *result);
+
 static void php_free_sybase_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 {
 	sybase_result *result = (sybase_result *)rsrc->ptr;
 
+	/* Check to see if we've read all rows */
+	if (result->sybase_ptr && result->sybase_ptr->active_result_index) {
+		if (result->sybase_ptr->cmd) {
+			ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL);
+		}
+		php_sybase_finish_results(result);
+	}
+
 	_free_sybase_result(result);
 }
 
@@ -1040,11 +1050,15 @@
 			case CS_PARAM_RESULT:
 			case CS_ROW_RESULT:
 				/* Unexpected results, cancel them. */
-			case CS_STATUS_RESULT:
 				php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase:  Unexpected results, cancelling current");
 				ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_CURRENT);
 				break;
 
+			case CS_STATUS_RESULT:
+				/* Status result from a stored procedure, cancel it but do not tell user */
+				ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_CURRENT);
+				break;
+
 			default:
 				php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase:  Unexpected results, cancelling all");
 				ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL);
@@ -1085,6 +1099,19 @@
 	return retcode;
 }
 
+#define RETURN_DOUBLE_VAL(result, buf, length)          \
+	if ((length - 1) <= EG(precision)) {                \
+		errno = 0;                                      \
+		Z_DVAL(result) = strtod(buf, NULL);             \
+		if (errno != ERANGE) {                          \
+			Z_TYPE(result) = IS_DOUBLE;                 \
+		} else {                                        \
+			ZVAL_STRINGL(&result, buf, length- 1, 1);   \
+		}                                               \
+	} else {                                            \
+		ZVAL_STRINGL(&result, buf, length- 1, 1);       \
+	}
+
 static int php_sybase_fetch_result_row (sybase_result *result, int numrows) 
 {
 	int i, j;
@@ -1105,7 +1132,6 @@
 		}
 		*/
 		
-		/* i= result->num_rows++; */
 		result->num_rows++;
 		i= result->store ? result->num_rows- 1 : 0;
 		if (i >= result->blocks_initialized*SYBASE_ROWS_BLOCK) {
@@ -1115,27 +1141,48 @@
 			result->data[i] = (zval *) safe_emalloc(sizeof(zval), result->num_fields, 0);
 		}
 
-		for (j=0; j<result->num_fields; j++) {
+		for (j = 0; j < result->num_fields; j++) {
+
+			/* If we are in non-storing mode, free the previous result */
+			if (!result->store && result->num_rows > 1 && Z_TYPE(result->data[i][j]) == IS_STRING) {
+				efree(Z_STRVAL(result->data[i][j]));
+			}
+
 			if (result->indicators[j] == -1) { /* null value */
 				ZVAL_NULL(&result->data[i][j]);
 			} else {
-				Z_STRLEN(result->data[i][j]) = result->lengths[j]-1;  /* we don't need the NULL in the length */
-				Z_STRVAL(result->data[i][j]) = estrndup(result->tmp_buffer[j], result->lengths[j]);
-				Z_TYPE(result->data[i][j]) = IS_STRING;
-				
 				switch (result->numerics[j]) {
-					case 1:
-						convert_to_long(&result->data[i][j]);
+					case 1: {
+						/* This indicates a long */
+						ZVAL_LONG(&result->data[i][j], strtol(result->tmp_buffer[j], NULL, 10));
 						break;
-					case 2:
-						convert_to_double(&result->data[i][j]);
+					}
+					
+					case 2: {
+						/* This indicates a float */
+						RETURN_DOUBLE_VAL(result->data[i][j], result->tmp_buffer[j], result->lengths[j]); 
 						break;
-					case 3:
-						/* This signals we have an integer datatype, but we need to convert to double if we 
-						 * overflow. 
-						 */
-						convert_scalar_to_number(&result->data[i][j] TSRMLS_CC);
+					}
+
+					case 3: {
+						/* This indicates either a long or a float, which ever fits */
+						errno = 0;
+						Z_LVAL(result->data[i][j]) = strtol(result->tmp_buffer[j], NULL, 10);
+						if (errno == ERANGE) {
+						
+							/* An overflow occurred, so try to fit it into a double */
+							RETURN_DOUBLE_VAL(result->data[i][j], result->tmp_buffer[j], result->lengths[j]); 
+							break;
+						}
+						Z_TYPE(result->data[i][j]) = IS_LONG;
 						break;
+					}
+					
+					default: {
+						/* This indicates anything else, return it as string */
+						ZVAL_STRINGL(&result->data[i][j], result->tmp_buffer[j], result->lengths[j]- 1, 1);
+						break;
+					}	   
 				}
 			}
 		}
@@ -1278,9 +1325,12 @@
 		Z_TYPE(result->fields[i]) = result->types[i];
 	}
 	
-	retcode= php_sybase_fetch_result_row(result, buffered ? 1 : -1);
-	if (retcode == CS_FAIL) {
-		return NULL;
+	if (buffered) {
+		retcode = CS_SUCCEED;
+	} else {
+		if ((retcode = php_sybase_fetch_result_row(result, -1)) == CS_FAIL) {
+			return NULL;
+		}
 	}
 
 	result->last_retcode = retcode;
@@ -1320,9 +1370,14 @@
 			if (zend_get_parameters_ex(3, &query, &sybase_link_index, &store_mode)==FAILURE) {
 				RETURN_FALSE;
 			}
+			if (!buffered) {
+				php_error_docref(NULL TSRMLS_CC, E_NOTICE, "cannot use non-storing mode with buffered queries");
+				store = 1;
+			} else {
+				convert_to_long_ex(store_mode);
+				store= (Z_LVAL_PP(store_mode) != 0);
+			}
 			id = -1;
-			convert_to_long_ex(store_mode);
-			store= (Z_LVAL_PP(store_mode) != 0);
 			break;
 		default:
 			WRONG_PARAM_COUNT;
@@ -1760,19 +1815,20 @@
 		
 		switch (Z_TYPE_PP(object)) {
 			case IS_OBJECT:
-				ce= Z_OBJCE_PP(object);
+				ce = Z_OBJCE_PP(object);
 				break;
-			default:
+			case IS_NULL:
+				break;
+			default: {
 				convert_to_string_ex(object);
 				zend_str_tolower(Z_STRVAL_PP(object), Z_STRLEN_PP(object));
-				zend_hash_find(EG(class_table), Z_STRVAL_PP(object), Z_STRLEN_PP(object)+1, (void **)&ce);
-
-				if (!ce) {
+				if (zend_hash_find(EG(class_table), Z_STRVAL_PP(object), Z_STRLEN_PP(object)+1, (void **)&ce) == FAILURE) {
 					php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Sybase:  Class %s has not been declared", Z_STRVAL_PP(object));
-					ce= ZEND_STANDARD_CLASS_DEF_PTR;
 				}
+			}
 		}
-		
+
+		/* Reset no. of arguments to 1 so that we can use INTERNAL_FUNCTION_PARAM_PASSTHRU */
 		ht= 1;
 	}
 	
@@ -1780,7 +1836,7 @@
 	if (Z_TYPE_P(return_value)==IS_ARRAY) {
 		object_and_properties_init(
 			return_value, 
-			object ? ce : ZEND_STANDARD_CLASS_DEF_PTR, 
+			ce ? ce : ZEND_STANDARD_CLASS_DEF_PTR, 
 			Z_ARRVAL_P(return_value)
 		);
 	}
@@ -1821,11 +1877,11 @@
 
 	/* Unbuffered ? */
 	if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS && Z_LVAL_PP(offset)>=result->num_rows) {
-		php_sybase_fetch_result_row(result, Z_LVAL_PP(offset));
+		php_sybase_fetch_result_row(result, Z_LVAL_PP(offset)+ 1);
 	}
 	
 	if (Z_LVAL_PP(offset)<0 || Z_LVAL_PP(offset)>=result->num_rows) {
-		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase:  Bad row offset");
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase:  Bad row offset %ld, must be betweem 0 and %d", Z_LVAL_PP(offset), result->num_rows - 1);
 		RETURN_FALSE;
 	}
 
