root/ext/pdo_firebird/firebird_statement.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. free_sqlda
  2. firebird_stmt_dtor
  3. firebird_stmt_execute
  4. firebird_stmt_fetch
  5. firebird_stmt_describe
  6. firebird_fetch_blob
  7. firebird_stmt_get_col
  8. firebird_bind_blob
  9. firebird_stmt_param_hook
  10. firebird_stmt_set_attribute
  11. firebird_stmt_get_attribute
  12. firebird_stmt_cursor_closer

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 7                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 1997-2016 The PHP Group                                |
   6   +----------------------------------------------------------------------+
   7   | This source file is subject to version 3.01 of the PHP license,      |
   8   | that is bundled with this package in the file LICENSE, and is        |
   9   | available through the world-wide-web at the following url:           |
  10   | http://www.php.net/license/3_01.txt                                  |
  11   | If you did not receive a copy of the PHP license and are unable to   |
  12   | obtain it through the world-wide-web, please send a note to          |
  13   | license@php.net so we can mail you a copy immediately.               |
  14   +----------------------------------------------------------------------+
  15   | Author: Ard Biesheuvel <abies@php.net>                               |
  16   +----------------------------------------------------------------------+
  17 */
  18 
  19 #ifdef HAVE_CONFIG_H
  20 #include "config.h"
  21 #endif
  22 
  23 #include "php.h"
  24 #include "php_ini.h"
  25 #include "ext/standard/info.h"
  26 #include "pdo/php_pdo.h"
  27 #include "pdo/php_pdo_driver.h"
  28 #include "php_pdo_firebird.h"
  29 #include "php_pdo_firebird_int.h"
  30 
  31 #include <time.h>
  32 
  33 #define RECORD_ERROR(stmt) _firebird_error(NULL, stmt,  __FILE__, __LINE__)
  34 
  35 /* free the allocated space for passing field values to the db and back */
  36 static void free_sqlda(XSQLDA const *sqlda) /* {{{ */
  37 {
  38         int i;
  39 
  40         for (i = 0; i < sqlda->sqld; ++i) {
  41                 XSQLVAR const *var = &sqlda->sqlvar[i];
  42 
  43                 if (var->sqlind) {
  44                         efree(var->sqlind);
  45                 }
  46         }
  47 }
  48 /* }}} */
  49 
  50 /* called by PDO to clean up a statement handle */
  51 static int firebird_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
  52 {
  53         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  54         int result = 1, i;
  55 
  56         /* release the statement */
  57         if (isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_drop)) {
  58                 RECORD_ERROR(stmt);
  59                 result = 0;
  60         }
  61 
  62         /* clean up the fetch buffers if they have been used */
  63         for (i = 0; i < S->out_sqlda.sqld; ++i) {
  64                 if (S->fetch_buf[i]) {
  65                         efree(S->fetch_buf[i]);
  66                 }
  67         }
  68         efree(S->fetch_buf);
  69 
  70         zend_hash_destroy(S->named_params);
  71         FREE_HASHTABLE(S->named_params);
  72 
  73         /* clean up the input descriptor */
  74         if (S->in_sqlda) {
  75                 free_sqlda(S->in_sqlda);
  76                 efree(S->in_sqlda);
  77         }
  78 
  79         free_sqlda(&S->out_sqlda);
  80         efree(S);
  81 
  82         return result;
  83 }
  84 /* }}} */
  85 
  86 /* called by PDO to execute a prepared query */
  87 static int firebird_stmt_execute(pdo_stmt_t *stmt) /* {{{ */
  88 {
  89         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
  90         pdo_firebird_db_handle *H = S->H;
  91         zend_ulong affected_rows = 0;
  92         static char info_count[] = {isc_info_sql_records};
  93         char result[64];
  94 
  95         do {
  96                 /* named or open cursors should be closed first */
  97                 if ((*S->name || S->cursor_open) && isc_dsql_free_statement(H->isc_status, &S->stmt, DSQL_close)) {
  98                         break;
  99                 }
 100                 S->cursor_open = 0;
 101                 /* assume all params have been bound */
 102 
 103                 if (isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION, S->in_sqlda)) {
 104                         break;
 105                 }
 106 
 107                 /* Determine how many rows have changed. In this case we are
 108                  * only interested in rows changed, not rows retrieved. That
 109                  * should be handled by the client when fetching. */
 110                 stmt->row_count = affected_rows;
 111 
 112                 switch (S->statement_type) {
 113                         case isc_info_sql_stmt_insert:
 114                         case isc_info_sql_stmt_update:
 115                         case isc_info_sql_stmt_delete:
 116                         case isc_info_sql_stmt_exec_procedure:
 117                                 if (isc_dsql_sql_info(H->isc_status, &S->stmt, sizeof ( info_count),
 118                                         info_count, sizeof(result), result)) {
 119                                         break;
 120                                 }
 121                                 if (result[0] == isc_info_sql_records) {
 122                                         unsigned i = 3, result_size = isc_vax_integer(&result[1], 2);
 123                                         while (result[i] != isc_info_end && i < result_size) {
 124                                                 short len = (short) isc_vax_integer(&result[i + 1], 2);
 125                                                 if (result[i] != isc_info_req_select_count) {
 126                                                         affected_rows += isc_vax_integer(&result[i + 3], len);
 127                                                 }
 128                                                 i += len + 3;
 129                                         }
 130                                         stmt->row_count = affected_rows;
 131                                 }
 132                         default:
 133                                 ;
 134                 }
 135 
 136                 /* commit? */
 137                 if (stmt->dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
 138                         break;
 139                 }
 140 
 141                 *S->name = 0;
 142                 S->cursor_open = (S->out_sqlda.sqln > 0);       /* A cursor is opened, when more than zero columns returned */
 143                 S->exhausted = !S->cursor_open;
 144 
 145                 return 1;
 146         } while (0);
 147 
 148         RECORD_ERROR(stmt);
 149 
 150         return 0;
 151 }
 152 /* }}} */
 153 
 154 /* called by PDO to fetch the next row from a statement */
 155 static int firebird_stmt_fetch(pdo_stmt_t *stmt, /* {{{ */
 156         enum pdo_fetch_orientation ori, zend_long offset)
 157 {
 158         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 159         pdo_firebird_db_handle *H = S->H;
 160 
 161         if (!stmt->executed) {
 162                 strcpy(stmt->error_code, "HY000");
 163                 H->last_app_error = "Cannot fetch from a closed cursor";
 164         } else if (!S->exhausted) {
 165                 if (isc_dsql_fetch(H->isc_status, &S->stmt, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
 166                         if (H->isc_status[0] && H->isc_status[1]) {
 167                                 RECORD_ERROR(stmt);
 168                         }
 169                         S->exhausted = 1;
 170                         return 0;
 171                 }
 172                 if (S->statement_type == isc_info_sql_stmt_exec_procedure) {
 173                         S->exhausted = 1;
 174                 }
 175                 stmt->row_count++;
 176                 return 1;
 177         }
 178         return 0;
 179 }
 180 /* }}} */
 181 
 182 /* called by PDO to retrieve information about the fields being returned */
 183 static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno) /* {{{ */
 184 {
 185         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 186         struct pdo_column_data *col = &stmt->columns[colno];
 187         XSQLVAR *var = &S->out_sqlda.sqlvar[colno];
 188         int colname_len;
 189         char *cp;
 190 
 191         /* allocate storage for the column */
 192         var->sqlind = (void*)ecalloc(1, var->sqllen + 2*sizeof(short));
 193         var->sqldata = &((char*)var->sqlind)[sizeof(short)];
 194 
 195         colname_len = (S->H->fetch_table_names && var->relname_length)
 196                                         ? (var->aliasname_length + var->relname_length + 1)
 197                                         : (var->aliasname_length);
 198         col->precision = -var->sqlscale;
 199         col->maxlen = var->sqllen;
 200         col->name = zend_string_alloc(colname_len, 0);
 201         cp = ZSTR_VAL(col->name);
 202         if (colname_len > var->aliasname_length) {
 203                 memmove(cp, var->relname, var->relname_length);
 204                 cp += var->relname_length;
 205                 *cp++ = '.';
 206         }
 207         memmove(cp, var->aliasname, var->aliasname_length);
 208         *(cp+var->aliasname_length) = '\0';
 209         col->param_type = PDO_PARAM_STR;
 210 
 211         return 1;
 212 }
 213 /* }}} */
 214 
 215 #define FETCH_BUF(buf,type,len,lenvar) ((buf) = (buf) ? (buf) : \
 216         emalloc((len) ? (len * sizeof(type)) : ((*(unsigned long*)lenvar) = sizeof(type))))
 217 
 218 #define CHAR_BUF_LEN 24
 219 
 220 /* fetch a blob into a fetch buffer */
 221 static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */
 222         zend_ulong *len, ISC_QUAD *blob_id)
 223 {
 224         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 225         pdo_firebird_db_handle *H = S->H;
 226         isc_blob_handle blobh = NULL;
 227         char const bl_item = isc_info_blob_total_length;
 228         char bl_info[20];
 229         unsigned short i;
 230         int result = *len = 0;
 231 
 232         if (isc_open_blob(H->isc_status, &H->db, &H->tr, &blobh, blob_id)) {
 233                 RECORD_ERROR(stmt);
 234                 return 0;
 235         }
 236 
 237         if (isc_blob_info(H->isc_status, &blobh, 1, const_cast(&bl_item),
 238                         sizeof(bl_info), bl_info)) {
 239                 RECORD_ERROR(stmt);
 240                 goto fetch_blob_end;
 241         }
 242 
 243         /* find total length of blob's data */
 244         for (i = 0; i < sizeof(bl_info); ) {
 245                 unsigned short item_len;
 246                 char item = bl_info[i++];
 247 
 248                 if (item == isc_info_end || item == isc_info_truncated || item == isc_info_error
 249                                 || i >= sizeof(bl_info)) {
 250                         H->last_app_error = "Couldn't determine BLOB size";
 251                         goto fetch_blob_end;
 252                 }
 253 
 254                 item_len = (unsigned short) isc_vax_integer(&bl_info[i], 2);
 255 
 256                 if (item == isc_info_blob_total_length) {
 257                         *len = isc_vax_integer(&bl_info[i+2], item_len);
 258                         break;
 259                 }
 260                 i += item_len+2;
 261         }
 262 
 263         /* we've found the blob's length, now fetch! */
 264 
 265         if (*len) {
 266                 zend_ulong cur_len;
 267                 unsigned short seg_len;
 268                 ISC_STATUS stat;
 269 
 270                 *ptr = S->fetch_buf[colno] = erealloc(*ptr, *len+1);
 271 
 272                 for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) {
 273 
 274                         unsigned short chunk_size = (*len-cur_len) > USHRT_MAX ? USHRT_MAX
 275                                 : (unsigned short)(*len-cur_len);
 276 
 277                         stat = isc_get_segment(H->isc_status, &blobh, &seg_len, chunk_size, &(*ptr)[cur_len]);
 278                 }
 279 
 280                 (*ptr)[*len++] = '\0';
 281 
 282                 if (H->isc_status[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) {
 283                         H->last_app_error = "Error reading from BLOB";
 284                         goto fetch_blob_end;
 285                 }
 286         }
 287         result = 1;
 288 
 289 fetch_blob_end:
 290         if (isc_close_blob(H->isc_status, &blobh)) {
 291                 RECORD_ERROR(stmt);
 292                 return 0;
 293         }
 294         return result;
 295 }
 296 /* }}} */
 297 
 298 static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,  /* {{{ */
 299         zend_ulong *len, int *caller_frees)
 300 {
 301         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 302         XSQLVAR const *var = &S->out_sqlda.sqlvar[colno];
 303 
 304         if (*var->sqlind == -1) {
 305                 /* A NULL value */
 306                 *ptr = NULL;
 307                 *len = 0;
 308         } else {
 309                 if (var->sqlscale < 0) {
 310                         static ISC_INT64 const scales[] = { 1, 10, 100, 1000,
 311                                 10000,
 312                                 100000,
 313                                 1000000,
 314                                 10000000,
 315                                 100000000,
 316                                 1000000000,
 317                                 LL_LIT(10000000000),
 318                                 LL_LIT(100000000000),
 319                                 LL_LIT(1000000000000),
 320                                 LL_LIT(10000000000000),
 321                                 LL_LIT(100000000000000),
 322                                 LL_LIT(1000000000000000),
 323                                 LL_LIT(10000000000000000),
 324                                 LL_LIT(100000000000000000),
 325                                 LL_LIT(1000000000000000000)
 326                         };
 327                         ISC_INT64 n, f = scales[-var->sqlscale];
 328 
 329                         switch (var->sqltype & ~1) {
 330                                 case SQL_SHORT:
 331                                         n = *(short*)var->sqldata;
 332                                         break;
 333                                 case SQL_LONG:
 334                                         n = *(ISC_LONG*)var->sqldata;
 335                                         break;
 336                                 case SQL_INT64:
 337                                         n = *(ISC_INT64*)var->sqldata;
 338                         }
 339 
 340                         *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
 341 
 342                         if (n >= 0) {
 343                                 *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
 344                                         n / f, -var->sqlscale, n % f);
 345                         } else if (n <= -f) {
 346                                 *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
 347                                         n / f, -var->sqlscale, -n % f);
 348                          } else {
 349                                 *len = slprintf(*ptr, CHAR_BUF_LEN, "-0.%0*" LL_MASK "d", -var->sqlscale, -n % f);
 350                         }
 351                 } else {
 352                         switch (var->sqltype & ~1) {
 353                                 struct tm t;
 354                                 char *fmt;
 355 
 356                                 case SQL_VARYING:
 357                                         *ptr = &var->sqldata[2];
 358                                         *len = *(short*)var->sqldata;
 359                                         break;
 360                                 case SQL_TEXT:
 361                                         *ptr = var->sqldata;
 362                                         *len = var->sqllen;
 363                                         break;
 364                                 case SQL_SHORT:
 365                                     *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
 366                                         *len = slprintf(*ptr, CHAR_BUF_LEN, "%d", *(short*)var->sqldata);
 367                                         break;
 368                                 case SQL_LONG:
 369                                         *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
 370                                         *len = slprintf(*ptr, CHAR_BUF_LEN, "%d", *(ISC_LONG*)var->sqldata);
 371                                         break;
 372                                 case SQL_INT64:
 373                                         *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
 374                                         *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata);
 375                                         break;
 376                                 case SQL_FLOAT:
 377                                         *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
 378                                         *len = slprintf(*ptr, CHAR_BUF_LEN, "%F", *(float*)var->sqldata);
 379                                         break;
 380                                 case SQL_DOUBLE:
 381                                         *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
 382                                         *len = slprintf(*ptr, CHAR_BUF_LEN, "%F" , *(double*)var->sqldata);
 383                                         break;
 384                                 case SQL_TYPE_DATE:
 385                                         isc_decode_sql_date((ISC_DATE*)var->sqldata, &t);
 386                                         fmt = S->H->date_format ? S->H->date_format : PDO_FB_DEF_DATE_FMT;
 387                                         if (0) {
 388                                 case SQL_TYPE_TIME:
 389                                                 isc_decode_sql_time((ISC_TIME*)var->sqldata, &t);
 390                                                 fmt = S->H->time_format ? S->H->time_format : PDO_FB_DEF_TIME_FMT;
 391                                         } else if (0) {
 392                                 case SQL_TIMESTAMP:
 393                                                 isc_decode_timestamp((ISC_TIMESTAMP*)var->sqldata, &t);
 394                                                 fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT;
 395                                         }
 396                                         /* convert the timestamp into a string */
 397                                         *len = 80;
 398                                         *ptr = FETCH_BUF(S->fetch_buf[colno], char, *len, NULL);
 399                                         *len = strftime(*ptr, *len, fmt, &t);
 400                                         break;
 401                                 case SQL_BLOB:
 402                                         return firebird_fetch_blob(stmt,colno,ptr,len,
 403                                                 (ISC_QUAD*)var->sqldata);
 404                         }
 405                 }
 406         }
 407         return 1;
 408 }
 409 /* }}} */
 410 
 411 static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param)
 412 {
 413         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 414         pdo_firebird_db_handle *H = S->H;
 415         isc_blob_handle h = NULL;
 416         zend_ulong put_cnt = 0, rem_cnt;
 417         unsigned short chunk_size;
 418         int result = 1;
 419 
 420         if (isc_create_blob(H->isc_status, &H->db, &H->tr, &h, blob_id)) {
 421                 RECORD_ERROR(stmt);
 422                 return 0;
 423         }
 424 
 425         SEPARATE_ZVAL(param);
 426         convert_to_string_ex(param);
 427 
 428         for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size)  {
 429 
 430                 chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;
 431 
 432                 if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL_P(param)[put_cnt])) {
 433                         RECORD_ERROR(stmt);
 434                         result = 0;
 435                         break;
 436                 }
 437                 put_cnt += chunk_size;
 438         }
 439 
 440         zval_dtor(param);
 441 
 442         if (isc_close_blob(H->isc_status, &h)) {
 443                 RECORD_ERROR(stmt);
 444                 return 0;
 445         }
 446         return result;
 447 }
 448 
 449 static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, /* {{{ */
 450         enum pdo_param_event event_type)
 451 {
 452         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 453         XSQLDA *sqlda = param->is_param ? S->in_sqlda : &S->out_sqlda;
 454         XSQLVAR *var;
 455 
 456         if (event_type == PDO_PARAM_EVT_FREE) { /* not used */
 457                 return 1;
 458         }
 459 
 460         if (!sqlda || param->paramno >= sqlda->sqld) {
 461                 strcpy(stmt->error_code, "HY093");
 462                 S->H->last_app_error = "Invalid parameter index";
 463                 return 0;
 464         }
 465         if (param->is_param && param->paramno == -1) {
 466                 zval *index;
 467 
 468                 /* try to determine the index by looking in the named_params hash */
 469                 if ((index = zend_hash_find(S->named_params, param->name)) != NULL) {
 470                         param->paramno = Z_LVAL_P(index);
 471                 } else {
 472                         /* ... or by looking in the input descriptor */
 473                         int i;
 474 
 475                         for (i = 0; i < sqlda->sqld; ++i) {
 476                                 XSQLVAR *var = &sqlda->sqlvar[i];
 477 
 478                                 if ((var->aliasname_length && !strncasecmp(ZSTR_VAL(param->name), var->aliasname,
 479                                                 min(ZSTR_LEN(param->name), var->aliasname_length)))
 480                                                 || (var->sqlname_length && !strncasecmp(ZSTR_VAL(param->name), var->sqlname,
 481                                                 min(ZSTR_LEN(param->name), var->sqlname_length)))) {
 482                                         param->paramno = i;
 483                                         break;
 484                                 }
 485                         }
 486                         if (i >= sqlda->sqld) {
 487                                 strcpy(stmt->error_code, "HY093");
 488                                 S->H->last_app_error = "Invalid parameter name";
 489                                 return 0;
 490                         }
 491                 }
 492         }
 493 
 494         var = &sqlda->sqlvar[param->paramno];
 495 
 496         switch (event_type) {
 497                 char *value;
 498                 zend_ulong value_len;
 499                 int caller_frees;
 500                 zval *parameter;
 501 
 502                 case PDO_PARAM_EVT_ALLOC:
 503                         if (param->is_param) {
 504                                 /* allocate the parameter */
 505                                 if (var->sqlind) {
 506                                         efree(var->sqlind);
 507                                 }
 508                                 var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short));
 509                                 var->sqldata = &((char*)var->sqlind)[sizeof(short)];
 510                         }
 511                         break;
 512 
 513                 case PDO_PARAM_EVT_EXEC_PRE:
 514                         if (!param->is_param) {
 515                                 break;
 516                         }
 517 
 518                         *var->sqlind = 0;
 519                         if (Z_ISREF(param->parameter)) {
 520                                 parameter = Z_REFVAL(param->parameter);
 521                         } else {
 522                                 parameter = &param->parameter;
 523                         }
 524 
 525                         if (Z_TYPE_P(parameter) == IS_RESOURCE) {
 526                                 php_stream *stm = NULL;
 527 
 528                                 php_stream_from_zval_no_verify(stm, parameter);
 529                                 if (stm) {
 530                                         zend_string *mem =  php_stream_copy_to_mem(stm, PHP_STREAM_COPY_ALL, 0);
 531                                         zval_ptr_dtor(parameter);
 532                                         ZVAL_STR(parameter, mem ? mem : ZSTR_EMPTY_ALLOC());
 533                                 } else {
 534                                         pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource");
 535                                         return 0;
 536                                 }
 537                         }
 538 
 539                         switch (var->sqltype & ~1) {
 540                                 case SQL_ARRAY:
 541                                         strcpy(stmt->error_code, "HY000");
 542                                         S->H->last_app_error = "Cannot bind to array field";
 543                                         return 0;
 544 
 545                                 case SQL_BLOB:
 546                                         return firebird_bind_blob(stmt, (ISC_QUAD*)var->sqldata, parameter);
 547                         }
 548 
 549                         /* check if a NULL should be inserted */
 550                         switch (Z_TYPE_P(parameter)) {
 551                                 int force_null;
 552 
 553                                 case IS_LONG:
 554                                         /* keep the allow-NULL flag */
 555                                         var->sqltype = (sizeof(zend_long) == 8 ? SQL_INT64 : SQL_LONG) | (var->sqltype & 1);
 556                                         var->sqldata = (void*)&Z_LVAL_P(parameter);
 557                                         var->sqllen = sizeof(zend_long);
 558                                         break;
 559                                 case IS_DOUBLE:
 560                                         /* keep the allow-NULL flag */
 561                                         var->sqltype = SQL_DOUBLE | (var->sqltype & 1);
 562                                         var->sqldata = (void*)&Z_DVAL_P(parameter);
 563                                         var->sqllen = sizeof(double);
 564                                         break;
 565                                 case IS_STRING:
 566                                         force_null = 0;
 567 
 568                                         /* for these types, an empty string can be handled like a NULL value */
 569                                         switch (var->sqltype & ~1) {
 570                                                 case SQL_SHORT:
 571                                                 case SQL_LONG:
 572                                                 case SQL_INT64:
 573                                                 case SQL_FLOAT:
 574                                                 case SQL_DOUBLE:
 575                                                 case SQL_TIMESTAMP:
 576                                                 case SQL_TYPE_DATE:
 577                                                 case SQL_TYPE_TIME:
 578                                                         force_null = (Z_STRLEN_P(parameter) == 0);
 579                                         }
 580                                         if (!force_null) {
 581                                                 /* keep the allow-NULL flag */
 582                                                 var->sqltype = SQL_TEXT | (var->sqltype & 1);
 583                                                 var->sqldata = Z_STRVAL_P(parameter);
 584                                                 var->sqllen      = Z_STRLEN_P(parameter);
 585                                                 break;
 586                                         }
 587                                 case IS_NULL:
 588                                         /* complain if this field doesn't allow NULL values */
 589                                         if (~var->sqltype & 1) {
 590                                                 strcpy(stmt->error_code, "HY105");
 591                                                 S->H->last_app_error = "Parameter requires non-null value";
 592                                                 return 0;
 593                                         }
 594                                         *var->sqlind = -1;
 595                                         break;
 596                                 default:
 597                                         strcpy(stmt->error_code, "HY105");
 598                                         S->H->last_app_error = "Binding arrays/objects is not supported";
 599                                         return 0;
 600                         }
 601                         break;
 602 
 603                 case PDO_PARAM_EVT_FETCH_POST:
 604                         if (param->paramno == -1) {
 605                             return 0;
 606                         }
 607                         if (param->is_param) {
 608                                 break;
 609                         }
 610                         value = NULL;
 611                         value_len = 0;
 612                         caller_frees = 0;
 613                         if (Z_ISREF(param->parameter)) {
 614                                 parameter = Z_REFVAL(param->parameter);
 615                         } else {
 616                                 parameter = &param->parameter;
 617                         }
 618                         zval_ptr_dtor(parameter);
 619                         ZVAL_NULL(parameter);
 620 
 621                         if (firebird_stmt_get_col(stmt, param->paramno, &value, &value_len, &caller_frees)) {
 622                                 switch (PDO_PARAM_TYPE(param->param_type)) {
 623                                         case PDO_PARAM_STR:
 624                                                 if (value) {
 625                                                         ZVAL_STRINGL(parameter, value, value_len);
 626                                                         break;
 627                                                 }
 628                                         case PDO_PARAM_INT:
 629                                                 if (value) {
 630                                                         ZVAL_LONG(parameter, *(zend_long*)value);
 631                                                         break;
 632                                                 }
 633                                         case PDO_PARAM_EVT_NORMALIZE:
 634                                                          if (!param->is_param) {
 635                                                                   char *s = ZSTR_VAL(param->name);
 636                                                                   while (*s != '\0') {
 637                                                                            *s = toupper(*s);
 638                                                                                 s++;
 639                                                                   }
 640                                                          }
 641                                                 break;
 642                                         default:
 643                                                 ZVAL_NULL(parameter);
 644                                 }
 645                                 if (value && caller_frees) {
 646                                         efree(value);
 647                                 }
 648                                 return 1;
 649                         }
 650                         return 0;
 651                 default:
 652                         ;
 653         }
 654         return 1;
 655 }
 656 /* }}} */
 657 
 658 static int firebird_stmt_set_attribute(pdo_stmt_t *stmt, zend_long attr, zval *val) /* {{{ */
 659 {
 660         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 661 
 662         switch (attr) {
 663                 default:
 664                         return 0;
 665                 case PDO_ATTR_CURSOR_NAME:
 666                         convert_to_string(val);
 667 
 668                         if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, Z_STRVAL_P(val),0)) {
 669                                 RECORD_ERROR(stmt);
 670                                 return 0;
 671                         }
 672                         strlcpy(S->name, Z_STRVAL_P(val), sizeof(S->name));
 673                         break;
 674         }
 675         return 1;
 676 }
 677 /* }}} */
 678 
 679 static int firebird_stmt_get_attribute(pdo_stmt_t *stmt, zend_long attr, zval *val) /* {{{ */
 680 {
 681         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 682 
 683         switch (attr) {
 684                 default:
 685                         return 0;
 686                 case PDO_ATTR_CURSOR_NAME:
 687                         if (*S->name) {
 688                                 ZVAL_STRING(val, S->name);
 689                         } else {
 690                                 ZVAL_NULL(val);
 691                         }
 692                         break;
 693         }
 694         return 1;
 695 }
 696 /* }}} */
 697 
 698 static int firebird_stmt_cursor_closer(pdo_stmt_t *stmt) /* {{{ */
 699 {
 700         pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
 701 
 702         /* close the statement handle */
 703         if ((*S->name || S->cursor_open) && isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_close)) {
 704                 RECORD_ERROR(stmt);
 705                 return 0;
 706         }
 707         *S->name = 0;
 708         S->cursor_open = 0;
 709         return 1;
 710 }
 711 /* }}} */
 712 
 713 
 714 struct pdo_stmt_methods firebird_stmt_methods = { /* {{{ */
 715         firebird_stmt_dtor,
 716         firebird_stmt_execute,
 717         firebird_stmt_fetch,
 718         firebird_stmt_describe,
 719         firebird_stmt_get_col,
 720         firebird_stmt_param_hook,
 721         firebird_stmt_set_attribute,
 722         firebird_stmt_get_attribute,
 723         NULL, /* get_column_meta_func */
 724         NULL, /* next_rowset_func */
 725         firebird_stmt_cursor_closer
 726 };
 727 /* }}} */
 728 
 729 /*
 730  * Local variables:
 731  * tab-width: 4
 732  * c-basic-offset: 4
 733  * End:
 734  * vim600: noet sw=4 ts=4 fdm=marker
 735  * vim<600: noet sw=4 ts=4
 736  */

/* [<][>][^][v][top][bottom][index][help] */