summaryrefslogtreecommitdiff
path: root/ext/interbase
diff options
context:
space:
mode:
authorArd Biesheuvel <abies@php.net>2004-05-12 15:16:51 +0000
committerArd Biesheuvel <abies@php.net>2004-05-12 15:16:51 +0000
commit8428d0088c7091cbb8ee7120a319fac7ad53793f (patch)
tree9bd99912c6011290bca6651d91a178741976ce40 /ext/interbase
parentafc9cb151bec01d3d3a9a8f353a35940495e2e5a (diff)
downloadphp-git-8428d0088c7091cbb8ee7120a319fac7ad53793f.tar.gz
Fixed a couple of inconsistencies in param binding
# Previously, empty strings were either rejected (for scaled integers) # or silently converted to 0 (unscaled integers & floats). Also, in some # cases, null zvals were converted to empty strings, which were # consequently rejected as unconvertible values. # In the new situation, empty strings will be handled as NULLs for # fields that cannot distinguish between the two (numeric/date/time). # Additionally, all range and value checking is now carried out by the # database, so there is a consistent interface for error handling.
Diffstat (limited to 'ext/interbase')
-rw-r--r--ext/interbase/ibase_query.c283
1 files changed, 133 insertions, 150 deletions
diff --git a/ext/interbase/ibase_query.c b/ext/interbase/ibase_query.c
index c7ae9260aa..463bcd66c5 100644
--- a/ext/interbase/ibase_query.c
+++ b/ext/interbase/ibase_query.c
@@ -618,182 +618,165 @@ static int _php_ibase_bind(XSQLDA *sqlda, zval ***b_vars, BIND_BUF *buf, /* {{{
var->sqlind = &buf[i].sqlind;
- if (Z_TYPE_P(b_var) != IS_NULL) {
- buf[i].sqlind = 0;
-
- if (var->sqlscale < 0) {
- /*
- DECIMAL or NUMERIC field are stored internally as scaled integers.
- Coerce it to string and let InterBase's internal routines handle it.
- */
- goto php_ibase_bind_default;
- }
+ /* check if a NULL should be inserted */
+ switch (Z_TYPE_P(b_var)) {
+ int force_null;
+
+ case IS_STRING:
+
+ force_null = 0;
+
+ /* for these types, an empty string can be handled like a NULL value */
+ switch (var->sqltype & ~1) {
+ case SQL_SHORT:
+ case SQL_LONG:
+ case SQL_INT64:
+ case SQL_FLOAT:
+ case SQL_DOUBLE:
+ case SQL_TIMESTAMP:
+ case SQL_TYPE_DATE:
+ case SQL_TYPE_TIME:
+ force_null = (Z_STRLEN_P(b_var) == 0);
+ }
- var->sqldata = (void*)&buf[i];
+ if (! force_null) break;
- switch (var->sqltype & ~1) {
- struct tm t;
+ case IS_NULL:
- case SQL_SHORT:
- convert_to_long(b_var);
- if (Z_LVAL_P(b_var) > SHRT_MAX || Z_LVAL_P(b_var) < SHRT_MIN) {
- _php_ibase_module_error("Parameter %d exceeds field width" TSRMLS_CC, i+1);
- rv = FAILURE;
- break;
- }
- buf[i].val.sval = (short) Z_LVAL_P(b_var);
- break;
- case SQL_LONG:
- convert_to_long(b_var);
-#if (SIZEOF_LONG > 4)
- /* ISC_LONG is always 32-bit */
- if (Z_LVAL_P(b_var) > ISC_LONG_MAX || Z_LVAL_P(b_var) < ISC_LONG_MIN) {
- _php_ibase_module_error("Parameter %d exceeds field width" TSRMLS_CC, i+1);
- rv = FAILURE;
- break;
- }
-#endif
- buf[i].val.lval = (ISC_LONG) Z_LVAL_P(b_var);
- break;
-#if (SIZEOF_LONG == 8)
- case SQL_INT64:
- convert_to_long(b_var);
- var->sqldata = (void *) &Z_LVAL_P(b_var);
- break;
-#endif
- case SQL_FLOAT:
- convert_to_double(b_var);
- buf[i].val.fval = (float) Z_DVAL_P(b_var);
- break;
- case SQL_DOUBLE:
- convert_to_double(b_var);
- var->sqldata = (void *) &Z_DVAL_P(b_var);
- break;
+ /* complain if this field doesn't allow NULL values */
+ if (! (var->sqltype & 1)) {
+ _php_ibase_module_error("Parameter %d: non-empty value required" TSRMLS_CC, i+1);
+ rv = FAILURE;
+ } else {
+ buf[i].sqlind = -1;
+ }
- case SQL_TIMESTAMP:
- case SQL_TYPE_DATE:
- case SQL_TYPE_TIME:
- if (Z_TYPE_P(b_var) == IS_LONG) {
- /* insert timestamp directly */
- t = *gmtime(&Z_LVAL_P(b_var));
- } else {
-#ifndef HAVE_STRPTIME
- goto php_ibase_bind_default; /* let IB string handling take over */
-#else
- convert_to_string(b_var);
+ if (var->sqltype & SQL_ARRAY) ++array_cnt;
- switch (var->sqltype & ~1) {
- default: /* == case SQL_TIMESTAMP/SQL_DATE: */
- strptime(Z_STRVAL_P(b_var), IBG(timestampformat), &t);
- break;
- case SQL_TYPE_DATE:
- strptime(Z_STRVAL_P(b_var), IBG(dateformat), &t);
- break;
- case SQL_TYPE_TIME:
- strptime(Z_STRVAL_P(b_var), IBG(timeformat), &t);
- break;
- }
-#endif
- }
+ continue;
+ }
+
+ /* if we make it to this point, we must provide a value for the parameter */
+
+ buf[i].sqlind = 0;
+
+ var->sqldata = (void*)&buf[i].val;
+
+ switch (var->sqltype & ~1) {
+ struct tm t;
+
+ case SQL_TIMESTAMP:
+ case SQL_TYPE_DATE:
+ case SQL_TYPE_TIME:
+ if (Z_TYPE_P(b_var) == IS_LONG) {
+ /* insert timestamp directly */
+ t = *gmtime(&Z_LVAL_P(b_var));
+ } else {
+#ifdef HAVE_STRPTIME
+ char *format = IBG(timestampformat);
+
+ convert_to_string(b_var);
switch (var->sqltype & ~1) {
- default: /* == case SQL_TIMESTAMP */
- isc_encode_timestamp(&t, &buf[i].val.tsval);
- break;
case SQL_TYPE_DATE:
- isc_encode_sql_date(&t, &buf[i].val.dtval);
+ format = IBG(dateformat);
break;
case SQL_TYPE_TIME:
- isc_encode_sql_time(&t, &buf[i].val.tmval);
- break;
+ format = IBG(timeformat);
}
- break;
- case SQL_BLOB:
+ if (! strptime(Z_STRVAL_P(b_var), format, &t)) {
+ /* strptime() cannot handle it, so let IB have a try */
+ break;
+ }
+#else /* ifndef HAVE_STRPTIME */
+ break; /* let IB parse it as a string */
+#endif
+ }
- convert_to_string(b_var);
+ switch (var->sqltype & ~1) {
+ default: /* == case SQL_TIMESTAMP */
+ isc_encode_timestamp(&t, &buf[i].val.tsval);
+ break;
+ case SQL_TYPE_DATE:
+ isc_encode_sql_date(&t, &buf[i].val.dtval);
+ break;
+ case SQL_TYPE_TIME:
+ isc_encode_sql_time(&t, &buf[i].val.tmval);
+ break;
+ }
+ continue;
- if (Z_STRLEN_P(b_var) != BLOB_ID_LEN ||
- !_php_ibase_string_to_quad(Z_STRVAL_P(b_var), &buf[i].val.qval)) {
+ case SQL_BLOB:
- ibase_blob ib_blob = { NULL, BLOB_INPUT };
+ convert_to_string(b_var);
- if (isc_create_blob(IB_STATUS, &ib_query->link->handle,
- &ib_query->trans->handle, &ib_blob.bl_handle, &ib_blob.bl_qd)) {
- _php_ibase_error(TSRMLS_C);
- return FAILURE;
- }
+ if (Z_STRLEN_P(b_var) != BLOB_ID_LEN ||
+ !_php_ibase_string_to_quad(Z_STRVAL_P(b_var), &buf[i].val.qval)) {
- if (_php_ibase_blob_add(&b_var, &ib_blob TSRMLS_CC) != SUCCESS) {
- return FAILURE;
- }
+ ibase_blob ib_blob = { NULL, BLOB_INPUT };
- if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) {
- _php_ibase_error(TSRMLS_C);
- return FAILURE;
- }
- buf[i].val.qval = ib_blob.bl_qd;
+ if (isc_create_blob(IB_STATUS, &ib_query->link->handle,
+ &ib_query->trans->handle, &ib_blob.bl_handle, &ib_blob.bl_qd)) {
+ _php_ibase_error(TSRMLS_C);
+ return FAILURE;
}
- break;
- case SQL_ARRAY:
- if (Z_TYPE_P(b_var) != IS_ARRAY) {
- convert_to_string(b_var);
- if (Z_STRLEN_P(b_var) != BLOB_ID_LEN ||
- !_php_ibase_string_to_quad(Z_STRVAL_P(b_var), &buf[i].val.qval)) {
+ if (_php_ibase_blob_add(&b_var, &ib_blob TSRMLS_CC) != SUCCESS) {
+ return FAILURE;
+ }
- _php_ibase_module_error("Parameter %d: invalid array ID" TSRMLS_CC,i+1);
- rv = FAILURE;
- }
- } else {
- /* convert the array data into something IB can understand */
- ibase_array *ar = &ib_query->in_array[array_cnt];
- void *array_data = emalloc(ar->ar_size);
- ISC_QUAD array_id = { 0, 0 };
-
- if (FAILURE == _php_ibase_bind_array(b_var, array_data, ar->ar_size,
- ar, 0 TSRMLS_CC)) {
- _php_ibase_module_error("Parameter %d: failed to bind array argument"
- TSRMLS_CC,i+1);
- efree(array_data);
- rv = FAILURE;
- break;
- }
+ if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) {
+ _php_ibase_error(TSRMLS_C);
+ return FAILURE;
+ }
+ buf[i].val.qval = ib_blob.bl_qd;
+ }
+ continue;
- if (isc_array_put_slice(IB_STATUS, &ib_query->link->handle, &ib_query->trans->handle,
- &array_id, &ar->ar_desc, array_data, &ar->ar_size)) {
- _php_ibase_error(TSRMLS_C);
- efree(array_data);
- return FAILURE;
- }
- buf[i].val.qval = array_id;
+ case SQL_ARRAY:
+
+ if (Z_TYPE_P(b_var) != IS_ARRAY) {
+ convert_to_string(b_var);
+
+ if (Z_STRLEN_P(b_var) != BLOB_ID_LEN ||
+ !_php_ibase_string_to_quad(Z_STRVAL_P(b_var), &buf[i].val.qval)) {
+
+ _php_ibase_module_error("Parameter %d: invalid array ID" TSRMLS_CC,i+1);
+ rv = FAILURE;
+ }
+ } else {
+ /* convert the array data into something IB can understand */
+ ibase_array *ar = &ib_query->in_array[array_cnt];
+ void *array_data = emalloc(ar->ar_size);
+ ISC_QUAD array_id = { 0, 0 };
+
+ if (FAILURE == _php_ibase_bind_array(b_var, array_data, ar->ar_size,
+ ar, 0 TSRMLS_CC)) {
+ _php_ibase_module_error("Parameter %d: failed to bind array argument"
+ TSRMLS_CC,i+1);
efree(array_data);
- }
- ++array_cnt;
- break;
-php_ibase_bind_default:
- /* empty strings should be coerced to NULL for non-text types */
- if (Z_TYPE_P(b_var) == IS_STRING && Z_STRLEN_P(b_var) == 0) {
- ZVAL_NULL(b_var);
- break;
+ rv = FAILURE;
+ continue;
}
- default:
- convert_to_string(b_var);
- var->sqldata = Z_STRVAL_P(b_var);
- var->sqllen = Z_STRLEN_P(b_var);
- var->sqltype = SQL_TEXT;
+ if (isc_array_put_slice(IB_STATUS, &ib_query->link->handle, &ib_query->trans->handle,
+ &array_id, &ar->ar_desc, array_data, &ar->ar_size)) {
+ _php_ibase_error(TSRMLS_C);
+ efree(array_data);
+ return FAILURE;
+ }
+ buf[i].val.qval = array_id;
+ efree(array_data);
+ }
+ ++array_cnt;
+ continue;
} /* switch */
- } /* if */
- if (Z_TYPE_P(b_var) == IS_NULL) {
- if (! (var->sqltype & 1)) {
- _php_ibase_module_error("Parameter %d must have a value" TSRMLS_CC, i+1);
- rv = FAILURE;
- }
- buf[i].sqlind = -1;
-
- if (var->sqltype & SQL_ARRAY) ++array_cnt;
- }
+ /* we end up here if none of the switch cases handled the field */
+ convert_to_string(b_var);
+ var->sqldata = Z_STRVAL_P(b_var);
+ var->sqllen = Z_STRLEN_P(b_var);
+ var->sqltype = SQL_TEXT;
} /* for */
return rv;
}