Browse Source

Added support for fetching and binding to blob fields

PHP-5.0
Ard Biesheuvel 22 years ago
parent
commit
2cc63714a0
  1. 130
      ext/pdo_firebird/firebird_statement.c

130
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(&param);
convert_to_string_ex(&param);
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;

Loading…
Cancel
Save