diff options
author | Ard Biesheuvel <abies@php.net> | 2004-06-14 10:56:49 +0000 |
---|---|---|
committer | Ard Biesheuvel <abies@php.net> | 2004-06-14 10:56:49 +0000 |
commit | 2cc63714a06a0a5c56249da1f97e621d33b92885 (patch) | |
tree | 789c8cfce6fcd1180efbce7af2ab7f6315399d35 /ext/pdo_firebird | |
parent | 533cdf740f57eea9ee8c19a06b76ba7d3c64bf51 (diff) | |
download | php-git-2cc63714a06a0a5c56249da1f97e621d33b92885.tar.gz |
Added support for fetching and binding to blob fields
Diffstat (limited to 'ext/pdo_firebird')
-rw-r--r-- | ext/pdo_firebird/firebird_statement.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 5d6e86fe4e..90ad2e13d6 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -205,6 +205,83 @@ static void set_param_type(enum pdo_param_type *param_type, XSQLVAR const *var) #define FETCH_BUF(buf,type,len) ((buf) = (buf) ? (buf) : \ emalloc((len) ? (len * sizeof(type)) : ((len) = sizeof(type)))) +/* fetch a blob into a fetch buffer */ +static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */ + unsigned long *len, ISC_QUAD *blob_id TSRMLS_DC) +{ + pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; + pdo_firebird_db_handle *H = S->H; + isc_blob_handle blobh = NULL; + static char bl_items[] = {isc_info_blob_total_length}; + char bl_info[20]; + unsigned short i; + int result = *len = 0; + + if (isc_open_blob(H->isc_status, &H->db, &H->tr, &blobh, blob_id)) { + RECORD_ERROR(stmt); + return 0; + } + + if (isc_blob_info(H->isc_status, &blobh, sizeof(bl_items), bl_items, + sizeof(bl_info), bl_info)) { + RECORD_ERROR(stmt); + goto fetch_blob_end; + } + + /* find total length of blob's data */ + for (i = 0; i < sizeof(bl_info); ) { + unsigned short item_len; + char item = bl_info[i++]; + + if (item == isc_info_end || item == isc_info_truncated || item == isc_info_error + || i >= sizeof(bl_info)) { + H->last_app_error = "Couldn't determine BLOB size"; + goto fetch_blob_end; + } + + item_len = (unsigned short) isc_vax_integer(&bl_info[i], 2); + + if (item == isc_info_blob_total_length) { + *len = isc_vax_integer(&bl_info[i+2], item_len); + break; + } + i += item_len+2; + } + + /* we've found the blob's length, now fetch! */ + + if (*len) { + unsigned long cur_len; + unsigned short seg_len; + ISC_STATUS stat; + + *ptr = S->fetch_buf[colno] = erealloc(*ptr, *len+1); + + for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) { + + unsigned short chunk_size = (*len-cur_len) > USHRT_MAX ? USHRT_MAX + : (unsigned short)(*len-cur_len); + + stat = isc_get_segment(H->isc_status, &blobh, &seg_len, chunk_size, &(*ptr)[cur_len]); + } + + (*ptr)[*len++] = '\0'; + + if (H->isc_status[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) { + H->last_app_error = "Error reading from BLOB"; + goto fetch_blob_end; + } + } + result = 1; + +fetch_blob_end: + if (isc_close_blob(H->isc_status, &blobh)) { + RECORD_ERROR(stmt); + return 0; + } + return result; +} + static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */ unsigned long *len TSRMLS_DC) { @@ -310,6 +387,9 @@ static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{ *ptr = FETCH_BUF(S->fetch_buf[colno], char, *len); *len = strftime(*ptr, *len, fmt, &t); break; + case SQL_BLOB: + return firebird_fetch_blob(stmt,colno,ptr,len, + (ISC_QUAD*)var->sqldata TSRMLS_CC); } } } @@ -317,6 +397,45 @@ static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{ } /* }}} */ +static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param TSRMLS_DC) +{ + pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; + pdo_firebird_db_handle *H = S->H; + isc_blob_handle h = NULL; + unsigned long put_cnt = 0, rem_cnt; + unsigned short chunk_size; + int result = 1; + + if (isc_create_blob(H->isc_status, &H->db, &H->tr, &h, blob_id)) { + RECORD_ERROR(stmt); + return 0; + } + + SEPARATE_ZVAL(¶m); + + convert_to_string_ex(¶m); + + for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size) { + + chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt; + + if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL_P(param)[put_cnt])) { + RECORD_ERROR(stmt); + result = 0; + break; + } + put_cnt += chunk_size; + } + + zval_dtor(param); + + if (isc_close_blob(H->isc_status, &h)) { + RECORD_ERROR(stmt); + return 0; + } + return result; +} + static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, /* {{{ */ enum pdo_param_event event_type TSRMLS_DC) { @@ -353,6 +472,17 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat *var->sqlind = 0; + switch (var->sqltype & ~1) { + case SQL_ARRAY: + stmt->error_code = PDO_ERR_NOT_IMPLEMENTED; + S->H->last_app_error = "Cannot bind to array field"; + return 0; + + case SQL_BLOB: + return firebird_bind_blob(stmt, (ISC_QUAD*)var->sqldata, + param->parameter TSRMLS_CC); + } + /* check if a NULL should be inserted */ switch (Z_TYPE_P(param->parameter)) { int force_null; |