abies Fri Sep 5 10:21:26 2003 EDT Modified files: /php-src/ext/interbase interbase.c Log: Be more relaxed about dimensions of array arguments Index: php-src/ext/interbase/interbase.c diff -u php-src/ext/interbase/interbase.c:1.175 php-src/ext/interbase/interbase.c:1.176 --- php-src/ext/interbase/interbase.c:1.175 Thu Sep 4 18:37:14 2003 +++ php-src/ext/interbase/interbase.c Fri Sep 5 10:21:25 2003 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: interbase.c,v 1.175 2003/09/04 22:37:14 abies Exp $ */ +/* $Id: interbase.c,v 1.176 2003/09/05 14:21:25 abies Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -716,7 +716,7 @@ php_info_print_table_start(); php_info_print_table_row(2, "Interbase Support", "enabled"); - php_info_print_table_row(2, "Revision", "$Revision: 1.175 $"); + php_info_print_table_row(2, "Revision", "$Revision: 1.176 $"); #ifdef COMPILE_DL_INTERBASE php_info_print_table_row(2, "Dynamic Module", "Yes"); #endif @@ -1105,7 +1105,7 @@ for (i = 0; i < sqlda->sqld; i++, var++) { unsigned short dim; - unsigned long ar_size; + unsigned long ar_size = 1; if ((var->sqltype & ~1) == SQL_ARRAY) { ISC_ARRAY_DESC *ar_desc = &IB_ARRAY[i].ar_desc; @@ -1121,7 +1121,7 @@ case blr_text: case blr_text2: IB_ARRAY[i].el_type = SQL_TEXT; - IB_ARRAY[i].el_size = ar_desc->array_desc_length + 1; + IB_ARRAY[i].el_size = ar_desc->array_desc_length; break; case blr_short: IB_ARRAY[i].el_type = SQL_SHORT; @@ -1165,8 +1165,12 @@ break; #endif case blr_varying: - case blr_varying2: /* changed to SQL_TEXT ? */ - /* sql_type = SQL_VARYING; Why? FIXME: ??? */ + case blr_varying2: + /** + * IB has a strange way of handling VARCHAR arrays. It doesn't store + * the length in the first short, as with VARCHAR fields. It does, + * however, expect the extra short to be allocated for each element. + */ IB_ARRAY[i].el_type = SQL_TEXT; IB_ARRAY[i].el_size = ar_desc->array_desc_length + sizeof(short); break; @@ -1174,7 +1178,12 @@ case blr_blob_id: case blr_cstring: case blr_cstring2: - /* FIXME */ + /** + * These types are mentioned as array types in the manual, but I + * wouldn't know how to create an array field with any of these + * types. I assume these types are not applicable to arrays, and + * were mentioned erroneously. + */ default: _php_ibase_module_error("Unsupported array type %d in relation '%s' column '%s'" TSRMLS_CC, ar_desc->array_desc_dtype, var->relname, var->sqlname); efree(IB_ARRAY); @@ -1182,7 +1191,7 @@ return FAILURE; } /* switch array_desc_type */ - ar_size = 1; /* calculate elements count */ + /* calculate elements count */ for (dim = 0; dim < ar_desc->array_desc_dimensions; dim++) { ar_size *= 1 + ar_desc->array_desc_bounds[dim].array_bound_upper - ar_desc->array_desc_bounds[dim].array_bound_lower; } @@ -1323,48 +1332,64 @@ /* {{{ _php_ibase_bind_array() */ static int _php_ibase_bind_array(zval *val, char *buf, unsigned long buf_size, ibase_array *array, int dim TSRMLS_DC) { - int - u_bound = array->ar_desc.array_desc_bounds[dim].array_bound_upper, + zval null_val, *pnull_val = &null_val; + int u_bound = array->ar_desc.array_desc_bounds[dim].array_bound_upper, l_bound = array->ar_desc.array_desc_bounds[dim].array_bound_lower, dim_len = 1 + u_bound - l_bound; + ZVAL_NULL(pnull_val); + if (dim < array->ar_desc.array_desc_dimensions) { unsigned long slice_size = buf_size / dim_len; unsigned short i; + zval **subval = &val; - if (Z_TYPE_P(val) != IS_ARRAY || zend_hash_num_elements(Z_ARRVAL_P(val)) != dim_len) { - _php_ibase_module_error("Array parameter binding argument must fit perfectly (mismatch at depth %d)" TSRMLS_CC, dim+1); - return FAILURE; + if (Z_TYPE_P(val) == IS_ARRAY) { + zend_hash_internal_pointer_reset(Z_ARRVAL_P(val)); } - zend_hash_internal_pointer_reset(Z_ARRVAL_P(val)); - for (i = 0; i < dim_len; ++i) { - zval **subval; - - if (zend_hash_get_current_data(Z_ARRVAL_P(val), (void *) &subval) == FAILURE || - _php_ibase_bind_array(*subval, buf, slice_size, array, dim + 1 TSRMLS_CC) == FAILURE) { + if (Z_TYPE_P(val) == IS_ARRAY && + zend_hash_get_current_data(Z_ARRVAL_P(val), (void *) &subval) == FAILURE) + { + subval = &pnull_val; + } + + if (_php_ibase_bind_array(*subval, buf, slice_size, array, dim + 1 TSRMLS_CC) == FAILURE) + { return FAILURE; } buf += slice_size; - zend_hash_move_forward(Z_ARRVAL_P(val)); + + if (Z_TYPE_P(val) == IS_ARRAY) { + zend_hash_move_forward(Z_ARRVAL_P(val)); + } } - zend_hash_internal_pointer_reset(Z_ARRVAL_P(val)); + if (Z_TYPE_P(val) == IS_ARRAY) { + zend_hash_internal_pointer_reset(Z_ARRVAL_P(val)); + } } else { /* expect a single value */ - if (array->ar_desc.array_desc_scale < 0) { + if (Z_TYPE_P(val) == IS_NULL) { + memset(buf, 0, buf_size); + } else if (array->ar_desc.array_desc_scale < 0) { /* no coercion for array types */ + double l; - switch (array->el_type) { - double l; + convert_to_double(val); + + if (Z_DVAL_P(val) > 0) { + l = Z_DVAL_P(val) * pow(10, -array->ar_desc.array_desc_scale) + .5; + } else { + l = Z_DVAL_P(val) * pow(10, -array->ar_desc.array_desc_scale) - .5; + } + switch (array->el_type) { case SQL_SHORT: - convert_to_double(val); - l = Z_DVAL_P(val) * pow(10, -array->ar_desc.array_desc_scale); if (l > SHRT_MAX || l < SHRT_MIN) { _php_ibase_module_error("Array parameter exceeds field width" TSRMLS_CC); return FAILURE; @@ -1372,8 +1397,6 @@ *(short*) buf = (short) l; break; case SQL_LONG: - convert_to_double(val); - l = Z_DVAL_P(val) * pow(10, -array->ar_desc.array_desc_scale); if (l > ISC_LONG_MAX || l < ISC_LONG_MIN) { _php_ibase_module_error("Array parameter exceeds field width" TSRMLS_CC); return FAILURE; @@ -1386,12 +1409,16 @@ long double l; convert_to_string(val); - + if (!sscanf(Z_STRVAL_P(val), "%" LL_MASK "f", &l)) { _php_ibase_module_error("Cannot convert '%s' to long double" TSRMLS_CC, Z_STRVAL_P(val)); return FAILURE; + } + + if (l > 0) { + *(ISC_INT64 *) buf = (ISC_INT64) (l * pow(10, -array->ar_desc.array_desc_scale) + .5); } else { - *(ISC_INT64 *) buf = (ISC_INT64)(l * pow(10, -array->ar_desc.array_desc_scale)); + *(ISC_INT64 *) buf = (ISC_INT64) (l * pow(10, -array->ar_desc.array_desc_scale) - .5); } } break; @@ -2559,7 +2586,7 @@ goto _sql_long; #else if (scale == 0) { - l = sprintf(string_data, "%.0" LL_MASK "d", *(ISC_INT64 *) data); + l = sprintf(string_data, "%" LL_MASK "d", *(ISC_INT64 *) data); ZVAL_STRINGL(val,string_data,l,1); } else { ISC_INT64 n = *(ISC_INT64 *) data, f = scales[-scale]; @@ -2698,6 +2725,14 @@ ib_array->ar_desc.array_desc_scale, flag TSRMLS_CC) == FAILURE) { return FAILURE; + } + + /* fix for peculiar handling of VARCHAR arrays; + truncate the field to the cstring length */ + if (ib_array->ar_desc.array_desc_dtype == blr_varying || + ib_array->ar_desc.array_desc_dtype == blr_varying2) { + + Z_STRLEN_P(ar_zval) = strlen(Z_STRVAL_P(ar_zval)); } } return SUCCESS;
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php