From b3b68834b5eef579883b40c93bfd7f86c0166914 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 3 Sep 2003 15:15:30 +0000 Subject: [PATCH] Fix binding of 16-bit NUMERIC parameters --- ext/interbase/interbase.c | 290 +++++++++++++++++--------------------- 1 file changed, 126 insertions(+), 164 deletions(-) diff --git a/ext/interbase/interbase.c b/ext/interbase/interbase.c index 7ff197441a..062d05c2d1 100644 --- a/ext/interbase/interbase.c +++ b/ext/interbase/interbase.c @@ -1311,190 +1311,152 @@ static int _php_ibase_blob_add(zval **string_arg, ibase_blob *ib_blob TSRMLS_DC) Bind parameter placeholders in a previously prepared query */ static int _php_ibase_bind(XSQLDA *sqlda, zval **b_vars, BIND_BUF *buf, ibase_query *ib_query TSRMLS_DC) { - XSQLVAR *var; - zval *b_var; - int i; + int i , rv = SUCCESS; + XSQLVAR *var = sqlda->sqlvar; - var = sqlda->sqlvar; - for (i = 0; i < sqlda->sqld; var++, i++) { /* bound vars */ + for (i = 0; i < sqlda->sqld; ++var, ++i) { /* bound vars */ - buf[i].sqlind = 0; + zval *b_var = b_vars[i]; + var->sqlind = &buf[i].sqlind; - b_var = b_vars[i]; if (Z_TYPE_P(b_var) == IS_NULL) { - static char nothing[64]; - static short null_flag = -1; - var->sqldata = nothing; - var->sqltype |= 1; - var->sqlind = &null_flag; - if (var->sqllen > 64) { - var->sqllen = 64; + + if ((var->sqltype & 1) != 1) { + _php_ibase_module_error("Parameter %d must have a value" TSRMLS_CC, i+1); + rv = FAILURE; } - } else - - switch (var->sqltype & ~1) { - case SQL_TEXT: /* direct to variable */ - case SQL_VARYING: - convert_to_string(b_var); - var->sqldata = (void *) Z_STRVAL_P(b_var); - var->sqllen = Z_STRLEN_P(b_var); - var->sqltype = SQL_TEXT + (var->sqltype & 1); - break; - 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("Field %*s overflow" TSRMLS_CC, var->aliasname_length, var->aliasname); - return FAILURE; - } - buf[i].val.sval = (short) Z_LVAL_P(b_var); - var->sqldata = (void *) (&buf[i].val.sval); - break; - case SQL_LONG: - if (var->sqlscale < 0) { - /* - DECIMAL or NUMERIC field stored internally as scaled integer. - Coerce it to string and let InterBase's internal routines - handle it. - */ - convert_to_string(b_var); - var->sqldata = (void *) Z_STRVAL_P(b_var); - var->sqllen = Z_STRLEN_P(b_var); - var->sqltype = SQL_TEXT; - } else { - convert_to_long(b_var); - var->sqldata = (void *) (&Z_LVAL_P(b_var)); - } - break; - case SQL_FLOAT: - convert_to_double(b_var); - buf[i].val.fval = (float) Z_DVAL_P(b_var); - var->sqldata = (void *) (&buf[i].val.fval); - break; - case SQL_DOUBLE: /* direct to variable */ - convert_to_double(b_var); - var->sqldata = (void *) (&Z_DVAL_P(b_var)); - break; -#ifdef SQL_INT64 - case SQL_INT64: + + buf[i].sqlind = -1; + } else { + buf[i].sqlind = 0; + + if (var->sqlscale < 0) { /* - Just let InterBase's internal routines handle it. - Besides, it might even have originally been a string - to avoid rounding errors... + DECIMAL or NUMERIC field are stored internally as scaled integers. + Coerce it to string and let InterBase's internal routines handle it. */ - convert_to_string(b_var); - var->sqldata = (void *) Z_STRVAL_P(b_var); - var->sqllen = Z_STRLEN_P(b_var); var->sqltype = SQL_TEXT; - break; -#endif -#ifndef SQL_TIMESTAMP - case SQL_DATE: -#else - case SQL_TIMESTAMP: - case SQL_TYPE_DATE: - case SQL_TYPE_TIME: -#endif -#ifndef HAVE_STRPTIME + } + + switch (var->sqltype & ~1) { + 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; + } + buf[i].val.sval = (short) Z_LVAL_P(b_var); + var->sqldata = (void *) &buf[i].val.sval; + break; + case SQL_LONG: + convert_to_long(b_var); + var->sqldata = (void *) &Z_LVAL_P(b_var); + break; + case SQL_FLOAT: + convert_to_double(b_var); + buf[i].val.fval = (float) Z_DVAL_P(b_var); + var->sqldata = (void *) &buf[i].val.fval; + break; + case SQL_DOUBLE: + convert_to_double(b_var); + var->sqldata = (void *) &Z_DVAL_P(b_var); + break; #ifndef SQL_TIMESTAMP - /* Parsing doesn't seem to happen with older versions... */ - { - struct tm t; - int n; - - t.tm_year = t.tm_mon = t.tm_mday = t.tm_hour = t.tm_min = t.tm_sec = 0; - + case SQL_DATE: convert_to_string(b_var); - - n = sscanf(Z_STRVAL_P(b_var), "%d%*[/]%d%*[/]%d %d%*[:]%d%*[:]%d", &t.tm_mon, &t.tm_mday, &t.tm_year, &t.tm_hour, &t.tm_min, &t.tm_sec); - - if (n != 3 && n != 6) { - _php_ibase_module_error("Invalid date/time format: Expected 3 or 6 fields, got %d. Use format m/d/Y H:i:s. You gave '%s'" TSRMLS_CC, n, Z_STRVAL_P(b_var)); - return FAILURE; - } - t.tm_year -= 1900; - t.tm_mon--; - isc_encode_date(&t, &buf[i].val.qval); - var->sqldata = (void *) (&buf[i].val.qval); - } + { + struct tm t; +#ifdef HAVE_STRPTIME + strptime(Z_STRVAL_P(b_var), IBG(timestampformat), &t); #else - /* - Once again, InterBase's internal parsing routines - seems to be a good solution... Might change this on - platforms that have strptime()? Code is there and works, - but the functions existence is not yet tested... - ask Sascha? - */ - convert_to_string(b_var); - var->sqldata = (void *) Z_STRVAL_P(b_var); - var->sqllen = Z_STRLEN_P(b_var); - var->sqltype = SQL_TEXT; + /* Parsing doesn't seem to happen with older versions... */ + int n; + + t.tm_year = t.tm_mon = t.tm_mday = t.tm_hour = t.tm_min = t.tm_sec = 0; + + n = sscanf(Z_STRVAL_P(b_var), "%d%*[/]%d%*[/]%d %d%*[:]%d%*[:]%d", &t.tm_mon, &t.tm_mday, &t.tm_year, &t.tm_hour, &t.tm_min, &t.tm_sec); + + if (n != 3 && n != 6) { + _php_ibase_module_error("Parameter %d: invalid date/time format (expected 3 or 6 fields, got %d. Use format m/d/Y H:i:s. You gave '%s')" TSRMLS_CC, i+1, n, Z_STRVAL_P(b_var)); + rv = FAILURE; + } + t.tm_year -= 1900; + t.tm_mon--; #endif + isc_encode_date(&t, &buf[i].val.qval); + var->sqldata = (void *) (&buf[i].val.qval); + } #else - { - struct tm t; - - convert_to_string(b_var); -#ifndef SQL_TIMESTAMP - strptime(Z_STRVAL_P(b_var), IBG(timestampformat), &t); - isc_encode_date(&t, &buf[i].val.qval); - var->sqldata = (void *) (&buf[i].val.qval); -#else - switch (var->sqltype & ~1) { - case SQL_TIMESTAMP: - strptime(Z_STRVAL_P(b_var), IBG(timestampformat), &t); - isc_encode_timestamp(&t, &buf[i].val.tsval); - var->sqldata = (void *) (&buf[i].val.tsval); - break; - case SQL_TYPE_DATE: - strptime(Z_STRVAL_P(b_var), IBG(dateformat), &t); - isc_encode_sql_date(&t, &buf[i].val.dtval); - var->sqldata = (void *) (&buf[i].val.dtval); - break; - case SQL_TYPE_TIME: - strptime(Z_STRVAL_P(b_var), IBG(timeformat), &t); - isc_encode_sql_time(&t, &buf[i].val.tmval); - var->sqldata = (void *) (&buf[i].val.tmval); - break; +#ifdef HAVE_STRPTIME + case SQL_TIMESTAMP: + case SQL_TYPE_DATE: + case SQL_TYPE_TIME: + { + struct tm t; + + convert_to_string(b_var); + + switch (var->sqltype & ~1) { + case SQL_TIMESTAMP: + strptime(Z_STRVAL_P(b_var), IBG(timestampformat), &t); + isc_encode_timestamp(&t, &buf[i].val.tsval); + var->sqldata = (void *) (&buf[i].val.tsval); + break; + case SQL_TYPE_DATE: + strptime(Z_STRVAL_P(b_var), IBG(dateformat), &t); + isc_encode_sql_date(&t, &buf[i].val.dtval); + var->sqldata = (void *) (&buf[i].val.dtval); + break; + case SQL_TYPE_TIME: + strptime(Z_STRVAL_P(b_var), IBG(timeformat), &t); + isc_encode_sql_time(&t, &buf[i].val.tmval); + var->sqldata = (void *) (&buf[i].val.tmval); + break; + } } #endif - } #endif - break; - case SQL_BLOB: - - 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)) { - - ibase_blob ib_blob = { NULL, {0, 0}, BLOB_INPUT }; - - 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 (_php_ibase_blob_add(&b_var, &ib_blob TSRMLS_CC) != SUCCESS) { - return FAILURE; - } + break; + case SQL_BLOB: - if (isc_close_blob(IB_STATUS, &ib_blob.bl_handle)) { - _php_ibase_error(TSRMLS_C); - return FAILURE; + 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)) { + + ibase_blob ib_blob = { NULL, {0, 0}, BLOB_INPUT }; + + 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 (_php_ibase_blob_add(&b_var, &ib_blob TSRMLS_CC) != SUCCESS) { + return FAILURE; + } + + 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; } - buf[i].val.qval = ib_blob.bl_qd; - } - var->sqldata = (void *) &buf[i].val.qval; - break; - case SQL_ARRAY: - _php_ibase_module_error("Binding arrays not supported yet" TSRMLS_CC); - return FAILURE; - break; - } /* switch */ + var->sqldata = (void *) &buf[i].val.qval; + break; + case SQL_ARRAY: + _php_ibase_module_error("Parameter %d: arrays not supported" TSRMLS_CC, i+1); + rv = FAILURE; + break; + default: + convert_to_string(b_var); + var->sqldata = Z_STRVAL_P(b_var); + var->sqllen = Z_STRLEN_P(b_var); + var->sqltype = SQL_TEXT; + } /* switch */ + } /* if */ } /* for */ - - return SUCCESS; + return rv; } /* }}} */ -- 2.40.0