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]);
}
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);
}
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);
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;
}
*/
- /* i= result->num_rows++; */
result->num_rows++;
i= result->store ? result->num_rows- 1 : 0;
if (i >= result->blocks_initialized*SYBASE_ROWS_BLOCK) {
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;
+ }
}
}
}
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;
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;
switch (Z_TYPE_PP(object)) {
case IS_OBJECT:
- ce= Z_OBJCE_PP(object);
+ ce = Z_OBJCE_PP(object);
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);
+ case IS_NULL:
+ break;
+ default: {
+ zend_class_entry **pce = NULL;
- if (!ce) {
+ convert_to_string_ex(object);
+ if (zend_lookup_class(Z_STRVAL_PP(object), Z_STRLEN_PP(object), &pce TSRMLS_CC) == 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;
+ } else {
+ ce = *pce;
}
+ }
}
-
+
+ /* Reset no. of arguments to 1 so that we can use INTERNAL_FUNCTION_PARAM_PASSTHRU */
ht= 1;
}
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)
);
}
/* 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;
}
convert_to_long_ex(offset);
field_offset = Z_LVAL_PP(offset);
- /* Unbuffered ? */
- if (result->last_retcode != CS_END_DATA && result->last_retcode != CS_END_RESULTS && field_offset>=result->num_rows) {
- php_sybase_fetch_result_row(result, field_offset);
- }
-
if (field_offset<0 || field_offset >= result->num_fields) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase: Bad column offset");
RETURN_FALSE;