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