diff options
Diffstat (limited to 'ext/pdo_firebird/firebird_statement.c')
-rw-r--r-- | ext/pdo_firebird/firebird_statement.c | 88 |
1 files changed, 58 insertions, 30 deletions
diff --git a/ext/pdo_firebird/firebird_statement.c b/ext/pdo_firebird/firebird_statement.c index 337ce3fb66..64968428bd 100644 --- a/ext/pdo_firebird/firebird_statement.c +++ b/ext/pdo_firebird/firebird_statement.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 7 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2015 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -98,9 +98,22 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt) /* {{{ */ break; } S->cursor_open = 0; - /* assume all params have been bound */ - if (isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION, S->in_sqlda)) { + /* allocate storage for the output data */ + if (S->out_sqlda.sqld) { + unsigned int i; + for (i = 0; i < S->out_sqlda.sqld; i++) { + XSQLVAR *var = &S->out_sqlda.sqlvar[i]; + var->sqlind = (void*)ecalloc(1, var->sqllen + 2 * sizeof(short)); + var->sqldata = &((char*)var->sqlind)[sizeof(short)]; + } + } + + if (S->statement_type == isc_info_sql_stmt_exec_procedure) { + if (isc_dsql_execute2(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION, S->in_sqlda, &S->out_sqlda)) { + break; + } + } else if (isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION, S->in_sqlda)) { break; } @@ -139,8 +152,8 @@ static int firebird_stmt_execute(pdo_stmt_t *stmt) /* {{{ */ } *S->name = 0; - S->cursor_open = (S->out_sqlda.sqln > 0); /* A cursor is opened, when more than zero columns returned */ - S->exhausted = !S->cursor_open; + S->cursor_open = S->out_sqlda.sqln && (S->statement_type != isc_info_sql_stmt_exec_procedure); + S->exhausted = !S->out_sqlda.sqln; /* There are data to fetch */ return 1; } while (0); @@ -162,6 +175,11 @@ static int firebird_stmt_fetch(pdo_stmt_t *stmt, /* {{{ */ strcpy(stmt->error_code, "HY000"); H->last_app_error = "Cannot fetch from a closed cursor"; } else if (!S->exhausted) { + if (S->statement_type == isc_info_sql_stmt_exec_procedure) { + stmt->row_count = 1; + S->exhausted = 1; + return 1; + } if (isc_dsql_fetch(H->isc_status, &S->stmt, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) { if (H->isc_status[0] && H->isc_status[1]) { RECORD_ERROR(stmt); @@ -169,9 +187,6 @@ static int firebird_stmt_fetch(pdo_stmt_t *stmt, /* {{{ */ S->exhausted = 1; return 0; } - if (S->statement_type == isc_info_sql_stmt_exec_procedure) { - S->exhausted = 1; - } stmt->row_count++; return 1; } @@ -188,17 +203,13 @@ static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */ int colname_len; char *cp; - /* allocate storage for the column */ - var->sqlind = (void*)ecalloc(1, var->sqllen + 2*sizeof(short)); - var->sqldata = &((char*)var->sqlind)[sizeof(short)]; - colname_len = (S->H->fetch_table_names && var->relname_length) ? (var->aliasname_length + var->relname_length + 1) : (var->aliasname_length); col->precision = -var->sqlscale; col->maxlen = var->sqllen; col->name = zend_string_alloc(colname_len, 0); - cp = col->name->val; + cp = ZSTR_VAL(col->name); if (colname_len > var->aliasname_length) { memmove(cp, var->relname, var->relname_length); cp += var->relname_length; @@ -223,7 +234,7 @@ static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ * { pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; pdo_firebird_db_handle *H = S->H; - isc_blob_handle blobh = NULL; + isc_blob_handle blobh = PDO_FIREBIRD_HANDLE_INITIALIZER; char const bl_item = isc_info_blob_total_length; char bl_info[20]; unsigned short i; @@ -367,7 +378,7 @@ static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, /* {{ break; case SQL_LONG: *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL); - *len = slprintf(*ptr, CHAR_BUF_LEN, "%ld", *(ISC_LONG*)var->sqldata); + *len = slprintf(*ptr, CHAR_BUF_LEN, "%d", *(ISC_LONG*)var->sqldata); break; case SQL_INT64: *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL); @@ -412,7 +423,8 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param) { pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data; pdo_firebird_db_handle *H = S->H; - isc_blob_handle h = NULL; + isc_blob_handle h = PDO_FIREBIRD_HANDLE_INITIALIZER; + zval data; zend_ulong put_cnt = 0, rem_cnt; unsigned short chunk_size; int result = 1; @@ -422,14 +434,16 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param) return 0; } - SEPARATE_ZVAL(param); - convert_to_string_ex(param); + data = *param; - for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size) { + if (Z_TYPE_P(param) != IS_STRING) { + zval_copy_ctor(&data); + convert_to_string(&data); + } + for (rem_cnt = Z_STRLEN(data); 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])) { + if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL(data)[put_cnt])) { RECORD_ERROR(stmt); result = 0; break; @@ -437,7 +451,9 @@ static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param) put_cnt += chunk_size; } - zval_dtor(param); + if (Z_TYPE_P(param) != IS_STRING) { + zval_dtor(&data); + } if (isc_close_blob(H->isc_status, &h)) { RECORD_ERROR(stmt); @@ -475,10 +491,10 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat for (i = 0; i < sqlda->sqld; ++i) { XSQLVAR *var = &sqlda->sqlvar[i]; - if ((var->aliasname_length && !strncasecmp(param->name->val, var->aliasname, - min(param->name->len, var->aliasname_length))) - || (var->sqlname_length && !strncasecmp(param->name->val, var->sqlname, - min(param->name->len, var->sqlname_length)))) { + if ((var->aliasname_length && !strncasecmp(ZSTR_VAL(param->name), var->aliasname, + min(ZSTR_LEN(param->name), var->aliasname_length))) + || (var->sqlname_length && !strncasecmp(ZSTR_VAL(param->name), var->sqlname, + min(ZSTR_LEN(param->name), var->sqlname_length)))) { param->paramno = i; break; } @@ -523,12 +539,13 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat } if (Z_TYPE_P(parameter) == IS_RESOURCE) { - php_stream *stm; + php_stream *stm = NULL; php_stream_from_zval_no_verify(stm, parameter); if (stm) { + zend_string *mem = php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0); zval_ptr_dtor(parameter); - ZVAL_STR(parameter, php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0)); + ZVAL_STR(parameter, mem ? mem : ZSTR_EMPTY_ALLOC()); } else { pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource"); return 0; @@ -541,8 +558,19 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat S->H->last_app_error = "Cannot bind to array field"; return 0; - case SQL_BLOB: + case SQL_BLOB: { + if (Z_TYPE_P(parameter) == IS_NULL) { + /* Check if field allow NULL values */ + if (~var->sqltype & 1) { + strcpy(stmt->error_code, "HY105"); + S->H->last_app_error = "Parameter requires non-null value"; + return 0; + } + *var->sqlind = -1; + return 1; + } return firebird_bind_blob(stmt, (ISC_QUAD*)var->sqldata, parameter); + } } /* check if a NULL should be inserted */ @@ -631,7 +659,7 @@ static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_dat } case PDO_PARAM_EVT_NORMALIZE: if (!param->is_param) { - char *s = param->name->val; + char *s = ZSTR_VAL(param->name); while (*s != '\0') { *s = toupper(*s); s++; |